powertools-lambda-dotnet icon indicating copy to clipboard operation
powertools-lambda-dotnet copied to clipboard

Bug: Logging casing affects nested object properties

Open sliedig opened this issue 11 months ago • 2 comments

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

sliedig avatar Sep 02 '23 09:09 sliedig