feat(logging): Structured scope support for Lambda JSON log format in Amazon.Lambda.Logging.AspNetCore - #2530
feat(logging): Structured scope support for Lambda JSON log format in Amazon.Lambda.Logging.AspNetCore#2530Lanayx wants to merge 7 commits into
Conversation
When AWS_LAMBDA_LOG_FORMAT=JSON and IncludeScopes=true, scope state objects
implementing IEnumerable<KeyValuePair<string, object>> have their key/value
entries appended to the message template (as {key} placeholders) and the
parameters array, so they are emitted as named JSON properties by the Lambda
JSON formatter.
Non-structured scopes are silently ignored. Existing behavior (scopes disabled,
text-format logging, no scopes) is unchanged.
Closes aws#2122
Co-authored-by: Lanayx <3329606+Lanayx@users.noreply.github.com>
…port feat(logging): Structured scope support for Lambda JSON log format in Amazon.Lambda.Logging.AspNetCore
GarrettBeatty
left a comment
There was a problem hiding this comment.
Thanks for the contribution! A few findings from an adversarial pass over the diff (head 1347570). Verdict: 4 findings (no blocking, but a couple worth addressing before merge).
1. [major] Unsanitized scope keys injected as template placeholders — LambdaILogger.cs, sb.Append($" {{{entry.Key}}}"). A scope key containing :, {, }, or whitespace is emitted verbatim into the message template (e.g. key "Order:Id" → {Order:Id}, where : is the MEL format separator; "a b" → {a b}). This can malform the placeholder token and mis-bind positional parameters. There is no key validation — consider skipping or sanitizing keys that aren't valid template property names.
2. [major] Scope / message-template key collision — LambdaILogger.cs, same append. A scope key equal to a message-template key (message {Name} + scope key Name) appends a duplicate {Name} placeholder bound to a different positional arg, producing ambiguous/duplicate JSON property emission. There's no collision handling.
3. [major] Missing AutoVer change file — .autover/changes/. LambdaILogger.cs is a shipped source change and .autover/autover.json is present, so repo convention requires a change-file entry (generated via the AutoVer CLI). This PR doesn't include one; it isn't test-only, so "Release Not Needed" doesn't apply.
4. [major – testing] No end-to-end JSON emission test — LoggingTests.cs, the 6 new [Fact]s. The test harness formats output as "{level}: {message}: parameter count: {N}" and never invokes the real Lambda JSON formatter, so the core behavior (positional placeholder → named JSON property binding, and null scope-value emission) is asserted only by parameter count, never by inspecting emitted JSON. A test that drives state+scopes through the real formatter and asserts the resulting JSON keys/values would close this gap.
…ver change file Co-authored-by: Lanayx <3329606+Lanayx@users.noreply.github.com>
Fix scope key sanitization, collisions, and add e2e JSON tests + auto…
…erge-conflicts # Conflicts: # Libraries/src/Amazon.Lambda.Logging.AspNetCore/LambdaILogger.cs Co-authored-by: Lanayx <3329606+Lanayx@users.noreply.github.com>
Merge upstream master to resolve mergeable_state=dirty on PR aws#2530
Scope properties were silently dropped when
AWS_LAMBDA_LOG_FORMAT=JSON. Addresses aws/aws-lambda-dotnet#2122. The final contribution should targetaws/aws-lambda-dotnet:master. Closes #2122.Changes
LambdaILogger.cs— In the JSON format path, whenIncludeScopes=true, iterates theScopeProviderand for each scope implementingIEnumerable<KeyValuePair<string, object>>, appends{key}placeholders to the message template and the corresponding values to the parameters array. This is necessary because the Lambda JSON formatter (RuntimeSupport) matches template placeholders positionally to args to emit named JSON properties — values without a matching placeholder are ignored. Non-structured scopes (plain strings etc.), null keys, and{OriginalFormat}entries are silently skipped. Non-JSON / scopes-disabled paths are unchanged.LoggingTests.cs— Six focused tests covering: single KV scope, nested scopes, scopes disabled, no-scope template preservation, null scope value, and non-structured scope.README.md— Documents structured scope behavior in Lambda JSON mode.Example
Scope properties are appended after message-template properties, so message positional args are unaffected. Nested scopes are collected in provider-enumeration order (outermost first).
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.