Changes between Initial Version and Version 1 of LogService

10/25/2012 05:37:17 PM (5 years ago)



  • LogService

    v1 v1  
     3The log service 
     6It's often useful to log some information during the execution of a Web 
     7application to trace the execution of the requests and to provide useful 
     8information for debugging when something goes wrong. The most common use-case is 
     9to log the exceptions tracebacks to a file on the server that provide the context 
     10where the error occurred so that we can fix the problem without disclosing 
     11sensitive information to the end-users. 
     13Python ships with a `logging`_ module that provides everything we need in a Web 
     14development context. However, it is relatively complex to configure and it's 
     15configuration is a singleton, which is problematic in a multi-applications setup 
     16(that is, when the same ``nagare-admin serve`` process serves more than one 
     19In order to solve these problems, Nagare provides its own ``log`` service 
     20(see :apidoc:`log`), which is built on top of the `logging`_ module but greatly 
     21simplifies its usage and configuration for common use-cases. 
     24Basic Usages 
     27Using The default logger 
     30By default, when you serve Web applications with the ``nagare-admin serve`` 
     31utility, Nagare creates a dedicated logger, handler and formatter for each 
     32application, and activates them: this is the purpose of the 
     33:apidoc:`log#log.configure` and :apidoc:`log#log.activate` functions. 
     35You can use the module level functions of the ``log`` module to write messages 
     36to the default logger of the *currently running* application, as shown in the 
     37example below: 
     39.. code-block:: python 
     40    :hl_lines: 8 
     42    from nagare import presentation, log 
     44    class Root(object): 
     45        pass 
     47    @presentation.render_for(Root) 
     48    def render(self, h, *args): 
     49'Rendering the Root component') 
     50        # some rendering code... 
     51        return h.root 
     53    app = Root 
     56Then, each time the default view of the ``Root`` component is rendered, this 
     57line should appear in the console shell (which is the output of the default 
     60.. code-block:: text 
     62    2012-06-14 10:22:38,379 - nagare.application.myapp - INFO - Rendering the root component 
     64As you see, the messages are issued in the ``nagare.application.myapp`` 
     65namespace, which is the namespace of the messages coming from the Nagare 
     66application called ``myapp``. 
     68Here is the full listing of the module-level functions of the ``nagare.log`` 
     71====================================== ================================================================= 
     72              Function                                             Effect 
     73====================================== ================================================================= 
     74``log.debug(msg, *args, **kw)``        Logs a message with ``DEBUG`` level on the application logger 
     75``, *args, **kw)``         Logs a message with ``INFO`` level on the application logger 
     76``log.warning(msg, *args, **kw)``      Logs a message with ``WARNING`` level on the application logger 
     77``log.error(msg, *args, **kw)``        Logs a message with ``ERROR`` level on the application logger 
     78``log.critical(msg, *args, **kw)``     Logs a message with ``CRITICAL`` level on the application logger 
     79``log.exception(msg, *args, **kw)``    Logs a message with ``ERROR`` level on the application logger, 
     80                                       and also logs the current exception information 
     81``log.log(level, msg, *args, **kw)``   Logs a message with the specified level on the application 
     82                                       logger 
     83====================================== ================================================================= 
     85All these functions accept variable arguments and keyword arguments, which are 
     86documented in the ``logging`` module, `here <>`_. 
     88Overriding the default configuration 
     91The ``[[logger]]``, ``[[hander]]`` and ``[[formatter]]`` sub-sections of the 
     92``[logging]`` section in the application configuration file are dedicated to 
     93configure the default application logger. 
     95The default logging setup is equivalent to the following ``[logging]`` section, 
     96where ``<name>`` is replaced by the name of the application (please 
     97refer to the ``logging``'s module `configuration file format`_ for a better 
     98understanding of the configuration of loggers, handlers and formatters): 
     100.. code-block:: ini 
     102    [logging] 
     104    [[logger]] 
     105    qualname=nagare.application.<name> 
     106    level=INFO 
     107    propagate=1 
     109    [[handler]] 
     110    class=StreamHandler 
     111    args=(sys.stderr,) 
     113    [[formatter]] 
     114    format=%(asctime)s - %(name)s - %(levelname)s - %(message)s 
     116As you can see, by default, the log messages with a level greater or equal to 
     117``INFO`` are printed to ``sys.stderr`` via a ``StreamHandler``. 
     119It's possible to override this default ``logging`` configuration by adding your 
     120own ``[logging]`` section to the application configuration file. Here, the 
     121logging level of the application is set to ``DEBUG``: 
     123.. code-block:: ini 
     125    [logging] 
     126    [[logger]] 
     127    level=DEBUG 
     129Here, a new handler is defined to log the messages to the file ``/tmp/myapp.log``. 
     130We use a ``RotatingFileHandler`` instead of the classical ``FileHandler`` since 
     131we want the file to be log-rotated in order to prevent it from becoming too large: 
     133.. code-block:: ini 
     135    [logging] 
     136    [[handler]] 
     137    class=handlers.RotatingFileHandler 
     138    args="('/tmp/myapp.log', 'a', 10485760, 10, 'UTF-8')" 
     140Using the Nagare IDE 
     143When the Nagare IDE is launched at the same time than your application 
     144(i.e ``nagare-admin serve <name> ide``), a second handler is bound to the default 
     145logger so that all the messages are also sent to the 
     146`IDE log panel <>`_. 
     148Advanced Usages 
     151Creating other application loggers 
     154As seen above, Nagare makes it easy to log messages in an application. However, 
     155as your application becomes more complex and is broken down in several modules 
     156and packages, it may become hard to track down where you sent a particular message 
     157or to analyze the log file which is now filled with numerous log messages. 
     159In this situation, it's generally useful to organize the log messages into 
     160namespaces, so that we can enable/disable the logging of messages in some 
     161namespaces or send messages with different namespaces to different handlers. 
     163For this purpose, Nagare offers a ``log.get_logger(namespace)`` function that 
     164creates a logger which puts the messages into the specified namespace. To create a 
     165new logger for your application, use a relative name starting with a dot. In this 
     166case, the new namespace is relative to the application namespace, e.g. 
     169The logger object offers the same functions as the ``log`` module for writing 
     170messages, that is ``logger.debug``, ````, ``logger.warning``, 
     171``logger.error``, ``logger.critical``, ``logger.exception`` and ``logger.log``, 
     172with the same parameters. 
     174In this example, we will log all the messages generated in the views to a 
     175specific ``nagare.application.myapp.ui`` namespace: 
     177.. code-block:: python 
     179    from nagare import log 
     181    @presentation.render_for(Root) 
     182    def render(self, h, *args): 
     183        log.get_logger('.ui').debug('Rendering the Root component') 
     184        # some rendering code... 
     185        return h.root 
     187and you can see, the message is now attached to the ``nagare.application.myapp.myapp.ui`` 
     190.. code-block:: text 
     192    2012-06-14 10:22:38,379 - nagare.application.myapp.ui - INFO - Rendering the root component 
     194Being under the ``nagare.application.myapp`` namespace, this logger propagates 
     195the messages to the default logger. Also this logger inherits the default logger 
     196configuration, which can be overridden: 
     198.. code-block:: ini 
     200    [[logging]] 
     201    [loggers] 
     202    keys=ui   # Declare the new logger 
     204    [[logger_ui]] 
     205    qualname=.ui    # Relative namespace 
     206    level=CRITICAL 
     207    # No specific handler: propagate the messages to the default application logger 
     208    handlers= 
     210Here the log level of the logger is set to ``CRITICAL``. 
     212Or a more complex configuration can be created, for example to log the messages 
     213to a specific log file: 
     215.. code-block:: ini 
     217    [logging] 
     218    [[loggers]] 
     219    keys=ui   # Declare the new logger 
     221    [[handlers]] 
     222    keys=logfile   # Declare the new handler 
     224    [[formatters]] 
     225    keys=simple   # Declare the new formatter 
     227    [[logger_ui]] 
     228    qualname=.ui    # Relative namespace 
     229    handlers=logfile 
     230    propagate=0   # Don't propagate the messages to the default application logger 
     232    [[handler_logfile]] 
     233    class=handlers.RotatingFileHandler 
     234    args="('/tmp/myapp_ui.log', 'a', 10485760, 10, 'UTF-8')"  # Specific log file 
     235    formatter=simple 
     237    [[formatter_simple]] 
     238    format=%(levelname)s: %(message)s 
     240Creating other loggers 
     243Any other general loggers can be created the same way, by just giving a full 
     244absolute namespace. 
     246For example the `SQLAlchemy documentation <>`_ 
     247states the name of the SQL query logger is ``sqlalchemy.engine``. So this 
     248logging configuration will display all the generated SQL queries: 
     250.. code-block:: ini 
     252    [logging] 
     253    [[loggers]] 
     254    keys=sa 
     256    [[handlers]] 
     257    keys=stderr 
     259    [[formatters]] 
     260    keys=multilines 
     262    [[logger_sa]] 
     263    qualname=sqlalchemy.engine   # The absolute SQLAlchemy logger namespace 
     264    level=INFO 
     265    handlers=stderr 
     267    [[handler_stderr]] 
     268    class=StreamHandler 
     269    args=(sys.stderr,) 
     270    formatter=multilines 
     272    [[formatter_multilines]] 
     273    format={ %(message)s } 
     276.. _`logging`: 
     277.. _`Configuration file format`: 
     279.. wikiname: NagareLogging