-
Notifications
You must be signed in to change notification settings - Fork 53
Support crt logs in 'logging' module #728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 24 commits
c5a9fe8
1804aab
2dc8981
0f84ece
2946561
d2043f5
e6dafb3
24fa990
23bc05f
4a199fc
ae006cf
3ec9bfc
0b8c21b
150f901
ea68050
429c49c
b6ef442
c98b39f
85306ba
206b1cd
51faa3f
1006e20
efd8b77
1b4fb57
5d813e4
c44ecf1
b97de43
cd02ec4
b5e8f4b
41d7b85
d1708c5
63092ad
a8d4d49
eae85a3
1362242
076e914
7e24817
44f4b75
d5faf92
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,194 @@ | ||
| # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| # SPDX-License-Identifier: Apache-2.0. | ||
|
|
||
| """Python logging integration for the AWS CRT.""" | ||
|
|
||
| import logging | ||
| import threading | ||
| from enum import IntEnum | ||
|
|
||
| import _awscrt | ||
| from awscrt.io import LogLevel | ||
|
|
||
| __all__ = ['init_logging', 'set_log_level', 'logf', 'LogSubject', 'CRT_LOG_FORMAT'] | ||
|
|
||
| _CRT_TO_PY_LEVEL = { | ||
| 0: logging.NOTSET, | ||
| 1: logging.CRITICAL, | ||
| 2: logging.ERROR, | ||
| 3: logging.WARNING, | ||
| 4: logging.INFO, | ||
| 5: logging.DEBUG, | ||
| 6: logging.DEBUG, | ||
| } | ||
|
|
||
| _PY_TO_CRT_LEVEL = { | ||
| logging.NOTSET: LogLevel.NoLogs, | ||
| logging.CRITICAL: LogLevel.Fatal, | ||
| logging.ERROR: LogLevel.Error, | ||
| logging.WARNING: LogLevel.Warn, | ||
| logging.INFO: LogLevel.Info, | ||
| logging.DEBUG: LogLevel.Trace, | ||
| } | ||
|
|
||
| # Default Format supported by native loggers. | ||
| CRT_LOG_FORMAT = '%(asctime)s [%(threadName)s] %(levelname)s %(name)s - %(message)s' | ||
|
|
||
|
|
||
| class LogSubject(IntEnum): | ||
| """Log subject identifiers for CRT subsystems.""" | ||
| # aws-c-common (package ID 0) | ||
| COMMON_GENERAL = 0x000 | ||
| COMMON_TASK_SCHEDULER = 0x001 | ||
|
|
||
| # aws-c-io (package ID 1) | ||
| IO_GENERAL = 0x400 | ||
| IO_EVENT_LOOP = 0x401 | ||
| IO_SOCKET = 0x402 | ||
| IO_SOCKET_HANDLER = 0x403 | ||
| IO_TLS = 0x404 | ||
| IO_ALPN = 0x405 | ||
| IO_DNS = 0x406 | ||
| IO_PKI = 0x407 | ||
| IO_CHANNEL = 0x408 | ||
| IO_CHANNEL_BOOTSTRAP = 0x409 | ||
| IO_FILE_UTILS = 0x40A | ||
| IO_SHARED_LIBRARY = 0x40B | ||
|
|
||
| # aws-c-http (package ID 2) | ||
| HTTP_GENERAL = 0x800 | ||
| HTTP_CONNECTION = 0x801 | ||
| HTTP_SERVER = 0x802 | ||
| HTTP_STREAM = 0x803 | ||
| HTTP_CONNECTION_MANAGER = 0x804 | ||
| HTTP_WEBSOCKET = 0x805 | ||
| HTTP_WEBSOCKET_SETUP = 0x806 | ||
|
|
||
| # aws-c-event-stream (package ID 4) | ||
| EVENT_STREAM_GENERAL = 0x1000 | ||
| EVENT_STREAM_CHANNEL_HANDLER = 0x1001 | ||
| EVENT_STREAM_RPC_SERVER = 0x1002 | ||
| EVENT_STREAM_RPC_CLIENT = 0x1003 | ||
|
|
||
| # aws-c-mqtt (package ID 5) | ||
| MQTT_GENERAL = 0x1400 | ||
| MQTT_CLIENT = 0x1401 | ||
| MQTT_TOPIC_TREE = 0x1402 | ||
|
|
||
| # aws-c-auth (package ID 6) | ||
| AUTH_GENERAL = 0x1800 | ||
| AUTH_PROFILE = 0x1801 | ||
| AUTH_CREDENTIALS_PROVIDER = 0x1802 | ||
| AUTH_SIGNING = 0x1803 | ||
|
|
||
| # aws-c-cal (package ID 7) | ||
| CAL_GENERAL = 0x1C00 | ||
| CAL_ECC = 0x1C01 | ||
| CAL_HASH = 0x1C02 | ||
| CAL_HMAC = 0x1C03 | ||
| CAL_DER = 0x1C04 | ||
| CAL_LIBCRYPTO_RESOLVE = 0x1C05 | ||
| CAL_RSA = 0x1C06 | ||
| CAL_ED25519 = 0x1C07 | ||
|
|
||
| # aws-c-s3 (package ID 14) | ||
| S3_GENERAL = 0x3800 | ||
| S3_CLIENT = 0x3801 | ||
|
|
||
| # aws-c-sdkutils (package ID 15) | ||
| SDKUTILS_GENERAL = 0x3C00 | ||
| SDKUTILS_PROFILE = 0x3C01 | ||
| SDKUTILS_ENDPOINTS_PARSING = 0x3C02 | ||
| SDKUTILS_ENDPOINTS_RESOLVE = 0x3C03 | ||
| SDKUTILS_ENDPOINTS_GENERAL = 0x3C04 | ||
| SDKUTILS_PARTITIONS_PARSING = 0x3C05 | ||
| SDKUTILS_ENDPOINTS_REGEX = 0x3C06 | ||
|
|
||
|
|
||
| _PACKAGE_ID_TO_MODULE = { | ||
| 0: 'common', | ||
| 1: 'io', | ||
| 2: 'http', | ||
| 4: 'event-stream', | ||
| 5: 'mqtt', | ||
| 6: 'auth', | ||
| 7: 'cal', | ||
| 14: 's3', | ||
| 15: 'sdkutils', | ||
| } | ||
|
|
||
|
|
||
| def _python_logging_callback(crt_level, message, subject_id, subject_name, thread_name): | ||
| """Called from C for each CRT log message.""" | ||
| module = _PACKAGE_ID_TO_MODULE.get(subject_id >> 10, 'unknown') | ||
| logger = logging.getLogger('awscrt.{}.{}'.format(module, subject_name)) | ||
| py_level = _CRT_TO_PY_LEVEL.get(crt_level, logging.DEBUG) | ||
| threading.current_thread().name = thread_name | ||
| logger.log(py_level, '%s', message) | ||
|
|
||
|
|
||
| def init_logging(level: int = logging.DEBUG): | ||
| """Initialize CRT logging, routing output through Python's logging module. | ||
|
|
||
| Log messages appear under the ``awscrt`` logger hierarchy, with each CRT | ||
| subsystem as a child logger (e.g. ``awscrt.io.event-loop``, | ||
| ``awscrt.s3.S3Client``). | ||
|
|
||
| This is mutually exclusive with :func:`~awscrt.io.init_logging` -- use one | ||
| or the other, not both. Can only be called once. | ||
|
|
||
| Example usage:: | ||
|
|
||
| import logging | ||
| from awscrt.logging import init_logging | ||
|
|
||
| logging.basicConfig(level=logging.DEBUG) | ||
| init_logging(logging.DEBUG) | ||
|
|
||
| Args: | ||
| level (int): Python logging level (e.g. ``logging.DEBUG``, | ||
| ``logging.WARNING``). | ||
|
|
||
| Raises: | ||
| RuntimeError: If CRT logging has already been initialized. | ||
| """ | ||
| root_logger = logging.getLogger('awscrt') | ||
|
|
||
| try: | ||
| crt_level = _PY_TO_CRT_LEVEL[level] | ||
| except KeyError: | ||
| raise ValueError(f"Invalid log level: {level}. Use logging.DEBUG, INFO, WARNING, ERROR, or CRITICAL") | ||
|
|
||
| if root_logger.level == logging.NOTSET: | ||
| root_logger.setLevel(_CRT_TO_PY_LEVEL.get(int(crt_level), logging.DEBUG)) | ||
|
|
||
| _awscrt.init_python_logging(int(crt_level), _python_logging_callback) | ||
|
|
||
|
|
||
| def set_log_level(level: int): | ||
| """Change the CRT log level. :func:`init_logging` must have been called first. | ||
|
azkrishpy marked this conversation as resolved.
|
||
|
|
||
| Args: | ||
| level (int): Python logging level (e.g. ``logging.DEBUG``, | ||
| ``logging.WARNING``). | ||
| """ | ||
| try: | ||
| crt_level = _PY_TO_CRT_LEVEL[level] | ||
| except KeyError: | ||
| raise ValueError(f"Invalid log level: {level}. Use logging.DEBUG, INFO, WARNING, ERROR, or CRITICAL") | ||
| _awscrt.set_log_level(int(crt_level)) | ||
|
|
||
|
|
||
| def logf(level: int, subject: LogSubject, message: str): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why naming it as And here we just take a message and subject, I think it's better to name it to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I only called it logf because we are directly calling AWS_LOGF() i some sense.. but yes we can use log as well... but it would also conflict with logger.log() is that a problem we need to worry about?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so, it's like we have two init_logging method... |
||
| """Log a message through the CRT's configured logger. | ||
|
|
||
| Args: | ||
| level (int): Python logging level (e.g. logging.DEBUG, logging.INFO). | ||
| subject (LogSubject): Log subject identifying the subsystem. | ||
| message (str): The message to log. | ||
| """ | ||
| try: | ||
| crt_level = _PY_TO_CRT_LEVEL[level] | ||
| except KeyError: | ||
| raise ValueError(f"Invalid log level: {level}. Use logging.DEBUG, INFO, WARNING, ERROR, or CRITICAL") | ||
| _awscrt.logger_log(int(crt_level), int(subject), message) | ||
Uh oh!
There was an error while loading. Please reload this page.