Skip to content

Commit d93b082

Browse files
author
Artem Krivonos
committed
add LambdaLoggerHandlerWithFrameType
1 parent 3c98bb4 commit d93b082

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

awslambdaric/bootstrap.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,16 @@ def __init__(self, log_sink):
299299
logging.Handler.__init__(self)
300300
self.log_sink = log_sink
301301

302+
def emit(self, record):
303+
msg = self.format(record)
304+
self.log_sink.log(msg)
305+
306+
307+
class LambdaLoggerHandlerWithFrameType(logging.Handler):
308+
def __init__(self, log_sink):
309+
super().__init__()
310+
self.log_sink = log_sink
311+
302312
def emit(self, record):
303313
self.log_sink.log(
304314
self.format(record),
@@ -425,7 +435,12 @@ def create_log_sink():
425435
def _setup_logging(log_format, log_level, log_sink):
426436
logging.Formatter.converter = time.gmtime
427437
logger = logging.getLogger()
428-
logger_handler = LambdaLoggerHandler(log_sink)
438+
439+
if log_format == LogFormat.JSON or log_level:
440+
logger_handler = LambdaLoggerHandlerWithFrameType(log_sink)
441+
else:
442+
logger_handler = LambdaLoggerHandler(log_sink)
443+
429444
if log_format == LogFormat.JSON:
430445
logger_handler.setFormatter(JsonFormatter())
431446
else:

awslambdaric/lambda_runtime_log_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def _get_log_level_from_env_var(log_level):
7171
_encode_json = _json_encoder.encode
7272

7373

74-
def _format_log_level(record: logging.LogRecord):
74+
def _format_log_level(record: logging.LogRecord) -> int:
7575
return min(50, max(0, record.levelno)) // 10 * 10
7676

7777

tests/test_bootstrap.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,6 @@ def test_log_level(self) -> None:
11791179
(LogFormat.JSON, "WARN", logging.WARNING),
11801180
(LogFormat.JSON, "ERROR", logging.ERROR),
11811181
(LogFormat.JSON, "FATAL", logging.CRITICAL),
1182-
# Log level is set only for Json format
11831182
(LogFormat.TEXT, "TRACE", logging.DEBUG),
11841183
(LogFormat.TEXT, "DEBUG", logging.DEBUG),
11851184
(LogFormat.TEXT, "INFO", logging.INFO),
@@ -1205,6 +1204,58 @@ def test_log_level(self) -> None:
12051204
self.assertEqual(expected_level, logging.getLogger().level)
12061205

12071206

1207+
class TestLambdaLoggerHandlerSetup(unittest.TestCase):
1208+
@classmethod
1209+
def tearDownClass(cls):
1210+
importlib.reload(bootstrap)
1211+
logging.getLogger().handlers.clear()
1212+
logging.getLogger().level = logging.NOTSET
1213+
1214+
def test_handler_setup(self, *_):
1215+
test_cases = [
1216+
(62, 0xA55A0003, 46, {}),
1217+
(133, 0xA55A001A, 117, {"AWS_LAMBDA_LOG_FORMAT": "JSON"}),
1218+
(62, 0xA55A001B, 46, {"AWS_LAMBDA_LOG_LEVEL": "INFO"}),
1219+
]
1220+
1221+
for total_length, header, message_length, env_vars in test_cases:
1222+
with patch.dict(
1223+
os.environ, env_vars, clear=True
1224+
), NamedTemporaryFile() as temp_file:
1225+
importlib.reload(bootstrap)
1226+
logging.getLogger().handlers.clear()
1227+
logging.getLogger().level = logging.NOTSET
1228+
1229+
before = int(time.time_ns() / 1000)
1230+
with bootstrap.FramedTelemetryLogSink(
1231+
os.open(temp_file.name, os.O_CREAT | os.O_RDWR)
1232+
) as ls:
1233+
bootstrap._setup_logging(
1234+
bootstrap._AWS_LAMBDA_LOG_FORMAT,
1235+
bootstrap._AWS_LAMBDA_LOG_LEVEL,
1236+
ls,
1237+
)
1238+
logger = logging.getLogger()
1239+
logger.critical("critical")
1240+
after = int(time.time_ns() / 1000)
1241+
1242+
content = open(temp_file.name, "rb").read()
1243+
self.assertEqual(len(content), total_length)
1244+
1245+
pos = 0
1246+
frame_type = int.from_bytes(content[pos : pos + 4], "big")
1247+
self.assertEqual(frame_type, header)
1248+
pos += 4
1249+
1250+
length = int.from_bytes(content[pos : pos + 4], "big")
1251+
self.assertEqual(length, message_length)
1252+
pos += 4
1253+
1254+
timestamp = int.from_bytes(content[pos : pos + 8], "big")
1255+
self.assertTrue(before <= timestamp)
1256+
self.assertTrue(timestamp <= after)
1257+
1258+
12081259
class TestLogging(unittest.TestCase):
12091260
@classmethod
12101261
def setUpClass(cls) -> None:

0 commit comments

Comments
 (0)