5

I feel like this should be super simple but I cannot figure out how to specify the path for the logfile when using structlog. The documentation states that you can use traditional logging alongside structlog so I tried this:

    logger = structlog.getLogger(__name__)
    logging.basicConfig(filename=logfile_path, level=logging.ERROR)
    logger.error("TEST")

The log file gets created but of course "TEST" doesn't show up inside it. It's just blank.

2 Answers2

1

I was able to get an example working by following the docs to log to both stdout and a file.

import logging.config
import structlog

timestamper = structlog.processors.TimeStamper(fmt="iso")
logging.config.dictConfig({
        "version": 1,
        "disable_existing_loggers": False,
        "handlers": {
            "default": {
                "level": "DEBUG",
                "class": "logging.StreamHandler",
            },
            "file": {
                "level": "DEBUG",
                "class": "logging.handlers.WatchedFileHandler",
                "filename": "test.log",
            },
        },
        "loggers": {
            "": {
                "handlers": ["default", "file"],
                "level": "DEBUG",
                "propagate": True,
            },
        }
})
structlog.configure(
    processors=[
        structlog.stdlib.add_log_level,
        structlog.stdlib.PositionalArgumentsFormatter(),
        timestamper,
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
    ],
    logger_factory=structlog.stdlib.LoggerFactory(),
    wrapper_class=structlog.stdlib.BoundLogger,
    cache_logger_on_first_use=True,
)
structlog.get_logger("test").info("hello")

If if you just wanted to log to a file you could use the snippet hynek suggested.

logging.basicConfig(filename='test.log', encoding='utf-8', level=logging.DEBUG)
jjbskir
  • 8,474
  • 9
  • 40
  • 53
-1

For structlog log entries to appear in that file, you have to tell structlog to use stdlib logging for output. You can find three different approaches in the docs, depending on your other needs.

hynek
  • 3,647
  • 1
  • 18
  • 26
  • 1
    Can you please detail your answer? I still can't seem to figure it out and couldn't find what I need from the documentation as it seems quite complicated. – AntonioDaSilva Aug 08 '22 at 19:04
  • 1
    The problem is that standard library logging *is* complicated. If you insist on using it, you'll have to spend some time learning it. The easiest way as of structlog 22.1 is to use [`structlog.stdlib.recreate_defaults(log_level=None)`](https://www.structlog.org/en/stable/api.html#structlog.stdlib.recreate_defaults) which will configure structlog to log thru stdlib and then use something like `logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)` to configure logging. – hynek Aug 11 '22 at 06:11
  • 1
    thanks! it works but the printing doesn't look as good as it did in the console: `[2m2022-08-12 14:08.49[0m [[32m[1minfo [0m] [1mHello, world![0m` whereas on the console things look like: `2022-08-11 23:30.25 [info ] Executing step step=99` – AntonioDaSilva Aug 12 '22 at 19:42
  • That is because the logs are outputted to the console with colors, but your console does not support colors. You can disable colored logs in console by setting: ```python3 structlog.dev.ConsoleRenderer(colors=False) ``` – Sagiv Oulu Sep 03 '22 at 14:32