|
5 | 5 | import logging
|
6 | 6 | import os
|
7 | 7 | import time
|
| 8 | +import traceback |
8 | 9 | from abc import ABCMeta, abstractmethod
|
9 | 10 | from datetime import datetime, timezone
|
10 | 11 | from functools import partial
|
11 | 12 | from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
|
| 13 | +from ..shared.functions import ( |
| 14 | + resolve_truthy_env_var_choice |
| 15 | +) |
12 | 16 |
|
13 | 17 | from aws_lambda_powertools.logging.types import LogRecord
|
14 | 18 | from aws_lambda_powertools.shared import constants
|
@@ -77,6 +81,7 @@ def __init__(
|
77 | 81 | log_record_order: List[str] | None = None,
|
78 | 82 | utc: bool = False,
|
79 | 83 | use_rfc3339: bool = False,
|
| 84 | + include_traceback: bool = None, |
80 | 85 | **kwargs,
|
81 | 86 | ) -> None:
|
82 | 87 | """Return a LambdaPowertoolsFormatter instance.
|
@@ -148,16 +153,34 @@ def __init__(
|
148 | 153 | self.keys_combined = {**self._build_default_keys(), **kwargs}
|
149 | 154 | self.log_format.update(**self.keys_combined)
|
150 | 155 |
|
| 156 | + self.include_traceback = resolve_truthy_env_var_choice(env=os.getenv(constants.POWERTOOLS_TRACEBACK_ENV, "false"), |
| 157 | + choice=include_traceback, |
| 158 | + ) |
| 159 | + |
151 | 160 | super().__init__(datefmt=self.datefmt)
|
152 | 161 |
|
153 | 162 | def serialize(self, log: LogRecord) -> str:
|
154 | 163 | """Serialize structured log dict to JSON str"""
|
155 | 164 | return self.json_serializer(log)
|
| 165 | + |
| 166 | + 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 |
| 172 | + } for fs in traceback.extract_tb(e.__traceback__)] |
| 173 | + |
156 | 174 |
|
157 | 175 | def format(self, record: logging.LogRecord) -> str: # noqa: A003
|
158 | 176 | """Format logging record as structured JSON str"""
|
159 | 177 | formatted_log = self._extract_log_keys(log_record=record)
|
160 | 178 | formatted_log["message"] = self._extract_log_message(log_record=record)
|
| 179 | + |
| 180 | + if self.include_traceback: |
| 181 | + # Generate the traceback from the traceback library |
| 182 | + formatted_log["stack_trace"] = self.serialize_traceback(record.msg) #JSR |
| 183 | + |
161 | 184 | # exception and exception_name fields can be added as extra key
|
162 | 185 | # in any log level, we try to extract and use them first
|
163 | 186 | extracted_exception, extracted_exception_name = self._extract_log_exception(log_record=record)
|
|
0 commit comments