Skip to content

Commit 5436377

Browse files
committed
Added tests and documentation.
1 parent 3ad3c76 commit 5436377

File tree

5 files changed

+87
-10
lines changed

5 files changed

+87
-10
lines changed

aws_lambda_powertools/logging/formatter.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def __init__(
8181
log_record_order: List[str] | None = None,
8282
utc: bool = False,
8383
use_rfc3339: bool = False,
84-
include_traceback: bool = None,
84+
include_stacktrace: bool = None,
8585
**kwargs,
8686
) -> None:
8787
"""Return a LambdaPowertoolsFormatter instance.
@@ -153,8 +153,8 @@ def __init__(
153153
self.keys_combined = {**self._build_default_keys(), **kwargs}
154154
self.log_format.update(**self.keys_combined)
155155

156-
self.include_traceback = resolve_truthy_env_var_choice(env=os.getenv(constants.POWERTOOLS_TRACEBACK_ENV, "false"),
157-
choice=include_traceback,
156+
self.include_stacktrace = resolve_truthy_env_var_choice(env=os.getenv(constants.POWERTOOLS_STACKTRACE_ENV, "false"),
157+
choice=include_stacktrace,
158158
)
159159

160160
super().__init__(datefmt=self.datefmt)
@@ -164,11 +164,11 @@ def serialize(self, log: LogRecord) -> str:
164164
return self.json_serializer(log)
165165

166166
def serialize_traceback(self, e: Exception) -> list:
167-
return [{"File": fs.filename,
168-
"Line": fs.lineno,
169-
"Column": fs.colno,
170-
"Function": fs.name,
171-
"Statement": fs.line
167+
return [{"file": fs.filename,
168+
"line": fs.lineno,
169+
"column": fs.colno,
170+
"function": fs.name,
171+
"statement": fs.line
172172
} for fs in traceback.extract_tb(e.__traceback__)]
173173

174174

@@ -177,7 +177,7 @@ def format(self, record: logging.LogRecord) -> str: # noqa: A003
177177
formatted_log = self._extract_log_keys(log_record=record)
178178
formatted_log["message"] = self._extract_log_message(log_record=record)
179179

180-
if self.include_traceback:
180+
if self.include_stacktrace:
181181
# Generate the traceback from the traceback library
182182
formatted_log["stack_trace"] = self.serialize_traceback(record.msg) #JSR
183183

aws_lambda_powertools/shared/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@
4343
POWERTOOLS_DEV_ENV: str = "POWERTOOLS_DEV"
4444
POWERTOOLS_DEBUG_ENV: str = "POWERTOOLS_DEBUG"
4545

46-
POWERTOOLS_TRACEBACK_ENV: str = "POWERTOOLS_LOGGER_ENHANCED_TRACEBACK"
46+
POWERTOOLS_STACKTRACE_ENV: str = "POWERTOOLS_LOGGER_ENHANCED_STACKTRACE"

docs/core/logger.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,22 @@ Logger can optionally log uncaught exceptions by setting `log_uncaught_exception
319319
--8<-- "examples/logger/src/logging_uncaught_exceptions_output.json"
320320
```
321321

322+
#### Stack trace logging
323+
324+
Logger can optionally log the full stack trace as JSON by setting `logger_formatter=LambdaPowertoolsFormatter(include_stacktrace=True)` at initialization. Optionally, setting the `POWERTOOLS_LOGGER_ENHANCED_STACKTRACE` environment variable to `true` will include stacktrace information in the logs.
325+
326+
=== "logging_stacktrace.py"
327+
328+
```python hl_lines="8"
329+
--8<-- "examples/logger/src/logging_stacktrace.py"
330+
```
331+
332+
=== "logging_stacktrace_output.json"
333+
334+
```json hl_lines="7-22"
335+
--8<-- "examples/logger/src/logging_stacktrace_output.json"
336+
```
337+
322338
### Date formatting
323339

324340
Logger uses Python's standard logging date format with the addition of timezone: `2021-05-03 11:47:12,494+0200`.
@@ -352,6 +368,7 @@ The following environment variables are available to configure Logger at a globa
352368
| **Event Logging** | Whether to log the incoming event. | `POWERTOOLS_LOGGER_LOG_EVENT` | `false` |
353369
| **Debug Sample Rate** | Sets the debug log sampling. | `POWERTOOLS_LOGGER_SAMPLE_RATE` | `0` |
354370
| **Disable Deduplication** | Disables log deduplication filter protection to use Pytest Live Log feature. | `POWERTOOLS_LOG_DEDUPLICATION_DISABLED` | `false` |
371+
| **Include Stack Trace** | Includes JSON formatted stack trace in the log output. | `POWERTOOLS_LOGGER_ENHANCED_STACKTRACE` | `false` |
355372

356373
[`POWERTOOLS_LOGGER_LOG_EVENT`](#logging-incoming-event) can also be set on a per-method basis, and [`POWERTOOLS_LOGGER_SAMPLE_RATE`](#sampling-debug-logs) on a per-instance basis. These parameter values will override the environment variable value.
357374

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ Core utilities such as Tracing, Logging, Metrics, and Event Handler will be avai
718718
| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Sets whether to decrypt or not values retrieved from AWS SSM Parameters Store | [Parameters](./utilities/parameters.md#ssmprovider){target="_blank"} | `false` |
719719
| **POWERTOOLS_DEV** | Increases verbosity across utilities | Multiple; see [POWERTOOLS_DEV effect below](#optimizing-for-non-production-environments) | `false` |
720720
| **LOG_LEVEL** | Sets logging level | [Logging](./core/logger.md){target="_blank"} | `INFO` |
721+
| **POWERTOOLS_LOGGER_ENHANCED_STACKTRACE** | Include JSON formatted stack trace in log message | [Logging](./core/logger.md){target="_blank"} | `false` |
721722

722723
### Optimizing for non-production environments
723724

tests/functional/test_logger.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,3 +959,62 @@ def test_stream_defaults_to_stdout(service_name, capsys):
959959
# NOTE: we can't assert on capsys.readouterr().err due to a known bug: https://github.com/pytest-dev/pytest/issues/5997
960960
log = json.loads(capsys.readouterr().out.strip())
961961
assert log["message"] == msg
962+
963+
def test_logger_logs_no_stack_trace_without_parameter(stdout):
964+
logger = Logger(stream=stdout)
965+
966+
try:
967+
val = 1 + "someString"
968+
except Exception as e:
969+
logger.exception(e)
970+
971+
log = capture_logging_output(stdout)
972+
assert "stack_trace" not in log
973+
974+
def test_logger_logs_stack_trace_with_parameter(stdout):
975+
logger = Logger(stream=stdout, logger_formatter=LambdaPowertoolsFormatter(include_stacktrace=True))
976+
977+
try:
978+
val = 1 + "someString"
979+
except Exception as e:
980+
logger.exception(e)
981+
982+
log = capture_logging_output(stdout)
983+
assert "stack_trace" in log
984+
985+
def test_logger_logs_stack_trace_with_env_var(stdout, monkeypatch: pytest.MonkeyPatch):
986+
monkeypatch.setenv(constants.POWERTOOLS_STACKTRACE_ENV, "true")
987+
logger = Logger(stream=stdout)
988+
989+
try:
990+
val = 1 + "someString"
991+
except Exception as e:
992+
logger.exception(e)
993+
994+
log = capture_logging_output(stdout)
995+
assert "stack_trace" in log
996+
997+
998+
def test_logger_logs_no_stack_trace_with_env_var(stdout, monkeypatch: pytest.MonkeyPatch):
999+
monkeypatch.setenv(constants.POWERTOOLS_STACKTRACE_ENV, "false")
1000+
logger = Logger(stream=stdout)
1001+
1002+
try:
1003+
val = 1 + "someString"
1004+
except Exception as e:
1005+
logger.exception(e)
1006+
1007+
log = capture_logging_output(stdout)
1008+
assert "stack_trace" not in log
1009+
1010+
def test_logger_logs_no_stack_trace_with_parameter_override(stdout, monkeypatch: pytest.MonkeyPatch):
1011+
monkeypatch.setenv(constants.POWERTOOLS_STACKTRACE_ENV, "true")
1012+
logger = Logger(stream=stdout, logger_formatter=LambdaPowertoolsFormatter(include_stacktrace=False))
1013+
1014+
try:
1015+
val = 1 + "someString"
1016+
except Exception as e:
1017+
logger.exception(e)
1018+
1019+
log = capture_logging_output(stdout)
1020+
assert "stack_trace" not in log

0 commit comments

Comments
 (0)