version: 1

custom_levels:
  OBSERVATION: 24
  ACTION: 25
  CHAT: 26
  LLM: 9

formatters:
  # Console output
  colored:
    class: colorlog.ColoredFormatter
    format: "{log_color}{asctime}.{msecs:03.0f} | {levelname:11} | {name:70} | {message}"
    style: "{"
    datefmt: "%H:%M:%S"

  # User-facing UI (structured JSON)
  json:
    class: pythonjsonlogger.jsonlogger.JsonFormatter
    format: "{name} {levelname} {levelno} {message} {created} {relativeCreated}"
    style: "{"

  # Experiment stream for console and file output, with optional `role` field
  experiment:
    class: control_backend.logging.OptionalFieldFormatter
    format: "%(asctime)s %(levelname)s %(role?)s %(message)s"
    defaults:
      role: "-"

filters:
  # Filter out any log records that have the extra field "partial" set to True, indicating that they
  #  will be replaced later.
  partial:
    (): control_backend.logging.PartialFilter

handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: colored
    filters: [partial]
    stream: ext://sys.stdout
  ui:
    class: zmq.log.handlers.PUBHandler
    level: LLM
    formatter: json
  file:
    class: control_backend.logging.DatedFileHandler
    formatter: experiment
    filters: [partial]
    # Directory must match config.logging_settings.experiment_log_directory
    file_prefix: experiment_logs/experiment

# Level for external libraries
root:
  level: WARN
  handlers: [console]

loggers:
  control_backend:
    level: LLM
    handlers: [ui]
  experiment:  # This name must match config.logging_settings.experiment_logger_name
    level: DEBUG
    handlers: [ui, file]
