{
  "$type": "site.standard.document",
  "canonicalUrl": "https://rednafi.com/python/logging-quirks-in-lambda-environment/",
  "description": "Configure Python logging for AWS Lambda's pre-configured handlers while maintaining compatibility with local development environments.",
  "path": "/python/logging-quirks-in-lambda-environment/",
  "publishedAt": "2022-10-20T00:00:00.000Z",
  "site": "at://did:plc:fgtm2c26vfcj74rfmeggbyqj/site.standard.publication/3mnl6f7ob462z",
  "tags": [
    "Python",
    "AWS",
    "Logging"
  ],
  "textContent": "At my workplace, while working on a [Lambda] function, I noticed that my Python logs weren't\nappearing on the corresponding [Cloudwatch] log dashboard. At first, I thought that the\nfunction wasn't picking up the correct log level from the environment variables. We were\nusing [Serverless framework] and GitLab CI to deploy the function, so my first line of\ninvestigation involved checking for missing environment variables in those config files.\n\nHowever, I quickly realized that the environment variables were being propagated to the\nLambda function as expected. So, the issue had to be coming from somewhere else. After\nperusing through some docs, I discovered from the source code of [Lambda Python Runtime\nInterface Client] that AWS Lambda Python runtime [pre-configures] a logging handler that\nmodifies the format of the log message, and also adds some metadata to the record if\navailable. What's not pre-configured though is the log level. This means that no matter the\ntype of log message you try to send, it won't print anything.\n\nAccording to the [Lambda function logging docs], to make your logging work in the Lambda\nenvironment, you'll only need to set the log level for the root logger like this:\n\nWhile this does make the log messages appear on the Cloudwatch dashboard, it doesn't work\nwhenever you'll need to introspect the logs in your local Python interpreter. If you execute\nthe above snippet locally, you won't see any log message on your console. That's because\nhere we're only setting the log level for the root logger and we haven't defined any\nhandler. To fix the local logging, you'll need to add a handler to the logger as and set the\nlog level on it as follows:\n\nIn the Lambda Python runtime, the root logger is already pre-configured to have modified\nhandlers. The snippet above first adds another handler to the logger and sets the log level.\nSo technically, the root logger will contain two handlers in the Lambda environment and\nprint every log message twice with different handlers. However, you won't see the duplicate\nmessages in your local environment since the local logger will have only the one handler\nthat we've defined. So, the logger will behave differently in the two environments; not\ngood.\n\n> Having multiple stream handlers on the root logger that send the message to the stdout\n> will print every log message twice.\n\nSo, this still doesn't do what we want. Besides, sometimes in the local environment, I just\nwant to use logging.basicConfig and start logging with minimal configuration. The goal\nhere is to configure the root logger in a way that doesn't conflict with Lambda's\npre-configured handlers and also works locally without any side effects. Here's what I've\nfound that works:\n\nThe above snippet first inspects whether the root logger contains any handlers and if it\ndoes then sets the log level for the root logger. Otherwise, it just configures the logger\nwith basicConfig for local development. This will print out the log messages both in the\nlocal and Lambda environment and won't suffer from any side effects like message\nduplication. It'll also make sure that the pre-configured formatting of the log message is\nkept intact.\n\nFurther reading\n\n- [Using Python logging with AWS Lambda]\n\n\n\n\n[lambda]:\n    https://aws.amazon.com/lambda/\n\n[cloudwatch]:\n    https://aws.amazon.com/cloudwatch/\n\n[serverless framework]:\n    https://www.serverless.com/\n\n[lambda python runtime interface client]:\n    https://github.com/aws/aws-lambda-python-runtime-interface-client\n\n[pre-configures]:\n    https://github.com/aws/aws-lambda-python-runtime-interface-client/blob/970e9c1d2613e0ce9c388547c76ac30992ad0e96/awslambdaric/bootstrap.py#L376-L385\n\n[lambda function logging docs]:\n    https://docs.aws.amazon.com/lambda/latest/dg/python-logging.html\n\n[using python logging with aws lambda]:\n    https://stackoverflow.com/questions/37703609/using-python-logging-with-aws-lambda",
  "title": "Python logging quirks in AWS Lambda environment"
}