Skip to content

Instantly share code, notes, and snippets.

@mneil
Last active February 3, 2023 16:06
Show Gist options
  • Save mneil/4f0dbe83e09df098f05ab5bd79068160 to your computer and use it in GitHub Desktop.
Save mneil/4f0dbe83e09df098f05ab5bd79068160 to your computer and use it in GitHub Desktop.
AWS Lambda Python Log Factory w/ Filter Secrets
'''
Place this file in your lambda package next to the handler file.
Setting the log formatter on lambda loses the request id out of the context.
But, you often want to use a logger across a few files and name them
or change the log format.
This factory will ensure that the lambda context id is available to any
log format you choose. It also has the ability to filter out strings
from the logs using a regular expression.
```
import logging
from . import log_factory
LOGGER = logging.getLogger(__name__)
def handler(event, context):
'''lambda handler'''
log_factory(context)
LOGGER.info('formatted logger with a secret password: %s', 'abcdefg')
# [INFO] 2020-12-11T22:47:37.043Z adfadfdsfasdf __init__.py formatted logger with a secret password: ****
```
'''
import os
import re
import sys
import uuid
import logging
def log_factory(context):
'''
Return a log formatter with the request id added
'''
old_factory = logging.getLogRecordFactory()
_id = str(uuid.uuid4())
def aws_request_id(*args, **kwargs):
record = old_factory(*args, **kwargs)
try:
record.aws_request_id = context.aws_request_id
except AttributeError:
# Request ID is unset. Use our own unique id
record.aws_request_id = _id
return record
logging.setLogRecordFactory(aws_request_id)
class Filter():
'''Filter hides information in logs'''
def __init__(self, formatter, patterns):
self.formatter = formatter
self.__patterns = patterns
def format(self, record):
'''format and filter our logs'''
msg = self.formatter.format(record)
for pattern in self.__patterns:
msg = pattern.sub('****', msg)
return msg
def __getattr__(self, attr):
return getattr(self.formatter, attr)
# Own format
FORMAT = "[%(levelname)s]\t%(asctime)s.%(msecs)dZ\t%(aws_request_id)s\t%(name)s\t%(message)s\n"
FILTERS = [
# Filter these strings / regex from logs automatically
re.compile(r'abcdefg'),
]
LOGGER = logging.getLogger()
for hander in LOGGER.handlers:
hander.setFormatter(Filter(logging.Formatter(FORMAT), FILTERS))
LOGGER.setLevel(os.getenv('LOG_LEVEL', 'INFO'))
logging.getLogger('boto3').setLevel(logging.ERROR)
logging.getLogger('botocore').setLevel(logging.ERROR)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment