I have small Python code executing in AWS lambda,
but Lambda puts the logs to CloudWatch Logs in a very inconvenient format:

I want to send those logs to ELK for visualization. Is there a way to put all Lambda iteration logs to one json file?
The preloaded LambdaLoggerHandler uses the standard class logging.Formatter.
Source: https://www.denialof.services/lambda/
Replace the formatter by a custom class that outputs to JSON.
Also the extra dict could contains additionnals values, extra['data'] avoids conflicts with others logrecord properties.
import logging
import json
class FormatterJSON(logging.Formatter):
def format(self, record):
record.message = record.getMessage()
if self.usesTime():
record.asctime = self.formatTime(record, self.datefmt)
j = {
'levelname': record.levelname,
'time': '%(asctime)s.%(msecs)dZ' % dict(asctime=record.asctime, msecs=record.msecs),
'aws_request_id': getattr(record, 'aws_request_id', '00000000-0000-0000-0000-000000000000'),
'message': record.message,
'module': record.module,
'extra_data': record.__dict__.get('data', {}),
}
return json.dumps(j)
logger = logging.getLogger()
logger.setLevel('INFO')
formatter = FormatterJSON(
'[%(levelname)s]\t%(asctime)s.%(msecs)dZ\t%(levelno)s\t%(message)s\n',
'%Y-%m-%dT%H:%M:%S'
)
# Replace the LambdaLoggerHandler formatter :
logger.handlers[0].setFormatter(formatter)
def lambda_handler(event, context):
my_input = {
'key1': 'value1',
'key2': 'value2'
}
logger.info('Process Info: %s', 'Hello', extra=dict(data=my_input))
However any stacktraces keeps render as usual.
Then CloudWatch gets this :
{
"levelname": "INFO",
"time": "2018-12-13T11:35:24.130Z",
"aws_request_id": "2e0f7055-fecb-11e8-8376-b77695872964",
"message": "Process Info: Hello",
"module": "lambda_function",
"extra_data": {
"key1": "value1",
"key2": "value2"
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With