[Freeipa-devel] [PATCH 53/53] ticket 2022 - modify codebase to utilize IPALogManager, obsoletes logging

Martin Kosek mkosek at redhat.com
Fri Nov 18 08:04:59 UTC 2011


On Thu, 2011-11-17 at 11:17 -0500, John Dennis wrote:
> On 11/16/2011 07:35 AM, Martin Kosek wrote:
> > On Tue, 2011-11-15 at 14:41 -0500, John Dennis wrote:
> >>
> >> --
> >> John Dennis<jdennis at redhat.com>
> >>
> >> Looking to carve out IT costs?
> >> www.redhat.com/carveoutcosts/
> >
> > Hi John,
> >
> > thanks for your patch, that was a fair amount of work there :-) I tested
> > them both and have few comments:
> >
> > 1) Patch 53 will need rebasing
> 
> O.K. will rebase.
> >
> > 2) Logging for install tools (ipa-server-install, ...) is now broken.
> > DEBUG level messages should get to /var/log/ipaserver-install.log even
> > when the installer is run without --debug. My
> > ipaserver-install.log/ipaserver-uninstall.log was silent when i run just
> > `ipa-server-install' without --debug flag
> 
> Yes you're right, it's supposed to always log to the file at the debug 
> level. Sorry that slipped by, it's a trivial one word fix in 
> standard_logging_setup(), done.

Ok.

> 
> > 3) Patch 53 touches most of our Python sources as it changes all
> > logging.* calls to log_mgr.root_logger.* calls. I think this may cause
> > problems (comment 1 is a good example). For example we may not be able
> > to cherry-pick most of new patches from master branch to ipa-2-1 branch
> > or other branches that do not use log_mgr.
> >
> > Additionally, typing "log_mgr.root_logger.*" whenever I want to log
> > anything seems a bit awkward to me. These issues are avoidable, however.
> > Since all our Python code use just the root_logger, can we just simply
> > export root logger in log_manager.py namespace and that import it as
> > "logging" in other modules? Then we would save *a lot* of changes across
> > all our code. Something like this:
> >
> > log_manager.py:
> > ---------------
> >   log_mgr = IPALogManager()
> >   log_mgr.configure(dict(default_level='error',
> >                          handlers=[dict(name='console',
> >                                         stream=sys.stderr)]),
> >                     configure_state='default')
> > +root_logger = log_mgr.root_logger
> >
> > ipa-server-install:
> > -------------------
> > +from ipapython.log_manager import root_logger as logginng
> >
> > ...
> > # now, all logging will work as usual:
> > logging.error('Some files have not been restored, see /var/lib/ipa/sysrestore/sysrestore.index')
> 
> Cherry picking patches between branches with out performing any editing 
> to apply the patch is a nice goal but perhaps not realistic. However 
> you're absolutely right this change introduces an extra step during 
> patch/rebase.
> 
> A larger question is should we continue to support the idea of having 
> log functions hung off a module name. Here's my thinking on that. But 
> skip to item 3 if you want a compromise solution.
> 
> 
> 1) I'm a bit concerned that co-opting or borrowing the logging module 
> name and using it for an entirely different purpose. Importing the name 
> "logging" and not have it be the Python logging module as most Python 
> programmers would be the source of needless confusion. Personally I 
> think I would be annoyed if someone had played that game because nothing 
> would be as I expect. The name "logging" implies the logging module with 
> all sorts of names, constants, objects, classes, sub-modules, etc. 
> associated with it, none of that would retain any of it's conventional 
> meaning. I much prefer clarity and to call something what it is and not 
> obfuscate for temporary expediency.
> 
> 2) The current Python logging implementation is broken IMHO and was the 
> source of some of our problems, I'm not sure I want to perpetuate that. 
> It exported a set of "convenience" functions bound to a global. It made 
> using the logging module easier to use via globals but at the expense of 
> all sorts of conflicts when more than one client of logging tried to 
> manipulate the same shared global objects.
> 
> The logging.debug(), etc. names are a bogus mapping of a top level 
> module symbol to a bound method of a specific instantiated object, an 
> object available externally only by calling a defined API to retrieve 
> that object from singleton manager by name. To my mind this is the 
> classic abuse of globals every textbook warns against. It's just bad 
> programming best avoided IMHO.
> 
> Why is it O.K. to have a global log_mgr object for IPA?
> 
>    a) Because it belongs to us, it's not shared with every piece of
>       Python code which imports the logging module.
> 
>    b) It's not abusing a top level module symbol to be a short circuit
>       reference into some other instantiated object. The root logger
>       belongs to the log_mgr instance shared by loaded IPA components.
>       Think of it as an IPA singleton.
> 
> 3) Can we have a shorter name as a compromise? Sure, I have no problems
>     with that. We already have the log_mgr as a single imported instance.
>     I don't see why we couldn't have also import the symbol
>     "root_logger" which is log_mgr.root_logger. I'm not keen on shorting
>     the name much more, for instance to "logger" because that's too
>     generic and obscures the fact it's the root logger, an important
>     distinction to maintain.
> 
>     An other option would be to have a LogManager object export the
>     debug(), info(), error(), critical(), & exception() methods where
>     they are bound to the LogManager's root_logger instance. This is
>     somewhat akin to what the standard Python logging module, except
>     they performed the binding on the module level and not on an
>     instance (the source of many problems). Those log methods *must*
>     be bound to a Logger object as such I'm not entirely keen on
>     binding them to a LogManager instance because once again you
>     end up providing an abused short cut which hides what is really
>     going on. I think it would benefit programmers if they knew they
>     were logging to a Logger and if so which one, because after all
>     once you try to customize things like "which loggers emit which
>     which messages" it would be really helpful to know you're dealing
>     with a Logger and which one it is and not obscure which one it is
>     to shorten the reference to it as a convenience via some short cut.
>     But if there is a consensus I could bend on this issue.
> 
>     That means we could have one of the two (I prefer the first)
> 
>     root_logger.debug()
> 
>     -or-
> 
>     log_mgr.debug() # Not a fan of this because it hides the important
>                     # concept of debug() being bound to the root_logger.
> 
>     As for:
> 
>     logging.debug()
> 
>     For the reasons pointed out in 1 I'd like to avoid that kind of
>     symbol abuse.
> 
> 

Ok, these are all valid arguments. I know that abusing "logging" is not
right, I was just afraid that diverging master branch from our 2.x
branch that much would do more harm (and extra effort whenever a patch
from master is backported to 2.x branch) that misusing the "logging"
name. I would like some second opinion on that before we make the call.

I think having root_logger exported to our tools and calling
root_logger.warning(...) etc. looks better than the previous version
(log_mgr.root_logger.warning()).

Martin




More information about the Freeipa-devel mailing list