1

I am currently developing a core utils package where I want to set some logging properties (I know that this is not best practice, but it´s for interal purposes and intended to generate logs). When I now import the package nothing gets logged:

# core.__main__.py

class BaseLoggerConfig(BaseModel):

    LOG_FORMAT: str = "%(levelprefix)s %(asctime)s  %(name)s:%(lineno)d: %(message)s"
    DATEFMT: str = "%Y-%m-%d %H:%M:%S"

    LOG_LEVEL: int = logging.INFO

    version: int = 1
    disable_existing_loggers: bool = False
    formatters: dict = {
        "default": {
            # "()": "uvicorn.logging.DefaultFormatter",
            "fmt": LOG_FORMAT,
            "datefmt": DATEFMT,
        },
    }
    filters: dict = {}

    handlers: dict = {
        "default": {
            "formatter": "default",
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stderr",
        }
    }

    loggers: dict = {}

    def __init__(self, name: str, **data):
        super().__init__(**data)

        self.loggers[name] = {
            "handlers": ["default"],
            "level": self.LOG_LEVEL,
            "propagate": False,
        }

LOG_CONFIG = BaseLoggerConfig(__name__)

logging.config.dictConfig(LOG_CONFIG)


- core.__main__
  Level: INFO
  Handlers: ['StreamHandler']

I now have logging in my other files, like:

# core.utils
import logging

logger = logging.getLogger(__name__)

def test():
    logger.info(f"I am a log from {__name__}")

# test.py
import logging
from core.utils import test

logger = logging.getLogger(__name__)

test()


What am I missing?

1
  • Which version of Python are you using Bennimi? Commented Nov 30, 2024 at 2:55

1 Answer 1

2

There are a couple of tweaks that need to be made here.

First, the file in which you configure your loggers should not be core/__main__.py, it should be core/__init__.py. __main__.py is used when you want to python -m core, which would run __main__.py.

Second, the fmt key in your formatter config should be called format. You can see the official docs for logging.config.

Third, in your LOG_FORMAT, levelprefix is not a valid field name. You probably want to use levelname which is "INFO", "DEBUG", etc.

Putting it all together:

# core/__init__.py

import logging
import logging.config

from pydantic import BaseModel


class BaseLoggerConfig(BaseModel):

    LOG_FORMAT: str = "%(levelname)s %(asctime)s  %(name)s:%(lineno)d: %(message)s"
    DATEFMT: str = "%Y-%m-%d %H:%M:%S"

    LOG_LEVEL: int = logging.INFO

    version: int = 1
    disable_existing_loggers: bool = False
    formatters: dict = {
        "default": {
            # "()": "uvicorn.logging.DefaultFormatter",
            "format": LOG_FORMAT,
            "datefmt": DATEFMT,
        },
    }
    filters: dict = {}

    handlers: dict = {
        "default": {
            "formatter": "default",
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stderr",
        }
    }

    loggers: dict = {}

    def __init__(self, name: str, **data):
        super().__init__(**data)

        self.loggers[name] = {
            "handlers": ["default"],
            "level": self.LOG_LEVEL,
            "propagate": False,
        }

LOG_CONFIG = BaseLoggerConfig(__name__)

logging.config.dictConfig(LOG_CONFIG)
# core/utils.py

import logging

logger = logging.getLogger(__name__)

def test():
    logger.info(f"I am a log from {__name__}")
# test.py

import logging
from core.utils import test

logger = logging.getLogger(__name__)

test()

Output:

INFO 2024-11-30 11:06:28  core.utils:8: I am a log from core.utils

EDIT: I realized that your %(levelprefix)s comes from uvicorn's formatter. In that case, you can uncomment your line

            # "()": "uvicorn.logging.DefaultFormatter",

and undo changing the key to format. Which means:

# core/__init__.py

# ...

class BaseLoggerConfig(BaseModel):

    LOG_FORMAT: str = "%(levelprefix)s %(asctime)s  %(name)s:%(lineno)d: %(message)s"
    DATEFMT: str = "%Y-%m-%d %H:%M:%S"

    # ...

    formatters: dict = {
        "default": {
            # "()": "uvicorn.logging.DefaultFormatter",
            "format": LOG_FORMAT,
            "datefmt": DATEFMT,
        },
    }

    # ...

Output: ("INFO" text is green)

INFO:     2024-12-01 14:13:14  core.utils:6: I am a log from core.utils
Sign up to request clarification or add additional context in comments.

5 Comments

this works but it does not seels to obey my formatting rules for some reasons.. is it bc of the uvicorn logger?
Not sure what formatting rules you want? I used your "fmt" format string, with one change (levelprefix is not a valid field, so I replaced it with levelname, like I mentioned).
I just realized that you're trying to use uvicorn's log formatter. I edited my answer to address that. @Bennimi
you are right, I duno why I assumed the package would start from main.. and yes I was initially planning on having the uvicorn formatter. Thanks for your support!
No problem, glad to help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.