Last active
February 3, 2023 16:06
-
-
Save mneil/4f0dbe83e09df098f05ab5bd79068160 to your computer and use it in GitHub Desktop.
AWS Lambda Python Log Factory w/ Filter Secrets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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