Google App Engine‘s built in ereporter module (more details) is an unsung hero of monitoring and error reporting. App Engine’s admin console and Google Cloud’s developer console both have solid monitoring, graphs, and log browsers, but there isn’t much for aggregating and alerting on user-defined errors.
Enter ereporter. It handles uncaught (Python) exceptions, stores them in the datastore, aggregates them by exception and application version, and sends then in an email report. Perfect.
Everything can be improved, though, and ereporter is no exception. Here are a couple monkey patches I use in in Bridgy and other App Engine projects.
First, I deploy a lot, so I’d rather not separate exceptions by minor version. This rolls them all up together:
ereporter.ExceptionRecord.get_key_name = \ classmethod(lambda cls, signature, version, date=None: signature)
I also see some exceptions regularly that I don’t care about and are just noise. Here’s a more complicated monkey patch that hides them:
class BlacklistingHandler(ereporter.ExceptionRecordingHandler): """An ereporter handler that ignores exceptions in a blacklist.""" # Exception message prefixes to ignore BLACKLIST = ( 'ConnectionError: HTTPConnectionPool', 'ConnectionError: HTTPSConnectionPool', 'DeadlineExceededError: The API call taskqueue.BulkAdd() took too long', 'error: An error occured while connecting to the server: Unable to fetch URL:', 'HTTPError: 404 Client Error:', 'HttpError: <HttpError 500 when requesting', 'TransientError', ) def emit(self, record): if record and record.exc_info: type_and_msg = traceback.format_exception_only(*record.exc_info[:2])[-1] for prefix in self.BLACKLIST: if type_and_msg.startswith(prefix): return return super(BlacklistingHandler, self).emit(record) # Do this instead of ereporter.register_logger() logging.getLogger().addHandler(BlacklistingHandler())