Supprimer Rendre public Rendre privé Add tags Delete tags
  Ajouter un tag   Annuler
  Supprimer le tag   Annuler
  • • DevOps notes •
  •  
  • Tags
  • Connexion

Declarative Logging/shaare/gWRxQw

  • python
  • python

Declarative Logging Configuration

  • Declarative configuration separates setup from code, making it easier to maintain and adjust.
  • Python’s logging.config module supports both INI-style (fileConfig) and dictionary-based (dictConfig) configurations.
  • Configuration objects can be loaded from files (INI, JSON, YAML) or defined in code.
  • Benefits include environment-specific overrides, less boilerplate, and clearer visibility of logger/handler relationships.

INI-Style Configuration with fileConfig

  • Uses an INI-format file to define loggers, handlers, and formatters.
  • Sections: [loggers], [handlers], [formatters], plus one section per named logger/handler/formatter.
  • Good for simple setups and backwards compatibility, but less flexible for dynamic structures.

Dictionary-Based Configuration with dictConfig

  • Configuration defined as a Python dict, offering full programmatic control.
  • Keys: version, disable_existing_loggers, and mappings for formatters, handlers, loggers, and optionally root.
  • Easy to build or modify at runtime, and to serialize/deserialize via JSON/YAML.

Loading Configuration from JSON or YAML

  • Store the same dict-based schema in a JSON/YAML file for external editing.
  • Read and parse the file, then pass the resulting dict to dictConfig.
  • Enables separation of concerns: ops teams can tweak logging without touching code.

Dynamic and Programmatic Adjustments

  • You can modify the config dict at runtime before calling dictConfig.
  • Handlers, formatters, and levels can be added, removed, or tweaked based on environment variables or feature flags.
  • Example: switch file logging on/off depending on a DEBUG flag.
import logging
import logging.config
import json
from typing import Any, Dict

"""
# Uncomment to test INI configuration

# Declarative logging configuration - INI-file
print("Declarative configuration using INI files")
print("---------\n")

config_path = "declarative-config.ini"

logging.config.fileConfig(
    fname=config_path,
)

app_logger = logging.getLogger("app")
app_logger.debug("INI-style fileConfig is working!")
"""

"""
# Uncomment to test Dictionary configuration

# Declarative logging configuration - Dictionary config
print("Declarative configuration using dictionary config")
print("---------\n")

dict_config: Dict[str, Any] = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "simple": {"format": "%(levelname)-8s - %(message)s"}
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "level": "INFO",
            "formatter": "simple",
            "stream": "ext://sys.stdout",
        }
    },
    "loggers": {
        "config.dict": {
            "level": "DEBUG",
            "handlers": ["console"],
        }
    },
}

logging.config.dictConfig(dict_config)
config_logger = logging.getLogger("config.dict")
config_logger.debug("dictConfig setup successfully")
config_logger.info("Info goes to console")
"""

"""
# Uncomment to test JSON configuration

# Declarative logging configuration - JSON config
print("Declarative configuration using JSON config")
print("---------\n")

config_path = "declarative-config.json"

with open(config_path, "r") as config_file:
    json_config = json.load(config_file)

logging.config.dictConfig(json_config)
config_logger = logging.getLogger("config.json")
config_logger.debug("JSON config setup successfully")
config_logger.info("Info goes to console")
"""

# Dynamically building config
print("Dynamically building config")
print("---------\n")

base_config: Dict[str, Any] = {
    "version": 1,
    "disable_existing_loggers": True,
    "handlers": {},
    "formatters": {},
    "loggers": {},
}

base_config["formatters"]["simple"] = {
    "format": "%(levelname)-8s - %(message)s"
}

base_config["handlers"]["console"] = {
    "class": "logging.StreamHandler",
    "level": "DEBUG",
    "formatter": "simple",
    "stream": "ext://sys.stdout",
}

base_config["loggers"]["config.dynamic"] = {
    "level": "WARNING",
    "handlers": ["console"],
}

def is_debug():
    return True

if is_debug():
    for logger, _config in base_config["loggers"].items():
        base_config["loggers"][logger]["level"] = "DEBUG"

logging.config.dictConfig(base_config)
config_logger = logging.getLogger("config.dynamic")
config_logger.debug("Dynamic config setup successfully")
config_logger.info("Info goes to console")

Example of declarative-config.ini

[loggers]
keys=root,app

[handlers]
keys=consoleHandler,nullHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=INFO
handlers=consoleHandler

[logger_app]
level=DEBUG
handlers=nullHandler
qualname=app

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[handler_nullHandler]
class=NullHandler
level=NOTSET
formatter=
args=()

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)-8s - %(message)s

Example of declarative-config.json

{
  "version": 1,
  "disable_existing_loggers": false,
  "formatters": {
    "simple": { "format": "%(levelname)-8s - %(message)s" },
    "detailed": {
      "format": "%(asctime)s %(name)s [%(levelname)s]: %(message)s",
      "datefmt": "%Y-%m-%d %H:%M:%S"
    }
  },
  "handlers": {
    "console": {
      "class": "logging.StreamHandler",
      "level": "INFO",
      "formatter": "detailed",
      "stream": "ext://sys.stdout"
    }
  },
  "loggers": {
    "config.json": {
      "level": "DEBUG"
    }
  },
  "root": {
    "level": "DEBUG",
    "handlers": ["console"]
  }
}
3 months ago Permalien
cluster icon
  • Range, zip : Efficient Looping: range Creating large lists for loops is memory-intensive (e.g., list(range(1_000_000))). range() stores only start, stop, and step...
  • Fixtures in Pytest : Fixtures in Pytest As tests grow more complex, repeating setup and cleanup steps makes tests harder to read and maintain. Pytest fixtures allow centr...
  • *args and **kwargs : Flexible Functions: *args and **kwargs We can use the syntax *args and **kwargs to accept a variable number of both positional and keyword arguments....
  • Implementing Retries and Timeouts : Implementing Retries and Timeouts External services can be slow or unreliable, causing scripts to hang or fail unexpectedly. Timeouts and retries hel...
  • Python Functions Are First‑Class Citizens : Python Functions Are First‑Class Citizens In Python, functions behave like any other object (strings, ints, lists). Because they are "first‑clas...


(110)
Filtrer par liens sans tag
Replier Replier tout Déplier Déplier tout Êtes-vous sûr de vouloir supprimer ce lien ? Êtes-vous sûr de vouloir supprimer ce tag ? Le gestionnaire de marque-pages personnel, minimaliste, et sans base de données par la communauté Shaarli