[ python-Feature Requests-1190689 ] logging module root logger name

SourceForge.net noreply at sourceforge.net
Thu Apr 28 09:36:02 CEST 2005


Feature Requests item #1190689, was opened at 2005-04-27 01:19
Message generated for change (Comment added) made by vsajip
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=1190689&group_id=5470

Category: Python Library
Group: None
>Status: Closed
>Resolution: Fixed
Priority: 5
Submitted By: Christopher Dunn (cxdunn)
Assigned to: Vinay Sajip (vsajip)
>Summary: logging module root logger name

Initial Comment:
I would like a trailing '.' to be ignored in names
passed to getLogger(), like a trainling '/' in a Unix path.

In module 'foo':
logfoo = getLogger('.foo.')
# logger '"" should be the parent of ".foo"

Elsewhere, controlled by the user of that module:
import foo
logdefault = getLogger('.')
hdlr = StreamHandler()
fmtr = Formatter("%(name)s:%(msg)s")
hdlr.setFormatter(fmtr)
logdefault.addHandler(hdlr)


Given this change, I would also like the name of the
default logger to be displayed as '.', or even "",
rather than 'root'. The current behavior is odd:

logfoo.info("Foo message")
displays
.foo:Foo message
buf
logdefault.info("Default message")
displays
root:Default message

I NEVER mentioned the word "root" anywhere! And I don't
think it's very descriptive.

I would rather see ANY of these:
:Default message
.:Default message
default:Default message
logging:Default message

These changes would make the system more intuitive.

-cxdunn

----------------------------------------------------------------------

>Comment By: Vinay Sajip (vsajip)
Date: 2005-04-28 07:36

Message:
Logged In: YES 
user_id=308438

Logger names are hierarchical with dots separating levels in 
the hierarchy. So to me it does not make sense to have 
logger names which end in a dot, and you have given no 
reason why trailing dots should be supported. However, the 
hierarchy is not completely anologous to file system 
hierarchies - there is by design no concept of a "default" 
or "current" logger. I do not propose to make a change to this.

However, I agree that the name of the root logger being "root" 
might be seen as unintuitive by some. Of your alternatives I 
think "logging" is best. I propose to add to the documentation 
the suggestion that users can define their own name for the 
root logger as in the following example:

logging.getLogger().name = "myapp"

People who use the root logger directly typically don't use 
other (named) loggers, because the whole point of using 
named loggers is to pinpoint areas of the application. Those 
users who use the root logger directly are typically not 
interested in finer granularity than the application or script 
itself.


----------------------------------------------------------------------

Comment By: Christopher Dunn (cxdunn)
Date: 2005-04-28 07:29

Message:
Logged In: YES 
user_id=1267419

Oops. Where I wrote abspath.rstrip('.'), I meant
abspath.strip('.')
Drop both leading and trailing dots for the prettified path.
-cdunn

----------------------------------------------------------------------

Comment By: Christopher Dunn (cxdunn)
Date: 2005-04-28 07:21

Message:
Logged In: YES 
user_id=1267419

I am attaching a first pass it it.

I've stored the "absolute" names everywhere, including both
leading and trailing '.'

I call this "absolute" by analogy with os.path.abspath(). I
believe that similarities within the Python library help the
user remember key concepts.

What's missing:

 * I don't have aliases.
 * The "current working logger" is always '.'
 * And I haven't added any extra tags for the Formatter.

But those are all very simple changes. The tough part is
getting the path-searching correct. I have a big UnitTest
suite which I can send to you if you'd like.

The most important thing is that the word "root" is
completely gone, but perhaps %(name)s should translate '.'
to 'root' for backwards compatibility.

The second-most important thing is that getLogger('.')
returns the root logger.

Third is that getLogger("Package.Module") is equivalent to
getLogger(".Package.Module.")

As for tags in the Formatter, after some testing I suggest
these:

%(name)s => abspath.rstrip('.'), but "." becomes "root"
%(absname)s => abspath, with leading AND trailing dot, like
a directory, so there is no question about whether the root
displays as "." or "". It is always just dot in absolute
notation.
%(logger)s => abspath.rstrip('.'), maybe the prettiest

I must tell you that, once I figured out how the logging
module works, I really love it!

Other possible additions:

* Some useful, predefined filter classes: Never, OneTime
(which must have a reset() method to clear its cache). I can
send my version if you want.
* A PipedStreamHandler. I'm not sure how to make this work.
The idea is that, in UnitTesting, I want to read from some
stream immediately after an operation, and I want the logged
data to be immediately available, but to disappear as soon
as I've read it. Does that make sense? Right now, I use a
cStringIO object, with s.seek(0); s.truncate() after every read.

-cxdunn

----------------------------------------------------------------------

Comment By: Christopher Dunn (cxdunn)
Date: 2005-04-27 20:37

Message:
Logged In: YES 
user_id=1267419

Novices always ask, "Why did it print 'root'? Where did that
come from? 
After discussing this with some other "logging" module
users, I think we've come up with a very good idea, which
would maintain BACKWARDS COMPATIBILITY.

Essentially, treat the logging module as a shell and the
logger name as a path. Specifically,

* Let the global logging functions operate on the "current
worrking logger", which by default is "." (Let "root" be an
alias for ".")
* Change getLogger() so that it works on both absolute and
relative logger paths. (Since the default current logger is
"root", we maintain backwards compatibility.)
* Change the format function so that %(name)s shows the
relative path, if the absolute path starts with the current
working logger name.
* Add a format keyword, %(absname)s, which prints the
absolute logger path.
* Add another format keyword, %(logger)s, which prints what
most people expect to see: the absolute logger name, sans
the leading dot. (The "root" or "." logger would display as
"", exactly the way it is usually accessed.)
* Add global functions, change_current_logger() and
get_current_logger().
* Add global function, alias(). Always create an alias for
"root" to "."

Examples::
  from logging import *
  log = getLogger() #or getLogger(".") or getLogger("root")
  h1 = StreamHandler()
  f1 = Formatter("[%(name)s]%(message)s")
  h1.setFormatter(f1)
  log.addHandler(h1)
  h2 = StreamHandler()
  f2 = Formatter("[%(absname)s]%(message)s")
  h2.setFormatter(f2)
  log.addHandler(h2)
  h3 = StreamHandler()
  f3 = Formatter("[%(logger)s]%(message)s")
  h3.setFormatter(f3)
  log.addHandler(h3)
  log.error("First message")

  # ...
  child = getLogger("child") # or getLogger(".child")
  child.error("Bad news")

This should print:

[root]First message
[.]First message
[]First message
[child]Bad news
[.child]Bad news
[child]Bad news


This would create tremendous flexibility, add some clarity
to the meaning of the "root" logger, and still maintain
complete backwards compatibility.

I am willing to make the changes myself, including
UnitTests, if there is agreement that they would be adopted.
(Note that String.before() and String.after() would make the
coding a little easier/clearer, but that's a different
feature request.)

-cxdunn

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=1190689&group_id=5470


More information about the Python-bugs-list mailing list