Skip to content

Commit a752929

Browse files
author
Artem Krivonos
committed
make _setup_logging private, set log level only for json format
1 parent e02ac41 commit a752929

File tree

4 files changed

+47
-21
lines changed

4 files changed

+47
-21
lines changed

awslambdaric/bootstrap.py

+11-13
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ def replace_line_indentation(line, indent_char, new_indent_char):
107107

108108

109109
if _AWS_LAMBDA_LOG_FORMAT == LogFormat.JSON:
110+
_ERROR_FRAME_TYPE = _FRAME_TYPES[(LogFormat.JSON, logging.ERROR)]
110111

111112
def log_error(error_result, log_sink):
112113
error_result = {
@@ -121,6 +122,7 @@ def log_error(error_result, log_sink):
121122
)
122123

123124
else:
125+
_ERROR_FRAME_TYPE = _DEFAULT_FRAME_TYPE
124126

125127
def log_error(error_result, log_sink):
126128
error_description = "[ERROR]"
@@ -295,9 +297,7 @@ def __init__(self, log_sink):
295297
def emit(self, record):
296298
msg = self.format(record)
297299

298-
self.log_sink.log(
299-
msg, frame_type=getattr(record, "_frame_type", _FRAME_TYPES.get(()))
300-
)
300+
self.log_sink.log(msg, frame_type=getattr(record, "_frame_type", None))
301301

302302

303303
class LambdaLoggerFilter(logging.Filter):
@@ -346,9 +346,6 @@ def log_error(self, message_lines):
346346
sys.stdout.write(error_message)
347347

348348

349-
_ERROR_FRAME_TYPE = _FRAME_TYPES[(_AWS_LAMBDA_LOG_FORMAT, logging.ERROR)]
350-
351-
352349
class FramedTelemetryLogSink(object):
353350
"""
354351
FramedTelemetryLogSink implements the logging contract between runtimes and the platform. It implements a simple
@@ -375,12 +372,12 @@ def __enter__(self):
375372
def __exit__(self, exc_type, exc_value, exc_tb):
376373
self.file.close()
377374

378-
def log(self, msg, frame_type=_DEFAULT_FRAME_TYPE):
375+
def log(self, msg, frame_type=None):
379376
encoded_msg = msg.encode("utf8")
380377

381378
timestamp = int(time.time_ns() / 1000) # UNIX timestamp in microseconds
382379
log_msg = (
383-
frame_type
380+
(frame_type or _DEFAULT_FRAME_TYPE)
384381
+ len(encoded_msg).to_bytes(4, "big")
385382
+ timestamp.to_bytes(8, "big")
386383
+ encoded_msg
@@ -416,12 +413,16 @@ def create_log_sink():
416413
_GLOBAL_AWS_REQUEST_ID = None
417414

418415

419-
def setup_logging(log_format, log_level, log_sink):
416+
def _setup_logging(log_format, log_level, log_sink):
420417
logging.Formatter.converter = time.gmtime
421418
logger = logging.getLogger()
422419
logger_handler = LambdaLoggerHandler(log_sink)
423420
if log_format == LogFormat.JSON:
424421
logger_handler.setFormatter(JsonFormatter())
422+
423+
logging.addLevelName(logging.DEBUG, "TRACE")
424+
if log_level:
425+
logger.setLevel(log_level)
425426
else:
426427
logger_handler.setFormatter(
427428
logging.Formatter(
@@ -430,9 +431,6 @@ def setup_logging(log_format, log_level, log_sink):
430431
)
431432
)
432433

433-
if log_level:
434-
logger.setLevel(log_level)
435-
436434
logger_handler.addFilter(LambdaLoggerFilter())
437435
logger.addHandler(logger_handler)
438436

@@ -445,7 +443,7 @@ def run(app_root, handler, lambda_runtime_api_addr):
445443
lambda_runtime_client = LambdaRuntimeClient(lambda_runtime_api_addr)
446444

447445
try:
448-
setup_logging(_AWS_LAMBDA_LOG_FORMAT, _AWS_LAMBDA_LOG_LEVEL, log_sink)
446+
_setup_logging(_AWS_LAMBDA_LOG_FORMAT, _AWS_LAMBDA_LOG_LEVEL, log_sink)
449447
global _GLOBAL_AWS_REQUEST_ID
450448

451449
request_handler = _get_handler(handler)

awslambdaric/lambda_runtime_log_utils.py

-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ def from_str(cls, value: str):
6161
}
6262
_DEFAULT_FRAME_TYPE = _FRAME_TYPES[(LogFormat.TEXT, logging.NOTSET)]
6363

64-
6564
_encode_json = json.JSONEncoder(ensure_ascii=False).encode
6665

6766

awslambdaric/lambda_runtime_marshaller.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
# simplejson's Decimal encoding allows '-NaN' as an output, which is a parse error for json.loads
1414
# to get the good parts of Decimal support, we'll special-case NaN decimals and otherwise duplicate the encoding for decimals the same way simplejson does
1515
class Encoder(json.JSONEncoder):
16-
def __init__(self, ensure_ascii=True):
17-
super().__init__(use_decimal=False, ensure_ascii=ensure_ascii)
16+
def __init__(self):
17+
super().__init__(use_decimal=False)
1818

1919
def default(self, obj):
2020
if isinstance(obj, decimal.Decimal):

tests/test_bootstrap.py

+34-5
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ def test_log_error_framed_log_sink(self):
927927
content = f.read()
928928

929929
frame_type = int.from_bytes(content[:4], "big")
930-
self.assertEqual(frame_type, 0xA55A0017)
930+
self.assertEqual(frame_type, 0xA55A0003)
931931

932932
length = int.from_bytes(content[4:8], "big")
933933
self.assertEqual(length, len(expected_logged_error.encode("utf8")))
@@ -973,7 +973,7 @@ def test_log_error_indentation_framed_log_sink(self):
973973
content = f.read()
974974

975975
frame_type = int.from_bytes(content[:4], "big")
976-
self.assertEqual(frame_type, 0xA55A0017)
976+
self.assertEqual(frame_type, 0xA55A0003)
977977

978978
length = int.from_bytes(content[4:8], "big")
979979
self.assertEqual(length, len(expected_logged_error.encode("utf8")))
@@ -1016,7 +1016,7 @@ def test_log_error_empty_stacktrace_line_framed_log_sink(self):
10161016
content = f.read()
10171017

10181018
frame_type = int.from_bytes(content[:4], "big")
1019-
self.assertEqual(frame_type, 0xA55A0017)
1019+
self.assertEqual(frame_type, 0xA55A0003)
10201020

10211021
length = int.from_bytes(content[4:8], "big")
10221022
self.assertEqual(length, len(expected_logged_error))
@@ -1053,7 +1053,7 @@ def test_log_error_invokeId_line_framed_log_sink(self):
10531053
content = f.read()
10541054

10551055
frame_type = int.from_bytes(content[:4], "big")
1056-
self.assertEqual(frame_type, 0xA55A0017)
1056+
self.assertEqual(frame_type, 0xA55A0003)
10571057

10581058
length = int.from_bytes(content[4:8], "big")
10591059
self.assertEqual(length, len(expected_logged_error))
@@ -1170,10 +1170,39 @@ def test_multiple_frame(self):
11701170
self.assertEqual(content[pos:], b"")
11711171

11721172

1173+
class TestLoggingSetup(unittest.TestCase):
1174+
def test_log_level(self) -> None:
1175+
test_cases = [
1176+
(LogFormat.JSON, "TRACE", logging.DEBUG),
1177+
(LogFormat.JSON, "DEBUG", logging.DEBUG),
1178+
(LogFormat.JSON, "INFO", logging.INFO),
1179+
(LogFormat.JSON, "WARN", logging.WARNING),
1180+
(LogFormat.JSON, "ERROR", logging.ERROR),
1181+
(LogFormat.JSON, "FATAL", logging.CRITICAL),
1182+
(LogFormat.TEXT, "TRACE", logging.NOTSET),
1183+
(LogFormat.TEXT, "DEBUG", logging.NOTSET),
1184+
(LogFormat.TEXT, "INFO", logging.NOTSET),
1185+
(LogFormat.TEXT, "WARN", logging.NOTSET),
1186+
(LogFormat.TEXT, "ERROR", logging.NOTSET),
1187+
(LogFormat.TEXT, "FATAL", logging.NOTSET),
1188+
]
1189+
for fmt, log_level, expected_level in test_cases:
1190+
with self.subTest():
1191+
# Drop previous setup
1192+
logging.getLogger().handlers.clear()
1193+
logging.getLogger().level = logging.NOTSET
1194+
1195+
bootstrap._setup_logging(fmt, log_level, bootstrap.StandardLogSink())
1196+
1197+
self.assertEqual(expected_level, logging.getLogger().level)
1198+
1199+
11731200
class TestLogging(unittest.TestCase):
11741201
@classmethod
11751202
def setUpClass(cls) -> None:
1176-
bootstrap.setup_logging(
1203+
logging.getLogger().handlers.clear()
1204+
logging.getLogger().level = logging.NOTSET
1205+
bootstrap._setup_logging(
11771206
LogFormat.from_str("JSON"), "INFO", bootstrap.StandardLogSink()
11781207
)
11791208

0 commit comments

Comments
 (0)