Introduction
Hi, I'm miruky.
Searching an unstructured log message often means parsing text after the fact. AWS Lambda advanced logging controls can capture Python logging output as JSON, and CloudWatch Logs Insights can address structurally nested JSON fields with dot notation.
This Console walkthrough sends three distinct event bodies to one function. Each application record contains an order object with a nested customer tier; an Insights query for order.customer.tier = "gold" returns one row for each distinct gold order and excludes the standard order.
The exercise uses three short Lambda invocations, a one-day log group, and a narrowly scoped log query. Current Lambda and CloudWatch pricing terms are linked below.
1. Prepare the execution role and log group
Use the English AWS Console in United States (N. Virginia). Lambda, CloudWatch Logs, and every invocation remain in us-east-1; IAM itself is global.
The header confirms United States (N. Virginia) while the Lambda Console is in English. This fixes the Region for the function, log group, invocations, and query.
In IAM, search for exact role name miruky-ajojxevzcpsbmryk and confirm that it is absent. Do not open or modify a partial match.
The exact filter reports 0 matches and No matches for miruky-ajojxevzcpsbmryk. That empty result establishes the global IAM resource boundary before creation.
Create the role for the Lambda AWS service and attach AWSLambdaBasicExecutionRole.
The role's permissions table shows one attached AWS managed policy: AWSLambdaBasicExecutionRole. The role uses the Lambda service trust relationship. Screenshots omit account-specific identifiers.
Open CloudWatch Logs and confirm that miruky-dwjrjfrjsvxegfiu does not exist. In this run, the account had no log groups in us-east-1, so the list itself established the empty baseline without a name filter.
The page reports Log groups (0) and There are no log groups. This confirms that the generated name is available before creation. Create miruky-dwjrjfrjsvxegfiu and set Retention to 1 day, which is one of the supported retention periods.
The log-group row shows miruky-dwjrjfrjsvxegfiu with retention set to 1 day.
By default, Lambda creates /aws/lambda/<function-name> when a function is initially invoked. Selecting an existing custom log group before any invocation keeps the controlled records in the generated group instead. One-day retention also prevents this small validation log from persisting indefinitely.
2. Create a function with JSON logging
Open AWS Lambda. In this run, the Region had no functions, so the Console opened its getting-started page instead of a function list.
The empty onboarding state shows Create a function without any function rows. Use it to enter the generated name miruky-lkddcrnpcpqhkitg and choose the supported Python 3.14 runtime.
The form shows miruky-lkddcrnpcpqhkitg and Python 3.14.
Expand Additional settings, choose Custom execution role, and select miruky-ajojxevzcpsbmryk in the side panel.
The panel shows Configure custom execution role and selects miruky-ajojxevzcpsbmryk.
Open Monitoring and operations tools and edit Logging configuration. Select custom log group miruky-dwjrjfrjsvxegfiu, set Log format to JSON, and keep Application log level at INFO.
The logging configuration selects JSON, application level INFO, and only miruky-dwjrjfrjsvxegfiu as the CloudWatch log group. System fields will still exist, but the later query will not select them.
Changing the format affects new log entries, not entries already stored. This controlled group begins empty, so all application records used below share the intended JSON format.
3. Emit a nested object with Python logging
Replace the starter code with this function and choose Deploy:
import logging
logger = logging.getLogger()
def lambda_handler(event, context):
# Keep application dimensions structured for direct field-level queries.
logger.info(
"order routed",
extra={
"order": {
"ref": event["order_ref"],
"customer": {"tier": event["tier"]},
},
"route": event["route"],
},
)
return {"logged": True}
The editor shows the standard logging library, one logger.info call, an order object with nested customer and tier keys, and a separate route field inside extra.
The function relies on Lambda's INFO application filter instead of overriding the level in code, following the JSON-logging guidance for Python. With Lambda JSON logging enabled, the standard Python logger adds values supplied through extra to the JSON record alongside Lambda-managed fields such as timestamp, level, message, and request ID. The controlled query below verifies that order remains a nested object. The code does not print the entire incoming event.
4. Generate three controlled records
Use one Private Lambda test event named miruky-zpgwxaehrfxbobzs with the initial input:
{
"order_ref": "order-blue",
"tier": "gold",
"route": "priority"
}
Save the test event, invoke the function once, and confirm that the response is {"logged":true}.
The editor shows event name miruky-zpgwxaehrfxbobzs with the fixed order-blue, gold, and priority values.
Edit the same private test event, replace its body with the standard order, save, and invoke once:
{
"order_ref": "order-green",
"tier": "standard",
"route": "normal"
}
The same saved event name now carries order-green, tier standard, and route normal. Confirm that the invocation returns {"logged":true}. This record is the negative control for the query.
Edit the event one more time and invoke another gold order:
{
"order_ref": "order-violet",
"tier": "gold",
"route": "priority"
}
The final editor state uses order-violet, tier gold, and route priority under the same event name. Confirm that the invocation returns {"logged":true}. The log group should now contain all three distinct order_ref values.
The same test event supplies three inputs, each with a distinct order_ref value. A repeated click can create another record with the same reference, so the query below handles reruns explicitly.
5. Query the nested tier field
Open CloudWatch Logs Insights, select only miruky-dwjrjfrjsvxegfiu, and choose a time range that covers the three invocations. The active Logs Insights experience may represent the chosen group in its data-source control or in an account-specific generated SOURCE line. Leave a generated line in place and replace only the remaining query body with:
fields order.ref, order.customer.tier, route
| filter message = "order routed"
| filter order.customer.tier = "gold"
| sort @timestamp asc
| dedup order.ref
The selected data source limits the query to miruky-dwjrjfrjsvxegfiu. The query begins with fields to retain only the three application columns, while dot notation addresses the nested order.customer.tier value. After sorting, dedup order.ref keeps the earliest result for each distinct order reference. dedup is last because only limit may follow it in Logs Insights QL.
Run the query. The result should contain two rows: order-blue and order-violet, each with tier gold and route priority.
The result rows show order-blue and order-violet, each with tier gold and route priority. For a rerun, Showing 2 of N matched means that dedup reduced repeated gold records to two distinct references instead of hiding them with a narrower time window.
order-green should be absent because its nested tier is standard. The query selects only the three application fields; @message and @requestId are not needed to identify each order or its route.
Wrap-up
Lambda emitted structured application records through the Python logger's extra argument. CloudWatch Logs Insights evaluated the nested order.customer.tier value directly and kept only the two distinct gold-tier orders.
Structured logging moves useful dimensions out of ad hoc message parsing. A stable logging contract still matters; each investigation should limit its log groups, time range, and output columns.
Thanks for reading this far.
See you in the next one.
Disclosure: This article was written with AI assistance and independently verified against the linked primary sources and observed results.
References
- Configuring JSON and plain text log formats for Lambda
- Log-level filtering for Lambda
- Configuring CloudWatch log groups for Lambda
- Log and monitor Python Lambda functions
- Building Lambda functions with Python
- Testing Lambda functions in the Console
- AWSLambdaBasicExecutionRole managed policy
- Supported logs and discovered fields in CloudWatch Logs Insights
- CloudWatch Logs Insights query syntax
- CloudWatch Logs Insights fields command
- CloudWatch Logs Insights filter command
- CloudWatch Logs Insights sort command
- CloudWatch Logs Insights dedup command
- Analyzing log data with CloudWatch Logs Insights
- Working with log groups and log streams
- PutRetentionPolicy API
- AWS Lambda pricing
- Amazon CloudWatch pricing















Top comments (0)