Skip to content

Commit ccd882f

Browse files
committed
fix: ensures xray_trace_id is refreshed
1 parent 0356025 commit ccd882f

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

aws_lambda_powertools/logging/formatter.py

+12-9
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,28 @@ def __init__(self, **kwargs):
3030
# Set the default unserializable function, by default values will be cast as str.
3131
self.default_json_formatter = kwargs.pop("json_default", str)
3232
# Set the insertion order for the log messages
33-
self.format_dict = dict.fromkeys(
34-
kwargs.pop("log_record_order", ["level", "location", "message", "xray_trace_id", "timestamp"])
35-
)
33+
self.format_dict = dict.fromkeys(kwargs.pop("log_record_order", ["level", "location", "message", "timestamp"]))
3634
self.reserved_keys = ["timestamp", "level", "location"]
3735
# Set the date format used by `asctime`
3836
super(JsonFormatter, self).__init__(datefmt=kwargs.pop("datefmt", None))
3937

4038
self.format_dict.update(self._build_root_keys(**kwargs))
4139

42-
@staticmethod
43-
def _build_root_keys(**kwargs):
44-
xray_trace_id = os.getenv("_X_AMZN_TRACE_ID")
45-
trace_id = xray_trace_id.split(";")[0].replace("Root=", "") if xray_trace_id else None
46-
40+
def _build_root_keys(self, **kwargs):
4741
return {
4842
"level": "%(levelname)s",
4943
"location": "%(funcName)s:%(lineno)d",
50-
"xray_trace_id": trace_id,
5144
"timestamp": "%(asctime)s",
5245
**kwargs,
5346
}
5447

48+
@staticmethod
49+
def _get_latest_trace_id():
50+
xray_trace_id = os.getenv("_X_AMZN_TRACE_ID")
51+
trace_id = xray_trace_id.split(";")[0].replace("Root=", "") if xray_trace_id else None
52+
53+
return trace_id
54+
5555
def update_formatter(self, **kwargs):
5656
self.format_dict.update(kwargs)
5757

@@ -90,6 +90,9 @@ def format(self, record): # noqa: A003
9090
if record.exc_text:
9191
log_dict["exception"] = record.exc_text
9292

93+
# fetch latest X-Ray Trace ID, if any
94+
log_dict.update({"xray_trace_id": self._get_latest_trace_id()})
95+
9396
# Filter out top level key with values that are None
9497
log_dict = {k: v for k, v in log_dict.items() if v is not None}
9598

docs/content/core/logger.mdx

+2-2
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ This can be fixed by either ensuring both has the `service` value as `payment`,
305305

306306
You might want to continue to use the same date formatting style, or override `location` to display the `package.function_name:line_number` as you previously had.
307307

308-
Logger allows you to either change the format or suppress the following keys altogether at the initialization: `location`, `timestamp`, `level`, `xray_trace_id`, and `datefmt`
308+
Logger allows you to either change the format or suppress the following keys altogether at the initialization: `location`, `timestamp`, `level`, and `datefmt`
309309

310310
```python
311311
from aws_lambda_powertools import Logger
@@ -317,7 +317,7 @@ logger = Logger(stream=stdout, location="[%(funcName)s] %(module)s", datefmt="fa
317317
logger = Logger(stream=stdout, location=None) # highlight-line
318318
```
319319

320-
Alternatively, you can also change the order of the following log record keys via the `log_record_order` parameter: `level`, `location`, `message`, `xray_trace_id`, and `timestamp`
320+
Alternatively, you can also change the order of the following log record keys via the `log_record_order` parameter: `level`, `location`, `message`, and `timestamp`
321321

322322
```python
323323
from aws_lambda_powertools import Logger

tests/functional/test_aws_lambda_logging.py

+26
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,29 @@ def test_log_dict_xray_is_not_present_when_tracing_is_disabled(stdout, monkeypat
201201

202202
# THEN `xray_trace_id`` key should not be present
203203
assert "xray_trace_id" not in log_dict
204+
205+
206+
def test_log_dict_xray_is_updated_when_tracing_id_changes(stdout, monkeypatch):
207+
# GIVEN a logger is initialized within a Lambda function with X-Ray enabled
208+
trace_id = "1-5759e988-bd862e3fe1be46a994272793"
209+
trace_header = f"Root={trace_id};Parent=53995c3f42cd8ad8;Sampled=1"
210+
monkeypatch.setenv(name="_X_AMZN_TRACE_ID", value=trace_header)
211+
logger = Logger(stream=stdout)
212+
213+
# WHEN logging a message
214+
logger.info("foo")
215+
216+
# and Trace ID changes to mimick a new invocation
217+
trace_id_2 = "1-5759e988-bd862e3fe1be46a949393982437"
218+
trace_header_2 = f"Root={trace_id_2};Parent=53995c3f42cd8ad8;Sampled=1"
219+
monkeypatch.setenv(name="_X_AMZN_TRACE_ID", value=trace_header_2)
220+
221+
logger.info("foo bar")
222+
223+
log_dict, log_dict_2 = [json.loads(line.strip()) for line in stdout.getvalue().split("\n") if line]
224+
225+
# THEN `xray_trace_id`` key should be different in both invocations
226+
assert log_dict["xray_trace_id"] == trace_id
227+
assert log_dict_2["xray_trace_id"] == trace_id_2
228+
229+
monkeypatch.delenv(name="_X_AMZN_TRACE_ID")

0 commit comments

Comments
 (0)