Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parent logger should also check the level #75045

Closed
qingyunha mannequin opened this issue Jul 6, 2017 · 10 comments
Closed

parent logger should also check the level #75045

qingyunha mannequin opened this issue Jul 6, 2017 · 10 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@qingyunha
Copy link
Mannequin

qingyunha mannequin commented Jul 6, 2017

BPO 30862
Nosy @vsajip, @bitdancer, @qingyunha
PRs
  • bpo-30862: Updated Logger.setLevel documentation. #2604
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2017-07-06.07:10:11.786>
    created_at = <Date 2017-07-06.01:06:28.236>
    labels = ['invalid', 'type-bug', 'library']
    title = 'parent logger should also check the level'
    updated_at = <Date 2017-12-07.16:41:19.574>
    user = 'https://github.com/qingyunha'

    bugs.python.org fields:

    activity = <Date 2017-12-07.16:41:19.574>
    actor = 'vinay.sajip'
    assignee = 'none'
    closed = True
    closed_date = <Date 2017-07-06.07:10:11.786>
    closer = 'vinay.sajip'
    components = ['Library (Lib)']
    creation = <Date 2017-07-06.01:06:28.236>
    creator = 'qingyunha'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 30862
    keywords = []
    message_count = 10.0
    messages = ['297791', '297799', '297810', '297814', '297830', '297834', '307535', '307765', '307787', '307818']
    nosy_count = 3.0
    nosy_names = ['vinay.sajip', 'r.david.murray', 'qingyunha']
    pr_nums = ['2604']
    priority = 'normal'
    resolution = 'not a bug'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue30862'
    versions = []

    @qingyunha qingyunha mannequin added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Jul 6, 2017
    @qingyunha
    Copy link
    Mannequin Author

    qingyunha mannequin commented Jul 6, 2017

    import logging
    
    logging.basicConfig(level=logging.ERROR)
    
    l = logging.getLogger("test")
    l.setLevel(logging.DEBUG)
    
    l.debug("Hello world")
    

    it will print 'Hello world'

    @bitdancer
    Copy link
    Member

    I will let Vinay answer definitively, but this is working as designed. This allows you to set 'debug' level on a sub-logger without getting debug output for every logger in your system, which is what you would get otherwise as the default logging level is NOTSET.

    The documentation for setLevel could probably be improved slightly in this regard, as currently you have to infer this behavior from the fact that NOTSET causes the ancestor logger's level to be used, implying that if you set it, that setting is used and not the ancestor logger's level.

    @vsajip
    Copy link
    Member

    vsajip commented Jul 6, 2017

    As RDM says, this behaviour is as designed. The logger's setLevel documentation says:

    "Sets the threshold for this logger to lvl. Logging messages which are less severe than lvl will be ignored. When a logger is created, the level is set to NOTSET (which causes all messages to be processed when the logger is the root logger, or delegation to the parent when the logger is a non-root logger). Note that the root logger is created with level WARNING.

    The term ‘delegation to the parent’ means that if a logger has a level of NOTSET, its chain of ancestor loggers is traversed until either an ancestor with a level other than NOTSET is found, or the root is reached.

    If an ancestor is found with a level other than NOTSET, then that ancestor’s level is treated as the effective level of the logger where the ancestor search began, and is used to determine how a logging event is handled.

    If the root is reached, and it has a level of NOTSET, then all messages will be processed. Otherwise, the root’s level will be used as the effective level."

    Not sure how I can improve upon that, as it seems clear enough, but any suggestions are welcome.

    @vsajip vsajip closed this as completed Jul 6, 2017
    @vsajip vsajip added the invalid label Jul 6, 2017
    @qingyunha
    Copy link
    Mannequin Author

    qingyunha mannequin commented Jul 6, 2017

    yes, I understand the effective level. my question is that before call ancestor's handler, should also check c.isEnabledFor(record.levelno)

        def callHandlers(self, record):
            """
            Pass a record to all relevant handlers.
    
            Loop through all handlers for this logger and its parents in the
            logger hierarchy. If no handler was found, output a one-off error
            message to sys.stderr. Stop searching up the hierarchy whenever a
            logger with the "propagate" attribute set to zero is found - that
            will be the last logger whose handlers are called.
            """
            c = self 
            found = 0
            while c:
                for hdlr in c.handlers:
                    found = found + 1
                    if record.levelno >= hdlr.level:
                        hdlr.handle(record)
                if not c.propagate:
                    c = None    #break out
                else:
                    c = c.parent
    ...
    

    @bitdancer
    Copy link
    Member

    @qingyunha: we are telling you that that would *introduce* a bug. This is working the way it is supposed to.

    Vinay, what if we rewrote the beginning of that paragraph like this:

    Sets the threshold for this logger to lvl. Logging messages which are less severe than lvl will be ignored, logging messages which have severity lvl or higher will be emitted by whichever handler or handlers service this logger, unless the handler's level has been set to a higher severity level than lvl.

    When a logger is created, the level is set to NOTSET....

    @vsajip
    Copy link
    Member

    vsajip commented Jul 6, 2017

    New changeset 0653fba by Vinay Sajip in branch 'master':
    bpo-30862: Updated Logger.setLevel documentation. (GH-2604)
    0653fba

    @qingyunha
    Copy link
    Mannequin Author

    qingyunha mannequin commented Dec 4, 2017

    Maybe I misunderstand. At least the basicConfig should also set the level of the handler that it created.

    @vsajip
    Copy link
    Member

    vsajip commented Dec 6, 2017

    Maybe I misunderstand.

    I think you do misunderstand. The level of the handler created by basicConfig doesn't have any level set, so it will process any message it is asked to handle. This is working as designed.

    @qingyunha
    Copy link
    Mannequin Author

    qingyunha mannequin commented Dec 7, 2017

    Sorry to disturb. When calling logging.basicConfig(level=logging.ERROR), I expect only the ERROR or above level will be logged. so the level argument if set should also pass to the handler.

    @vsajip
    Copy link
    Member

    vsajip commented Dec 7, 2017

    basicConfig() provides default behaviour for simple cases. If you don't like the defaults it provides, you can choose your own configuration code to do exactly what you want.

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants