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 Version 3 and Version 4 of logging


Ignore:
Timestamp:
05/16/06 17:18:01 (13 years ago)
Author:
jorge.vargas
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • logging

    v3 v4  
    9595This 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 
    9696=== qualname === 
    97 name of this logger,  
    98 log=logging.getLogger(qualname) 
    99 if omitted this is the root logger 
    100 log=logging.getLogger() 
    101 === level ===  
    102 log.setLevel(level) 
    103 === handlers ===  
    104 handlers is a list so  
    105 for handler in handlers: 
    106  log.addHandlers(handler) 
    107 === propagate ===  
    108  log.propagate=propagate 
    109  
    110 == Putting it all together== 
    111  
    112 === in log.cfg === 
    113  
    114 {{{ 
    115 [logging] 
    116 [[formatters]] 
    117 [[[message_only]]] 
    118 format='*(message)s' 
    119  
    120 [[[full_content]]] 
    121 format='*(asctime)s *(name)s *(levelname)s *(message)s' 
    122  
    123 [[handlers]] 
    124 [[[debug_out]]] 
    125 class='StreamHandler' 
    126 level='DEBUG' 
    127 args='(sys.stdout,)' 
    128 formatter='full_content' 
    129  
    130 [[[access_out]]] 
    131 class='StreamHandler' 
    132 level='INFO' 
    133 args='(sys.stdout,)' 
    134 formatter='message_only' 
    135  
    136 [[[error_out]]] 
    137 class='StreamHandler' 
    138 level='ERROR' 
    139 args='(sys.stdout,)' 
    140 }}} 
    141  
    142 We 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 
    143  
    144 === In dev.cfg === 
    145 {{{ 
    146 [logging] 
    147  
    148 [[loggers]] 
    149 [[[your_project]]] 
    150 level='DEBUG' 
    151 qualname='<your package>' 
    152 handlers=['debug_out'] 
    153  
    154 [[[allinfo]]] 
    155 level='INFO' 
    156 handlers=['debug_out'] 
    157  
    158 [[[access]]] 
    159 level='INFO' 
    160 qualname='turbogears.access' 
    161 handlers=['access_out'] 
    162 propagate=0 
    163 }}} 
    164  
    165 We 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. 
    166  
    167 So 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. 
    168  
    169 = Custom level Logging = 
    170 TODO add patch to add custom levels 
    171  
    172 That 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. 
    173  
    174 the other line you should care about is 
    175 {{{ 
    176 log.debug("Happy TurboGears Controller Responding For Duty") 
    177 }{{ 
    178  
    179 Which 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 :) 
    180  
    181 == Why not just use logging.debug(msg)? == 
    182  
    183 because 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. 
    184  
    185 = TurboGears log.cfg = 
    186 if 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. 
    187  
    188 So 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] 
    189  
    190 by 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 
    191  
    192 == What is this *()  == 
    193 think of it as %() 
    194 === Why? === 
    195 http://trac.turbogears.org/turbogears/browser/tags/0.9a5/turbogears/config.py#L117 and if you still dont believe me  
    196 http://trac.turbogears.org/turbogears/browser/tags/0.9a5/turbogears/config.py#L23 now can we go on? 
    197  
    198 == log.cfg format== 
    199 So the file always starts with  
    200 {{{ 
    201 [logging] 
    202 }}} 
    203 This is the head if the logging cfg, if we ever more this to other file the core will still work thanks to configObj 
    204  
    205 then you have 3 sections  
    206 {{{ 
    207 [[formatters]] 
    208 [[handlers]] 
    209 [[loggers]] 
    210 }}} 
    211  
    212 where all are optional although you should at least have "handlers" and "loggers" 
    213 after this all lvl 3 are just names which as all dict keys must be unique 
    214  
    215 == Formatters == 
    216 === format key === 
    217 each 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 when ommited 
    218  
    219 == handlers == 
    220 === class key === 
    221 each 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 the logging module, if you want to make a TG extension and patch this go ahead :) 
    222 === args key === 
    223 the "optional" args key are the parameters pass to each subclass of Handler 
    224 === level key === 
    225 the 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 
    226  
    227 === formatter key === 
    228 formatter any lvl 3 name form formatters  
    229 if level is ommited level=NOTSET if formatter is omitted the default is used '%(message)s' 
    230  
    231 {{{ 
    232 ... 
    233 [[[full_content]]] 
    234 format='*(asctime)s *(name)s *(levelname)s *(message)s' 
    235 ... 
    236 [[[debug_out]]] 
    237 class='StreamHandler' 
    238 level='DEBUG' 
    239 args='(sys.stdout,)' 
    240 formatter='full_content' 
    241 }}} 
    242 So now this makes sence We are creating a StreamHandler to sys.stdout with lvl debug using the formatted defined above  
    243  
    244 == loggers == 
    245 This 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 therefore 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 :) 
    246  
    247 === qualname === 
    248 name of this logger. 
    249  
     97name of this logger 
    25098{{{ 
    25199if qualname: 
    252100log=logging.getLogger(qualname) 
    253 else 
    254 log=logging.getLogger() #root logger 
     101else: 
     102log=logging.getLogger() 
    255103}}} 
    256  
    257104=== level ===  
    258105{{{ 
     
    269116log.propagate=propagate 
    270117}}} 
     118 
     119And no those are "examples" it's not the way TG does it. 
    271120 
    272121== Putting it all together == 
     
    302151}}} 
    303152 
    304 We 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 
    305  
     153We 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. 
    306154=== In dev.cfg === 
    307155{{{ 
     
    327175We 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. 
    328176 
    329 NOTE: your_project was a bug in the code generator this has been fix in r1367. and is part of 0.9a6 
     177NOTE: "your_project" is no longer there as of r1367 and 0.9a6, it was a "typo"  
    330178 
    331 So 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. 
     179= What now = 
     180 
     181Now 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. 
    332182 
    333183= Custom level Logging =