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 1 and Version 2 of logging

05/16/06 16:37:25 (13 years ago)



  • logging

    v1 v2  
    1   this is NOT finish 
    3 = Undestanding the Logger = 
    5 As 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.  
    6 there 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. 
    8 Please note <your package> is use across this doc, on your local copy it should say the name of your project's package 
    10 = Using the Logger = 
    11 Basically what you need is a quick read of http://docs.python.org/lib/module-logging.html the first page is sufficient for now. 
    12 after that two lines in your controllers.py is all you need to get going 
    13 {{{  
    14 log = logging.getLogger("<your package>.controllers") 
    15 }}} 
    16 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. 
    18 the other line you should care about is 
    19 {{{ 
    20 log.debug("Happy TurboGears Controller Responding For Duty") 
    21 }{{ 
    23 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 :) 
    25 == Why not just use logging.debug(msg)? == 
    27 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. 
    29 = TurboGears log.cfg = 
    30 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. 
    32 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] 
    34 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 
    36 == What is this *()  == 
    37 think of it as %() 
    38 === Why? === 
    39 http://trac.turbogears.org/turbogears/browser/tags/0.9a5/turbogears/config.py#L117 and if you still dont believe me  
    40 http://trac.turbogears.org/turbogears/browser/tags/0.9a5/turbogears/config.py#L23 now can we go on? 
    42 == log.cfg format== 
    43 So the file always starts with  
    44 {{{ 
    45 [logging] 
    46 }}} 
    47 This is the head if the logging cfg, if we ever more this to other file the core will still work thanks to configObj 
    49 then you have 3 sections  
    50 {{{ 
    51 [[formatters]] 
    52 [[handlers]] 
    53 [[loggers]] 
    54 }}} 
    56 where all are optional although you should at least have \[\[handlers\]\]  
    57 after this all lvl 3 are just names which as all dict keys must be unique 
    59 == Formatters == 
    60 === format key === 
    61 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 went ommited 
    63 == handlers == 
    64 === class key === 
    65 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 logging.__dict__ 
    66 === args key === 
    67 the "optional" args key are the parameters pass to each subclass of Handler 
    68 === level key === 
    69 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, i got a patch to fix this TODO summit patch 
    70 === formatter key === 
    71 formatter any lvl 3 name form formatters  
    72 if level is ommited level=NOTSET if formatter is omitted the default is used '%(message)s' 
    74 {{{ 
    75 ... 
    76 [[[full_content]]] 
    77 format='*(asctime)s *(name)s *(levelname)s *(message)s' 
    78 ... 
    79 [[[debug_out]]] 
    80 class='StreamHandler' 
    81 level='DEBUG' 
    82 args='(sys.stdout,)' 
    83 formatter='full_content' 
    84 }}} 
    85 So now this makes sence We are creating a StreamHandler to sys.stdout with lvl debug using the formatted defined above  
    87 == loggers == 
    88 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 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 === 
    90 name of this logger,  
    91 log=logging.getLogger(qualname) 
    92 if omitted this is the root logger 
    93 log=logging.getLogger() 
    94 === level ===  
    95 log.setLevel(level) 
    96 === handlers ===  
    97 handlers is a list so  
    98 for handler in handlers: 
    99  log.addHandlers(handler) 
    100 === propagate ===  
    101  log.propagate=propagate 
    103 == Putting it all together== 
    105 === in log.cfg === 
    107 {{{ 
    108 [logging] 
    109 [[formatters]] 
    110 [[[message_only]]] 
    111 format='*(message)s' 
    113 [[[full_content]]] 
    114 format='*(asctime)s *(name)s *(levelname)s *(message)s' 
    116 [[handlers]] 
    117 [[[debug_out]]] 
    118 class='StreamHandler' 
    119 level='DEBUG' 
    120 args='(sys.stdout,)' 
    121 formatter='full_content' 
    123 [[[access_out]]] 
    124 class='StreamHandler' 
    125 level='INFO' 
    126 args='(sys.stdout,)' 
    127 formatter='message_only' 
    129 [[[error_out]]] 
    130 class='StreamHandler' 
    131 level='ERROR' 
    132 args='(sys.stdout,)' 
    133 }}} 
    135 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 
    137 === In dev.cfg === 
    138 {{{ 
    139 [logging] 
    141 [[loggers]] 
    142 [[[your_project]]] 
    143 level='DEBUG' 
    144 qualname='<your package>' 
    145 handlers=['debug_out'] 
    147 [[[allinfo]]] 
    148 level='INFO' 
    149 handlers=['debug_out'] 
    151 [[[access]]] 
    152 level='INFO' 
    153 qualname='turbogears.access' 
    154 handlers=['access_out'] 
    155 propagate=0 
    156 }}} 
    158 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. 
    160 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. 
    162 = Custom level Logging = 
    163 TODO add patch to add custom levels