dynatrace-extensions / dt-extensions-python-sdk

Dynatrace Python Extensions SDK
https://dynatrace-extensions.github.io/dt-extensions-python-sdk/
MIT License
8 stars 2 forks source link

Initialize logging system at ROOT vs limiting to dynatrace_extension.sdk.extension and api #79

Open JosephHobbs opened 1 week ago

JosephHobbs commented 1 week ago

Is your feature request related to a problem? Please describe.

The current extension logging initialization only adds handlers to the 'dynatrace_extension.sdk.extension' and 'api' loggers. Due to this, other modules do not get these appenders, which prevents logs from being written for any logger outside of these two. This means that any logging I do in my own modules does not show up by default.

Describe the solution you'd like

I would love to see these appenders attached to the ROOT logger. This will ensure that all loggers would send their logs to these appenders as opposed to just the two built-in loggers. So for example, changing...

formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s (%(threadName)s): %(message)s")
error_handler = logging.StreamHandler()
error_handler.addFilter(lambda record: record.levelno >= logging.ERROR)
error_handler.setFormatter(formatter)
std_handler = logging.StreamHandler(sys.stdout)
std_handler.addFilter(lambda record: record.levelno < logging.ERROR)
std_handler.setFormatter(formatter)
extension_logger = logging.getLogger(__name__)
extension_logger.setLevel(logging.INFO)
extension_logger.addHandler(error_handler)
extension_logger.addHandler(std_handler)

api_logger = logging.getLogger("api")
api_logger.setLevel(logging.INFO)
api_logger.addHandler(error_handler)
api_logger.addHandler(std_handler)

to something like this...

formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s (%(threadName)s): %(message)s")
error_handler = logging.StreamHandler()
error_handler.addFilter(lambda record: record.levelno >= logging.ERROR)
error_handler.setFormatter(formatter)
std_handler = logging.StreamHandler(sys.stdout)
std_handler.addFilter(lambda record: record.levelno < logging.ERROR)
std_handler.setFormatter(formatter)

logging.getLogger().addHandler(error_handler)
logging.getLogger().addHandler(std_handler)

extension_logger = logging.getLogger(__name__)
extension_logger.setLevel(logging.INFO)

api_logger = logging.getLogger("api")
api_logger.setLevel(logging.INFO)

Describe alternatives you've considered

At this point, my workaround/alternative is to duplicate your logging code within my own init.py. This (at least) initializes the logger for my extension (module) and would apply to that module down...

################################################################################
# __init__.py
################################################################################

import logging
import sys

# The 'internal' name of our extension

EXTENSION_NAME = '%extension_name%'

# Initialize a logger for our extension namespace so that everything within
# the namespace will output to the log file! This is the same initialization
# code Dynatrace is using within their SDK.

_logging_formatter = logging.Formatter(
    "%(asctime)s [%(levelname)s] %(name)s (%(threadName)s): %(message)s")

_logging_handler_err = logging.StreamHandler()
_logging_handler_err.addFilter(lambda record: record.levelno >= logging.ERROR)
_logging_handler_err.setFormatter(_logging_formatter)

_logging_handler_out = logging.StreamHandler(sys.stdout)
_logging_handler_out.addFilter(lambda record: record.levelno < logging.ERROR)
_logging_handler_out.setFormatter(_logging_formatter)

_extension_logger = logging.getLogger(EXTENSION_NAME)
_extension_logger.setLevel(logging.INFO)
_extension_logger.addHandler(_logging_handler_err)
_extension_logger.addHandler(_logging_handler_out)

################################################################################
# END
################################################################################
radu-stefan-dt commented 6 days ago

Why not reuse the same logger?

from dynatrace_extension.sdk.extension import extension_logger as logger

logger.info("Hello world")