Skip to content

Bug: Logging casing affects nested object properties #417

@sliedig

Description

@sliedig

Expected Behaviour

Logger should respect the casing of the of the object it logs, irrespective of the POWERTOOLS_LOGGER_CASE configuration. In the following example, the logging attribute logs the Amazon.Lambda.SQSEvents.SQSEvent. In this instance the POWERTOOLS_LOGGER_CASE setting is not defined and defaults to snake case (the current default setting, see docs).

    [Logging(LogEvent = true)]
    [Metrics(CaptureColdStart = true)]
    [Tracing(CaptureMode = TracingCaptureMode.ResponseAndError)]
    public async Task<string> FunctionHandler(SQSEvent sqsEvent, ILambdaContext context)
    {
        // implementation......
    }

The log output should be.

{
  "cold_start": true,
  "xray_trace_id": "1-64f2e834-b9df67f7a705145c59f8092f",
  "function_name": "uni-prop-local-contract-ContractEventHandlerFuncti-PSkd9CKrYlRh",
  "function_version": "$LATEST",
  "function_memory_size": 512,
  "function_arn": "arn:aws:lambda:ap-southeast-2:538510314095:function:uni-prop-local-contract-ContractEventHandlerFuncti-PSkd9CKrYlRh",
  "function_request_id": "12579e8a-9950-5bc2-bb7e-c3e67320b537",
  "timestamp": "2023-09-02T07:45:57.5637679Z",
  "level": "Information",
  "service": "unicorn.contracts",
  "name": "AWS.Lambda.Powertools.Logging.Logger",
  "message": {
    "Records": [
      {
        "MessageId": "17ac62a8-0ae4-4b7c-aeed-c602004a736b",
        "ReceiptHandle": "AQEB9CXbbsl59Im3MAetnLq7NAOSSFCCp/MHFdKf9Ft7u0OctJa6+PDbVSVDV6fdvbyPQ/P2wmXZADZ2W2D0HHId1jZp9xhfY+XDndOSdl5x6rX0g4Iqa4EL1VHP5OzpJoBZ+tZOGkO3cjorTv6LNCeEZlHNPGrIq7SMiATIV9qpirUj/Y3Grb92Hi+UDfk03zZ4B9FvSOXMUVtNnZBNr8BGgrLDHfZpfh1+4yp7Gu+I9uhLwZzlKo4jkx3NZX+LsRgE8Jpq61LUumSkbVWNujnD9WokOlx3GrqD7qNh7byvAfu++gesrNhhhX9Q7pCahcyUkKe0iRCuv+bSczMxD07mrscpRoMcb93DdtJh59jn8rFfuV4GYNSqYHEdVuoBZg6qbN2XF0EiK8EMXThB5UiUmKkMje0TLbGKYor/bP4kfK0=",
        "Body": "{\n\"address\": {\n\"country\": \"USA\",\n\"city\": \"Anytown\",\n\"street\": \"Main Street\",\n\"number\": 222\n},\n\"seller_name\": \"John Doe\",\n\"property_id\": \"usa/anytown/main-street/333\"\n}",
        "Md5OfBody": "95cf13afcccc87caed66de64b2c28f0b",
        "Md5OfMessageAttributes": "b51fb21666798a04bb45833ff6dc08ad",
        "EventSourceArn": "arn:aws:sqs:ap-southeast-2:538510314095:UnicornContractsIngestQueue-Local",
        "EventSource": "aws:sqs",
        "AwsRegion": "ap-southeast-2",
        "Attributes": {
          "ApproximateReceiveCount": "1",
          "AWSTraceHeader": "Root=1-64f2e929-78c8c8f13605d20d170afacd;Parent=3b94c8aa1aee62e6;Sampled=1",
          "SentTimestamp": "1693641001436",
          "SenderId": "AROAX2YNXJJX23OWVT6JY:BackplaneAssumeRoleSession",
          "ApproximateFirstReceiveTimestamp": "1693641001446"
        },
        "MessageAttributes": {
          "HttpMethod": {
            "StringValue": "POST",
            "BinaryValue": null,
            "StringListValues": [],
            "BinaryListValues": [],
            "DataType": "String"
          }
        }
      }
    ]
  },
  "sampling_rate": 0
}

Current Behaviour

By default, if you apply the above example, the output would look like this - everything snake case.

{
  "cold_start": true,
  "xray_trace_id": "1-64f2e834-b9df67f7a705145c59f8092f",
  "function_name": "uni-prop-local-contract-ContractEventHandlerFuncti-PSkd9CKrYlRh",
  "function_version": "$LATEST",
  "function_memory_size": 512,
  "function_arn": "arn:aws:lambda:ap-southeast-2:538510314095:function:uni-prop-local-contract-ContractEventHandlerFuncti-PSkd9CKrYlRh",
  "function_request_id": "12579e8a-9950-5bc2-bb7e-c3e67320b537",
  "timestamp": "2023-09-02T07:45:57.5637679Z",
  "level": "Information",
  "service": "unicorn.contracts",
  "name": "AWS.Lambda.Powertools.Logging.Logger",
  "message": {
    "records": [
      {
        "message_id": "4bdc3703-d801-41a6-8e1a-f2c066692bc7",
        "receipt_handle": "AQEBA6PRPusqsS9CPajNcTosKxsRPPvx70RnB/bQ2vjfjolv2zS5Icic3p2dVJLVig0GmKMg/fLb2piFe2GyJ/ylRFJIDho7r1as5DnQkIFhtpENDuBuNpMrVzw+1//xSJ2BFoNbh6RP50GB7hjcgyYuQ8zcrgceKHctrey9OG5bsyWrgzHFA1IUK9yS7mw1lSyOgizLPL4KScXv+sAeu0M8sZNihRpPR0Tv/8kRoaj40veVEllLcp9sbwt+A0RH+BIWBiLHl6yU51TqpRs99njCKUDXOnpiS9462Myz4mmOhzHRM4BkBY040+WZJ9mpLOaeOrlUFQDcCFw4AIz/HJqo3BpjAVW5UOHqq52dKCRvHmXgfC0IwgG//sepwz0+9etQffIaI9lnGdjQvQbCqdSYRGo80JY48uXZV1Te4MJETYI=",
        "body": "{\n\"address\": {\n\"country\": \"USA\",\n\"city\": \"Anytown\",\n\"street\": \"Main Street\",\n\"number\": 222\n},\n\"seller_name\": \"John Doe\",\n\"property_id\": \"usa/anytown/main-street/333\"\n}",
        "md5_of_body": "95cf13afcccc87caed66de64b2c28f0b",
        "md5_of_message_attributes": "b51fb21666798a04bb45833ff6dc08ad",
        "event_source_arn": "arn:aws:sqs:ap-southeast-2:538510314095:UnicornContractsIngestQueue-Local",
        "event_source": "aws:sqs",
        "aws_region": "ap-southeast-2",
        "attributes": {
          "approximate_receive_count": "1",
          "a_w_s_trace_header": "Root=1-64f2e834-3c0e93736f6ba2b20d753ed1;Parent=71052d679694decd;Sampled=1",
          "sent_timestamp": "1693640756520",
          "sender_id": "AROAX2YNXJJX23OWVT6JY:BackplaneAssumeRoleSession",
          "approximate_first_receive_timestamp": "1693640756527"
        },
        "message_attributes": {
          "http_method": {
            "string_value": "POST",
            "binary_value": null,
            "string_list_values": [],
            "binary_list_values": [],
            "data_type": "String"
          }
        }
      }
    ]
  },
  "sampling_rate": 0
}

Similarly, if you define POWERTOOLS_LOGGER_CASE as camel case, you get:

{
  "coldStart": true,
  "xrayTraceId": "1-64f300a1-3c412c94f3f0f78886a83a0a",
  "functionName": "uni-prop-local-contract-ContractEventHandlerFuncti-PSkd9CKrYlRh",
  "functionVersion": "$LATEST",
  "functionMemorySize": 512,
  "functionArn": "arn:aws:lambda:ap-southeast-2:538510314095:function:uni-prop-local-contract-ContractEventHandlerFuncti-PSkd9CKrYlRh",
  "functionRequestId": "a11d70c2-4eb7-5dec-a145-2daf4c6d124a",
  "timestamp": "2023-09-02T09:30:10.1436179Z",
  "level": "Information",
  "service": "unicorn.contracts",
  "name": "AWS.Lambda.Powertools.Logging.Logger",
  "message": {
    "records": [
      {
        "messageId": "856aa859-d1c7-4121-b408-30a2d9abff10",
        "receiptHandle": "AQEBCR9KN558uxQYXnPjSsOR4fRcPCXSNDXX3l3cMLw+UrG9sFg0LzfYq6shPAXQUkEfRIJjiR7tSyx7psLKINdqaUxACBbJXnSKu7OfH7EsAxq7K2cZ0FN8LBnR6HvQeWxwcR7YSnS8OSaeI3P5D5Q6DwTq6MSxnS4DyG/8WODa4oBsLBfUz9hWLNVFf7aQqE1yXhltpNr2HVKkRRnchivfviYjDL7dMZoBYLuBAH+us+HI18v7PCRvJ7Fwlg4oeLLW6uQd7hREyMBSUVr9st//HSQM7CifsSAmroLqveCIrUEIgRcu0dsShPGwkj6bNrD5K0WYRczZSlkgCb9ZG6HeM0oBh5LQk2Ak+IhAD8urWVXbZruIojm7XMwbTXVI1AZOq/zVvczv9Qb4UB/d9OsiEETSr1Rg2sZoGQIK31Ibqn4=",
        "body": "{\n\"address\": {\n\"country\": \"USA\",\n\"city\": \"Anytown\",\n\"street\": \"Main Street\",\n\"number\": 222\n},\n\"seller_name\": \"John Doe\",\n\"property_id\": \"usa/anytown/main-street/333\"\n}",
        "md5OfBody": "95cf13afcccc87caed66de64b2c28f0b",
        "md5OfMessageAttributes": "b51fb21666798a04bb45833ff6dc08ad",
        "eventSourceArn": "arn:aws:sqs:ap-southeast-2:538510314095:UnicornContractsIngestQueue-Local",
        "eventSource": "aws:sqs",
        "awsRegion": "ap-southeast-2",
        "attributes": {
          "approximateReceiveCount": "1",
          "awsTraceHeader": "Root=1-64f300a0-75746f3e2832451e1720a3d7;Parent=20b56946b0a910a5;Sampled=1",
          "sentTimestamp": "1693647009037",
          "senderId": "AROAX2YNXJJX23OWVT6JY:BackplaneAssumeRoleSession",
          "approximateFirstReceiveTimestamp": "1693647009046"
        },
        "messageAttributes": {
          "httpMethod": {
            "stringValue": "POST",
            "binaryValue": null,
            "stringListValues": [],
            "binaryListValues": [],
            "dataType": "String"
          }
        }
      }
    ]
  },
  "samplingRate": 0
}

In both cases, this is a misrepresentation of the definition of the SQSEvent class.

Code snippet

Already provide above

Possible Solution

Two recommendations:

  1. Do not apply key casing conventions to nested objects. Keep the property definition of the original object. Apply casing configuration to top-level keys only. This includes all extra keys, but not the values of the extra keys.

  2. Make Pascal case the default casing for all keys. This is the default casing for .NET and should be an opt-out if users want something different, rather than it being an opt in.

Steps to Reproduce

Do nothing. Or change the POWERTOOLS_LOGGER_CASE to CamelCase

Powertools for AWS Lambda (.NET) version

latest

AWS Lambda function runtime

dotnet6

Debugging logs

No response

Metadata

Metadata

Assignees

Labels

area/loggingCore logging utilitynot-a-bugNew and existing bug reports incorrectly submitted as bugreleasedFix or implementation already in main and releasedv2v2 release

Type

No type

Projects

Status

✅ Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions