Skip to content

Commit 16f4dbe

Browse files
feat(logger): add method to return currently configured keys (#4033)
* Initial commit * mypy + tests * Using get_current_keys instead of current_keys + error handling * Tests * Docs * Adding documentation * Addressing Ruben's feedback * Addressing Ruben's feedback * Addressing Ruben's feedback
1 parent b3eaeb5 commit 16f4dbe

File tree

6 files changed

+78
-4
lines changed

6 files changed

+78
-4
lines changed

Diff for: aws_lambda_powertools/logging/formatter.py

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ class BasePowertoolsFormatter(logging.Formatter, metaclass=ABCMeta):
4848
def append_keys(self, **additional_keys) -> None:
4949
raise NotImplementedError()
5050

51+
def get_current_keys(self) -> Dict[str, Any]:
52+
return {}
53+
5154
def remove_keys(self, keys: Iterable[str]) -> None:
5255
raise NotImplementedError()
5356

@@ -231,6 +234,9 @@ def formatTime(self, record: logging.LogRecord, datefmt: Optional[str] = None) -
231234
def append_keys(self, **additional_keys) -> None:
232235
self.log_format.update(additional_keys)
233236

237+
def get_current_keys(self) -> Dict[str, Any]:
238+
return self.log_format
239+
234240
def remove_keys(self, keys: Iterable[str]) -> None:
235241
for key in keys:
236242
self.log_format.pop(key, None)

Diff for: aws_lambda_powertools/logging/logger.py

+3
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,9 @@ def debug(
583583
def append_keys(self, **additional_keys: object) -> None:
584584
self.registered_formatter.append_keys(**additional_keys)
585585

586+
def get_current_keys(self) -> Dict[str, Any]:
587+
return self.registered_formatter.get_current_keys()
588+
586589
def remove_keys(self, keys: Iterable[str]) -> None:
587590
self.registered_formatter.remove_keys(keys)
588591

Diff for: docs/core/logger.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,16 @@ Logger is commonly initialized in the global scope. Due to [Lambda Execution Con
274274
--8<-- "examples/logger/src/clear_state_event_two.json"
275275
```
276276

277+
### Accessing currently configured keys
278+
279+
You can view all currently configured keys from the Logger state using the `get_current_keys()` method. This method is useful when you need to avoid overwriting keys that are already configured.
280+
281+
=== "get_current_keys.py"
282+
283+
```python hl_lines="4 11"
284+
--8<-- "examples/logger/src/get_current_keys.py"
285+
```
286+
277287
### Log levels
278288

279289
The default log level is `INFO`. It can be set using the `level` constructor option, `setLevel()` method or by using the `POWERTOOLS_LOG_LEVEL` environment variable.
@@ -732,7 +742,7 @@ The `log` argument is the final log record containing [our standard keys](#stand
732742
For exceptional cases where you want to completely replace our formatter logic, you can subclass `BasePowertoolsFormatter`.
733743

734744
???+ warning
735-
You will need to implement `append_keys`, `clear_state`, override `format`, and optionally `remove_keys` to keep the same feature set Powertools for AWS Lambda (Python) Logger provides. This also means keeping state of logging keys added.
745+
You will need to implement `append_keys`, `clear_state`, override `format`, and optionally `get_current_keys`, and `remove_keys` to keep the same feature set Powertools for AWS Lambda (Python) Logger provides. This also means tracking the added logging keys.
736746

737747
=== "bring_your_own_formatter_from_scratch.py"
738748

Diff for: examples/logger/src/bring_your_own_formatter_from_scratch.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
import logging
3-
from typing import Iterable, List, Optional
3+
from typing import Any, Dict, Iterable, List, Optional
44

55
from aws_lambda_powertools import Logger
66
from aws_lambda_powertools.logging.formatter import BasePowertoolsFormatter
@@ -16,6 +16,9 @@ def append_keys(self, **additional_keys):
1616
# also used by `inject_lambda_context` decorator
1717
self.log_format.update(additional_keys)
1818

19+
def current_keys(self) -> Dict[str, Any]:
20+
return self.log_format
21+
1922
def remove_keys(self, keys: Iterable[str]):
2023
for key in keys:
2124
self.log_format.pop(key, None)

Diff for: examples/logger/src/get_current_keys.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from aws_lambda_powertools import Logger
2+
from aws_lambda_powertools.utilities.typing import LambdaContext
3+
4+
logger = Logger()
5+
6+
7+
@logger.inject_lambda_context
8+
def lambda_handler(event: dict, context: LambdaContext) -> str:
9+
logger.info("Collecting payment")
10+
11+
if "order" not in logger.get_current_keys():
12+
logger.append_keys(order=event.get("order"))
13+
14+
return "hello world"

Diff for: tests/functional/test_logger.py

+40-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
import string
1010
import sys
1111
import warnings
12-
from ast import Dict
1312
from collections import namedtuple
1413
from datetime import datetime, timezone
15-
from typing import Any, Callable, Iterable, List, Optional, Union
14+
from typing import Any, Callable, Dict, Iterable, List, Optional, Union
1615

1716
import pytest
1817

@@ -606,6 +605,45 @@ def test_logger_append_remove_keys(stdout, service_name):
606605
assert (extra_keys.items() <= keys_removed_log.items()) is False
607606

608607

608+
def test_logger_append_and_show_current_keys(stdout, service_name):
609+
# GIVEN a Logger is initialized
610+
logger = Logger(service=service_name, stream=stdout)
611+
extra_keys = {"request_id": "id", "context": "value"}
612+
613+
# WHEN keys are updated
614+
logger.append_keys(**extra_keys)
615+
616+
# THEN appended keys must be present in logger
617+
current_keys = logger.get_current_keys()
618+
assert "request_id" in current_keys
619+
assert "context" in current_keys
620+
621+
622+
def test_logger_formatter_without_get_current_keys_method(stdout, service_name):
623+
class CustomFormatter(BasePowertoolsFormatter):
624+
def append_keys(self, **additional_keys):
625+
# Fake method
626+
pass
627+
628+
def clear_state(self) -> None:
629+
# Fake method
630+
pass
631+
632+
custom_formater = CustomFormatter()
633+
634+
# GIVEN a Logger is initialized with a Logger Formatter from scratch
635+
636+
logger = Logger(service=service_name, stream=stdout, logger_formatter=custom_formater)
637+
extra_keys = {"request_id": "id", "context": "value"}
638+
639+
# WHEN keys are updated
640+
logger.append_keys(**extra_keys)
641+
642+
# THEN the appended keys will not persist
643+
# unless the customer implements the required methods and persists the log_format
644+
assert logger.get_current_keys() == {}
645+
646+
609647
def test_logger_custom_formatter(stdout, service_name, lambda_context):
610648
class CustomFormatter(BasePowertoolsFormatter):
611649
custom_format = {}

0 commit comments

Comments
 (0)