Skip to content

Commit 3cc64ce

Browse files
committed
Filter out H2 shutdown errors
Workaround for #282.
1 parent 8dcf555 commit 3cc64ce

1 file changed

Lines changed: 33 additions & 2 deletions

File tree

‎yarrharr/application.py‎

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@
4141
from twisted.logger import FileLogObserver, Logger, LogLevel, globalLogPublisher
4242
from twisted.internet import defer
4343
from twisted.logger import formatEvent
44+
from twisted.logger import FilteringLogObserver, ILogFilterPredicate, PredicateResult
4445
from twisted.web.wsgi import WSGIResource
4546
from twisted.web.server import Site
4647
from twisted.web.static import File
4748
from twisted.web.resource import Resource, NoResource
4849
from twisted.internet.endpoints import serverFromString
4950
from twisted.python.filepath import FilePath
51+
from zope.interface import implementer
5052

5153
from . import __version__
5254
from .signals import schedule_changed
@@ -349,6 +351,32 @@ def formatForSystemd(event):
349351
return prefix + s.replace("\n", "\n" + prefix + " ") + "\n"
350352

351353

354+
@implementer(ILogFilterPredicate)
355+
def dropUnhandledHTTP2Shutdown(event):
356+
"""
357+
Suppress the log messages which result from an unhandled error in HTTP/2
358+
connection shutdown. See #282 and Twisted #9462.
359+
360+
This log message is relayed from the :mod:`twisted.python.log` so the
361+
fields are a little odd:
362+
363+
* ``'log_namespace'`` is ``'log_legacy'``, and there is a ``'system'``
364+
field with a value of ``'-'``.
365+
* ``'log_text'`` contains the actual log text, including a pre-formatted
366+
traceback.
367+
* ``'failure'`` used instead of ``'log_failure'``.
368+
"""
369+
if event.get('log_namespace') != 'log_legacy':
370+
return PredicateResult.maybe
371+
if event.get('log_level') != LogLevel.critical:
372+
return PredicateResult.maybe
373+
if 'failure' not in event or not event['failure'].check(AttributeError):
374+
return PredicateResult.maybe
375+
if event['log_text'].startswith('Unhandled Error') and "no attribute 'shutdown'" in event['log_text']:
376+
return PredicateResult.no
377+
return PredicateResult.maybe
378+
379+
352380
class TwistedLoggerLogHandler(logging.Handler):
353381
publisher = globalLogPublisher
354382

@@ -479,8 +507,11 @@ def run():
479507
logging._srcfile = None # Disable expensive collection of location information.
480508
root.setLevel(logging.DEBUG if settings.DEBUG else logging.INFO)
481509
root.addHandler(TwistedLoggerLogHandler())
482-
globalLogBeginner.beginLoggingTo([FileLogObserver(sys.stdout, formatForSystemd)],
483-
redirectStandardIO=False)
510+
observer = FilteringLogObserver(
511+
FileLogObserver(sys.stdout, formatForSystemd),
512+
[dropUnhandledHTTP2Shutdown],
513+
)
514+
globalLogBeginner.beginLoggingTo([observer], redirectStandardIO=False)
484515

485516
log.info("Yarrharr {version} starting", version=__version__)
486517

0 commit comments

Comments
 (0)