Skip to content

Commit 907ed65

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

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

awslambdaric/bootstrap.py

+16-1
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

+1-1
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

+46
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,52 @@ def test_log_level(self) -> None:
12051205
self.assertEqual(expected_level, logging.getLogger().level)
12061206

12071207

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

0 commit comments

Comments
 (0)