Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Initial Version and Version 1 of logging


Ignore:
Timestamp:
05/16/06 16:35:51 (13 years ago)
Author:
jorge.vargas
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • logging

    v1 v1  
     1  this is NOT finish 
     2 
     3= Undestanding the Logger = 
     4 
     5As the original post<link to post> said this is a normal python logger so we go to http://docs.python.org/lib/module-logging.html to learn how to use it.  
     6there 2 places where logging is stored both mark by the tag [logging] your dev/prod.cfg and the config/log.cfg the idea is that log.cfg will have things that don't change based on the location. 
     7 
     8Please note <your package> is use across this doc, on your local copy it should say the name of your project's package 
     9 
     10= Using the Logger = 
     11Basically what you need is a quick read of http://docs.python.org/lib/module-logging.html the first page is sufficient for now. 
     12after that two lines in your controllers.py is all you need to get going 
     13{{{  
     14log = logging.getLogger("<your package>.controllers") 
     15}}} 
     16That is the prefered way to create a logger the param string is the name which could be anything, although it's good practice to follow a convention, here TG by default suggest to name the logger after the package/module since this is a unique name. 
     17 
     18the other line you should care about is 
     19{{{ 
     20log.debug("Happy TurboGears Controller Responding For Duty") 
     21}{{ 
     22 
     23Which as you read in http://docs.python.org/lib/module-logging.html u did right? is a log with level 10 you also should know that :) 
     24 
     25== Why not just use logging.debug(msg)? == 
     26 
     27because we want to be able to do this [http://docs.python.org/lib/multiple-destinations.html Multiple Destinations] so you can later find out if the error is on your side or on the framework just by looking at the log. You can also send diferent logs to diferent places, in general is a better practice to do it this way, and you will take full advantage of the python logging module. 
     28 
     29= TurboGears log.cfg = 
     30if you are used to the "normal" way of creating loggers, either by logging.basicConfig or [http://docs.python.org/lib/logging-config-fileformat.html files] you may get confused by this format. 
     31 
     32So lets start with the format this is a ConfigObj and its format is at [http://www.voidspace.org.uk/python/configobj.html#the-config-file-format ConfigObj File Format] for you the framework user the only diference from [http://docs.python.org/lib/module-ConfigParser.html ConfigParser] is the extra nested tags (\[\]) and by now you should know that those generate a dict inside another. On the other hand if you want to explore the goodies of ConfigObj Here are the [http://www.voidspace.org.uk/python/configobj.html docs] 
     33 
     34by the way if you ever want to store python type in a config file [http://www.voidspace.org.uk/python/configobj.html#unrepr-mode unrepr] is what you need which is exactly what TG is doing and yes those are format strings and python lists on the default log.cfg 
     35 
     36== What is this *()  == 
     37think of it as %() 
     38=== Why? === 
     39http://trac.turbogears.org/turbogears/browser/tags/0.9a5/turbogears/config.py#L117 and if you still dont believe me  
     40http://trac.turbogears.org/turbogears/browser/tags/0.9a5/turbogears/config.py#L23 now can we go on? 
     41 
     42== log.cfg format== 
     43So the file always starts with  
     44{{{ 
     45[logging] 
     46}}} 
     47This is the head if the logging cfg, if we ever more this to other file the core will still work thanks to configObj 
     48 
     49then you have 3 sections  
     50{{{ 
     51[[formatters]] 
     52[[handlers]] 
     53[[loggers]] 
     54}}} 
     55 
     56where all are optional although you should at least have \[\[handlers\]\]  
     57after this all lvl 3 are just names which as all dict keys must be unique 
     58 
     59== Formatters == 
     60=== format key === 
     61each lvl 3 aggregate should have only one key call format which becomes the fmt param of a [http://docs.python.org/lib/node357.html Formatter Object], there you can see all the possible values this can have, as well as what happens went ommited 
     62 
     63== handlers == 
     64=== class key === 
     65each handler must have at least a class key which has to be one of [http://docs.python.org/lib/node345.html Handler Objects] and yes you can subclass it but I think you will have enough with the defaults, also TG will error out since your class is not part of logging.__dict__ 
     66=== args key === 
     67the "optional" args key are the parameters pass to each subclass of Handler 
     68=== level key === 
     69the level key indicates the loggin level of this handler this can be any of the default levels DEBUG, INFO, WARNING, ERROR and CRITICAL or a string with the number, i got a patch to fix this TODO summit patch 
     70=== formatter key === 
     71formatter any lvl 3 name form formatters  
     72if level is ommited level=NOTSET if formatter is omitted the default is used '%(message)s' 
     73 
     74{{{ 
     75... 
     76[[[full_content]]] 
     77format='*(asctime)s *(name)s *(levelname)s *(message)s' 
     78... 
     79[[[debug_out]]] 
     80class='StreamHandler' 
     81level='DEBUG' 
     82args='(sys.stdout,)' 
     83formatter='full_content' 
     84}}} 
     85So now this makes sence We are creating a StreamHandler to sys.stdout with lvl debug using the formatted defined above  
     86 
     87== loggers == 
     88This is a another way to create [http://docs.python.org/lib/node341.html Logger Objects]  You can either define them here or do the calls in your code, it depends on your situation/taste there for I'll make a reference to the method call and you will know how to do it both ways and I'll type it ones 
     89=== qualname === 
     90name of this logger,  
     91log=logging.getLogger(qualname) 
     92if omitted this is the root logger 
     93log=logging.getLogger() 
     94=== level ===  
     95log.setLevel(level) 
     96=== handlers ===  
     97handlers is a list so  
     98for handler in handlers: 
     99 log.addHandlers(handler) 
     100=== propagate ===  
     101 log.propagate=propagate 
     102 
     103== Putting it all together== 
     104 
     105=== in log.cfg === 
     106 
     107{{{ 
     108[logging] 
     109[[formatters]] 
     110[[[message_only]]] 
     111format='*(message)s' 
     112 
     113[[[full_content]]] 
     114format='*(asctime)s *(name)s *(levelname)s *(message)s' 
     115 
     116[[handlers]] 
     117[[[debug_out]]] 
     118class='StreamHandler' 
     119level='DEBUG' 
     120args='(sys.stdout,)' 
     121formatter='full_content' 
     122 
     123[[[access_out]]] 
     124class='StreamHandler' 
     125level='INFO' 
     126args='(sys.stdout,)' 
     127formatter='message_only' 
     128 
     129[[[error_out]]] 
     130class='StreamHandler' 
     131level='ERROR' 
     132args='(sys.stdout,)' 
     133}}} 
     134 
     135We define 2 formatters named message_only and full_content, then we define 3 handlers which all Stream to stdout with diferent levels and using the two formaters we define, and we have no loggers because we are handling that from controllers.py 
     136 
     137=== In dev.cfg === 
     138{{{ 
     139[logging] 
     140 
     141[[loggers]] 
     142[[[your_project]]] 
     143level='DEBUG' 
     144qualname='<your package>' 
     145handlers=['debug_out'] 
     146 
     147[[[allinfo]]] 
     148level='INFO' 
     149handlers=['debug_out'] 
     150 
     151[[[access]]] 
     152level='INFO' 
     153qualname='turbogears.access' 
     154handlers=['access_out'] 
     155propagate=0 
     156}}} 
     157 
     158We define 3 loggers [[[your_project]]] which is the one we use at the start of this tutorial that prints DEBUG messages to stdout, [[[allinfo]]] which is the main logger (notice missing qualname) and [[[access]]] that prints INFO messages to stdout. 
     159 
     160So now that you finally undestand how it works it's time to turn it around and do lots of stuff with it check out (LoggingConfiguration move this to LoggingConfigurationExamples?, and add an explanation) for some nice examples. 
     161 
     162= Custom level Logging = 
     163TODO add patch to add custom levels