blob: 3a05439226afb4003cad851177dcf58f25e19eaf [file] [log] [blame]
Vinay Sajipc63619b2010-12-19 12:56:57 +00001:mod:`logging.config` --- Logging configuration
2===============================================
3
4.. module:: logging.config
5 :synopsis: Configuration of the logging module.
6
7
8.. moduleauthor:: Vinay Sajip <vinay_sajip@red-dove.com>
9.. sectionauthor:: Vinay Sajip <vinay_sajip@red-dove.com>
10
Vinay Sajip01094e12010-12-19 13:41:26 +000011.. sidebar:: Important
12
13 This page contains only reference information. For tutorials,
14 please see
15
16 * :ref:`Basic Tutorial <logging-basic-tutorial>`
17 * :ref:`Advanced Tutorial <logging-advanced-tutorial>`
18 * :ref:`Logging Cookbook <logging-cookbook>`
19
20This section describes the API for configuring the logging module.
Vinay Sajipc63619b2010-12-19 12:56:57 +000021
22.. _logging-config-api:
23
24Configuration functions
25^^^^^^^^^^^^^^^^^^^^^^^
26
27The following functions configure the logging module. They are located in the
28:mod:`logging.config` module. Their use is optional --- you can configure the
29logging module using these functions or by making calls to the main API (defined
30in :mod:`logging` itself) and defining handlers which are declared either in
31:mod:`logging` or :mod:`logging.handlers`.
32
33.. function:: dictConfig(config)
34
35 Takes the logging configuration from a dictionary. The contents of
36 this dictionary are described in :ref:`logging-config-dictschema`
37 below.
38
39 If an error is encountered during configuration, this function will
40 raise a :exc:`ValueError`, :exc:`TypeError`, :exc:`AttributeError`
41 or :exc:`ImportError` with a suitably descriptive message. The
42 following is a (possibly incomplete) list of conditions which will
43 raise an error:
44
45 * A ``level`` which is not a string or which is a string not
46 corresponding to an actual logging level.
47 * A ``propagate`` value which is not a boolean.
48 * An id which does not have a corresponding destination.
49 * A non-existent handler id found during an incremental call.
50 * An invalid logger name.
51 * Inability to resolve to an internal or external object.
52
53 Parsing is performed by the :class:`DictConfigurator` class, whose
54 constructor is passed the dictionary used for configuration, and
55 has a :meth:`configure` method. The :mod:`logging.config` module
56 has a callable attribute :attr:`dictConfigClass`
57 which is initially set to :class:`DictConfigurator`.
58 You can replace the value of :attr:`dictConfigClass` with a
59 suitable implementation of your own.
60
61 :func:`dictConfig` calls :attr:`dictConfigClass` passing
62 the specified dictionary, and then calls the :meth:`configure` method on
63 the returned object to put the configuration into effect::
64
65 def dictConfig(config):
66 dictConfigClass(config).configure()
67
68 For example, a subclass of :class:`DictConfigurator` could call
69 ``DictConfigurator.__init__()`` in its own :meth:`__init__()`, then
70 set up custom prefixes which would be usable in the subsequent
71 :meth:`configure` call. :attr:`dictConfigClass` would be bound to
72 this new subclass, and then :func:`dictConfig` could be called exactly as
73 in the default, uncustomized state.
74
75.. function:: fileConfig(fname[, defaults])
76
77 Reads the logging configuration from a :mod:`configparser`\-format file named
78 *fname*. This function can be called several times from an application,
79 allowing an end user to select from various pre-canned
80 configurations (if the developer provides a mechanism to present the choices
81 and load the chosen configuration). Defaults to be passed to the ConfigParser
82 can be specified in the *defaults* argument.
83
84
85.. function:: listen(port=DEFAULT_LOGGING_CONFIG_PORT)
86
87 Starts up a socket server on the specified port, and listens for new
88 configurations. If no port is specified, the module's default
89 :const:`DEFAULT_LOGGING_CONFIG_PORT` is used. Logging configurations will be
90 sent as a file suitable for processing by :func:`fileConfig`. Returns a
91 :class:`Thread` instance on which you can call :meth:`start` to start the
92 server, and which you can :meth:`join` when appropriate. To stop the server,
93 call :func:`stopListening`.
94
95 To send a configuration to the socket, read in the configuration file and
96 send it to the socket as a string of bytes preceded by a four-byte length
97 string packed in binary using ``struct.pack('>L', n)``.
98
99
100.. function:: stopListening()
101
102 Stops the listening server which was created with a call to :func:`listen`.
103 This is typically called before calling :meth:`join` on the return value from
104 :func:`listen`.
105
106
107.. _logging-config-dictschema:
108
109Configuration dictionary schema
110^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111
112Describing a logging configuration requires listing the various
113objects to create and the connections between them; for example, you
114may create a handler named 'console' and then say that the logger
115named 'startup' will send its messages to the 'console' handler.
116These objects aren't limited to those provided by the :mod:`logging`
117module because you might write your own formatter or handler class.
118The parameters to these classes may also need to include external
119objects such as ``sys.stderr``. The syntax for describing these
120objects and connections is defined in :ref:`logging-config-dict-connections`
121below.
122
123Dictionary Schema Details
124"""""""""""""""""""""""""
125
126The dictionary passed to :func:`dictConfig` must contain the following
127keys:
128
129* *version* - to be set to an integer value representing the schema
130 version. The only valid value at present is 1, but having this key
131 allows the schema to evolve while still preserving backwards
132 compatibility.
133
134All other keys are optional, but if present they will be interpreted
135as described below. In all cases below where a 'configuring dict' is
136mentioned, it will be checked for the special ``'()'`` key to see if a
137custom instantiation is required. If so, the mechanism described in
138:ref:`logging-config-dict-userdef` below is used to create an instance;
139otherwise, the context is used to determine what to instantiate.
140
141* *formatters* - the corresponding value will be a dict in which each
142 key is a formatter id and each value is a dict describing how to
143 configure the corresponding Formatter instance.
144
145 The configuring dict is searched for keys ``format`` and ``datefmt``
146 (with defaults of ``None``) and these are used to construct a
147 :class:`logging.Formatter` instance.
148
149* *filters* - the corresponding value will be a dict in which each key
150 is a filter id and each value is a dict describing how to configure
151 the corresponding Filter instance.
152
153 The configuring dict is searched for the key ``name`` (defaulting to the
154 empty string) and this is used to construct a :class:`logging.Filter`
155 instance.
156
157* *handlers* - the corresponding value will be a dict in which each
158 key is a handler id and each value is a dict describing how to
159 configure the corresponding Handler instance.
160
161 The configuring dict is searched for the following keys:
162
163 * ``class`` (mandatory). This is the fully qualified name of the
164 handler class.
165
166 * ``level`` (optional). The level of the handler.
167
168 * ``formatter`` (optional). The id of the formatter for this
169 handler.
170
171 * ``filters`` (optional). A list of ids of the filters for this
172 handler.
173
174 All *other* keys are passed through as keyword arguments to the
175 handler's constructor. For example, given the snippet::
176
177 handlers:
178 console:
179 class : logging.StreamHandler
180 formatter: brief
181 level : INFO
182 filters: [allow_foo]
183 stream : ext://sys.stdout
184 file:
185 class : logging.handlers.RotatingFileHandler
186 formatter: precise
187 filename: logconfig.log
188 maxBytes: 1024
189 backupCount: 3
190
191 the handler with id ``console`` is instantiated as a
192 :class:`logging.StreamHandler`, using ``sys.stdout`` as the underlying
193 stream. The handler with id ``file`` is instantiated as a
194 :class:`logging.handlers.RotatingFileHandler` with the keyword arguments
195 ``filename='logconfig.log', maxBytes=1024, backupCount=3``.
196
197* *loggers* - the corresponding value will be a dict in which each key
198 is a logger name and each value is a dict describing how to
199 configure the corresponding Logger instance.
200
201 The configuring dict is searched for the following keys:
202
203 * ``level`` (optional). The level of the logger.
204
205 * ``propagate`` (optional). The propagation setting of the logger.
206
207 * ``filters`` (optional). A list of ids of the filters for this
208 logger.
209
210 * ``handlers`` (optional). A list of ids of the handlers for this
211 logger.
212
213 The specified loggers will be configured according to the level,
214 propagation, filters and handlers specified.
215
216* *root* - this will be the configuration for the root logger.
217 Processing of the configuration will be as for any logger, except
218 that the ``propagate`` setting will not be applicable.
219
220* *incremental* - whether the configuration is to be interpreted as
221 incremental to the existing configuration. This value defaults to
222 ``False``, which means that the specified configuration replaces the
223 existing configuration with the same semantics as used by the
224 existing :func:`fileConfig` API.
225
226 If the specified value is ``True``, the configuration is processed
227 as described in the section on :ref:`logging-config-dict-incremental`.
228
229* *disable_existing_loggers* - whether any existing loggers are to be
230 disabled. This setting mirrors the parameter of the same name in
231 :func:`fileConfig`. If absent, this parameter defaults to ``True``.
232 This value is ignored if *incremental* is ``True``.
233
234.. _logging-config-dict-incremental:
235
236Incremental Configuration
237"""""""""""""""""""""""""
238
239It is difficult to provide complete flexibility for incremental
240configuration. For example, because objects such as filters
241and formatters are anonymous, once a configuration is set up, it is
242not possible to refer to such anonymous objects when augmenting a
243configuration.
244
245Furthermore, there is not a compelling case for arbitrarily altering
246the object graph of loggers, handlers, filters, formatters at
247run-time, once a configuration is set up; the verbosity of loggers and
248handlers can be controlled just by setting levels (and, in the case of
249loggers, propagation flags). Changing the object graph arbitrarily in
250a safe way is problematic in a multi-threaded environment; while not
251impossible, the benefits are not worth the complexity it adds to the
252implementation.
253
254Thus, when the ``incremental`` key of a configuration dict is present
255and is ``True``, the system will completely ignore any ``formatters`` and
256``filters`` entries, and process only the ``level``
257settings in the ``handlers`` entries, and the ``level`` and
258``propagate`` settings in the ``loggers`` and ``root`` entries.
259
260Using a value in the configuration dict lets configurations to be sent
261over the wire as pickled dicts to a socket listener. Thus, the logging
262verbosity of a long-running application can be altered over time with
263no need to stop and restart the application.
264
265.. _logging-config-dict-connections:
266
267Object connections
268""""""""""""""""""
269
270The schema describes a set of logging objects - loggers,
271handlers, formatters, filters - which are connected to each other in
272an object graph. Thus, the schema needs to represent connections
273between the objects. For example, say that, once configured, a
274particular logger has attached to it a particular handler. For the
275purposes of this discussion, we can say that the logger represents the
276source, and the handler the destination, of a connection between the
277two. Of course in the configured objects this is represented by the
278logger holding a reference to the handler. In the configuration dict,
279this is done by giving each destination object an id which identifies
280it unambiguously, and then using the id in the source object's
281configuration to indicate that a connection exists between the source
282and the destination object with that id.
283
284So, for example, consider the following YAML snippet::
285
286 formatters:
287 brief:
288 # configuration for formatter with id 'brief' goes here
289 precise:
290 # configuration for formatter with id 'precise' goes here
291 handlers:
292 h1: #This is an id
293 # configuration of handler with id 'h1' goes here
294 formatter: brief
295 h2: #This is another id
296 # configuration of handler with id 'h2' goes here
297 formatter: precise
298 loggers:
299 foo.bar.baz:
300 # other configuration for logger 'foo.bar.baz'
301 handlers: [h1, h2]
302
303(Note: YAML used here because it's a little more readable than the
304equivalent Python source form for the dictionary.)
305
306The ids for loggers are the logger names which would be used
307programmatically to obtain a reference to those loggers, e.g.
308``foo.bar.baz``. The ids for Formatters and Filters can be any string
309value (such as ``brief``, ``precise`` above) and they are transient,
310in that they are only meaningful for processing the configuration
311dictionary and used to determine connections between objects, and are
312not persisted anywhere when the configuration call is complete.
313
314The above snippet indicates that logger named ``foo.bar.baz`` should
315have two handlers attached to it, which are described by the handler
316ids ``h1`` and ``h2``. The formatter for ``h1`` is that described by id
317``brief``, and the formatter for ``h2`` is that described by id
318``precise``.
319
320
321.. _logging-config-dict-userdef:
322
323User-defined objects
324""""""""""""""""""""
325
326The schema supports user-defined objects for handlers, filters and
327formatters. (Loggers do not need to have different types for
328different instances, so there is no support in this configuration
329schema for user-defined logger classes.)
330
331Objects to be configured are described by dictionaries
332which detail their configuration. In some places, the logging system
333will be able to infer from the context how an object is to be
334instantiated, but when a user-defined object is to be instantiated,
335the system will not know how to do this. In order to provide complete
336flexibility for user-defined object instantiation, the user needs
337to provide a 'factory' - a callable which is called with a
338configuration dictionary and which returns the instantiated object.
339This is signalled by an absolute import path to the factory being
340made available under the special key ``'()'``. Here's a concrete
341example::
342
343 formatters:
344 brief:
345 format: '%(message)s'
346 default:
347 format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
348 datefmt: '%Y-%m-%d %H:%M:%S'
349 custom:
350 (): my.package.customFormatterFactory
351 bar: baz
352 spam: 99.9
353 answer: 42
354
355The above YAML snippet defines three formatters. The first, with id
356``brief``, is a standard :class:`logging.Formatter` instance with the
357specified format string. The second, with id ``default``, has a
358longer format and also defines the time format explicitly, and will
359result in a :class:`logging.Formatter` initialized with those two format
360strings. Shown in Python source form, the ``brief`` and ``default``
361formatters have configuration sub-dictionaries::
362
363 {
364 'format' : '%(message)s'
365 }
366
367and::
368
369 {
370 'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
371 'datefmt' : '%Y-%m-%d %H:%M:%S'
372 }
373
374respectively, and as these dictionaries do not contain the special key
375``'()'``, the instantiation is inferred from the context: as a result,
376standard :class:`logging.Formatter` instances are created. The
377configuration sub-dictionary for the third formatter, with id
378``custom``, is::
379
380 {
381 '()' : 'my.package.customFormatterFactory',
382 'bar' : 'baz',
383 'spam' : 99.9,
384 'answer' : 42
385 }
386
387and this contains the special key ``'()'``, which means that
388user-defined instantiation is wanted. In this case, the specified
389factory callable will be used. If it is an actual callable it will be
390used directly - otherwise, if you specify a string (as in the example)
391the actual callable will be located using normal import mechanisms.
392The callable will be called with the **remaining** items in the
393configuration sub-dictionary as keyword arguments. In the above
394example, the formatter with id ``custom`` will be assumed to be
395returned by the call::
396
397 my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)
398
399The key ``'()'`` has been used as the special key because it is not a
400valid keyword parameter name, and so will not clash with the names of
401the keyword arguments used in the call. The ``'()'`` also serves as a
402mnemonic that the corresponding value is a callable.
403
404
405.. _logging-config-dict-externalobj:
406
407Access to external objects
408""""""""""""""""""""""""""
409
410There are times where a configuration needs to refer to objects
411external to the configuration, for example ``sys.stderr``. If the
412configuration dict is constructed using Python code, this is
413straightforward, but a problem arises when the configuration is
414provided via a text file (e.g. JSON, YAML). In a text file, there is
415no standard way to distinguish ``sys.stderr`` from the literal string
416``'sys.stderr'``. To facilitate this distinction, the configuration
417system looks for certain special prefixes in string values and
418treat them specially. For example, if the literal string
419``'ext://sys.stderr'`` is provided as a value in the configuration,
420then the ``ext://`` will be stripped off and the remainder of the
421value processed using normal import mechanisms.
422
423The handling of such prefixes is done in a way analogous to protocol
424handling: there is a generic mechanism to look for prefixes which
425match the regular expression ``^(?P<prefix>[a-z]+)://(?P<suffix>.*)$``
426whereby, if the ``prefix`` is recognised, the ``suffix`` is processed
427in a prefix-dependent manner and the result of the processing replaces
428the string value. If the prefix is not recognised, then the string
429value will be left as-is.
430
431
432.. _logging-config-dict-internalobj:
433
434Access to internal objects
435""""""""""""""""""""""""""
436
437As well as external objects, there is sometimes also a need to refer
438to objects in the configuration. This will be done implicitly by the
439configuration system for things that it knows about. For example, the
440string value ``'DEBUG'`` for a ``level`` in a logger or handler will
441automatically be converted to the value ``logging.DEBUG``, and the
442``handlers``, ``filters`` and ``formatter`` entries will take an
443object id and resolve to the appropriate destination object.
444
445However, a more generic mechanism is needed for user-defined
446objects which are not known to the :mod:`logging` module. For
447example, consider :class:`logging.handlers.MemoryHandler`, which takes
448a ``target`` argument which is another handler to delegate to. Since
449the system already knows about this class, then in the configuration,
450the given ``target`` just needs to be the object id of the relevant
451target handler, and the system will resolve to the handler from the
452id. If, however, a user defines a ``my.package.MyHandler`` which has
453an ``alternate`` handler, the configuration system would not know that
454the ``alternate`` referred to a handler. To cater for this, a generic
455resolution system allows the user to specify::
456
457 handlers:
458 file:
459 # configuration of file handler goes here
460
461 custom:
462 (): my.package.MyHandler
463 alternate: cfg://handlers.file
464
465The literal string ``'cfg://handlers.file'`` will be resolved in an
466analogous way to strings with the ``ext://`` prefix, but looking
467in the configuration itself rather than the import namespace. The
468mechanism allows access by dot or by index, in a similar way to
469that provided by ``str.format``. Thus, given the following snippet::
470
471 handlers:
472 email:
473 class: logging.handlers.SMTPHandler
474 mailhost: localhost
475 fromaddr: my_app@domain.tld
476 toaddrs:
477 - support_team@domain.tld
478 - dev_team@domain.tld
479 subject: Houston, we have a problem.
480
481in the configuration, the string ``'cfg://handlers'`` would resolve to
482the dict with key ``handlers``, the string ``'cfg://handlers.email``
483would resolve to the dict with key ``email`` in the ``handlers`` dict,
484and so on. The string ``'cfg://handlers.email.toaddrs[1]`` would
485resolve to ``'dev_team.domain.tld'`` and the string
486``'cfg://handlers.email.toaddrs[0]'`` would resolve to the value
487``'support_team@domain.tld'``. The ``subject`` value could be accessed
488using either ``'cfg://handlers.email.subject'`` or, equivalently,
489``'cfg://handlers.email[subject]'``. The latter form only needs to be
490used if the key contains spaces or non-alphanumeric characters. If an
491index value consists only of decimal digits, access will be attempted
492using the corresponding integer value, falling back to the string
493value if needed.
494
495Given a string ``cfg://handlers.myhandler.mykey.123``, this will
496resolve to ``config_dict['handlers']['myhandler']['mykey']['123']``.
497If the string is specified as ``cfg://handlers.myhandler.mykey[123]``,
498the system will attempt to retrieve the value from
499``config_dict['handlers']['myhandler']['mykey'][123]``, and fall back
500to ``config_dict['handlers']['myhandler']['mykey']['123']`` if that
501fails.
502
503.. _logging-config-fileformat:
504
505Configuration file format
506^^^^^^^^^^^^^^^^^^^^^^^^^
507
508The configuration file format understood by :func:`fileConfig` is based on
509:mod:`configparser` functionality. The file must contain sections called
510``[loggers]``, ``[handlers]`` and ``[formatters]`` which identify by name the
511entities of each type which are defined in the file. For each such entity, there
512is a separate section which identifies how that entity is configured. Thus, for
513a logger named ``log01`` in the ``[loggers]`` section, the relevant
514configuration details are held in a section ``[logger_log01]``. Similarly, a
515handler called ``hand01`` in the ``[handlers]`` section will have its
516configuration held in a section called ``[handler_hand01]``, while a formatter
517called ``form01`` in the ``[formatters]`` section will have its configuration
518specified in a section called ``[formatter_form01]``. The root logger
519configuration must be specified in a section called ``[logger_root]``.
520
521Examples of these sections in the file are given below. ::
522
523 [loggers]
524 keys=root,log02,log03,log04,log05,log06,log07
525
526 [handlers]
527 keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09
528
529 [formatters]
530 keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
531
532The root logger must specify a level and a list of handlers. An example of a
533root logger section is given below. ::
534
535 [logger_root]
536 level=NOTSET
537 handlers=hand01
538
539The ``level`` entry can be one of ``DEBUG, INFO, WARNING, ERROR, CRITICAL`` or
540``NOTSET``. For the root logger only, ``NOTSET`` means that all messages will be
541logged. Level values are :func:`eval`\ uated in the context of the ``logging``
542package's namespace.
543
544The ``handlers`` entry is a comma-separated list of handler names, which must
545appear in the ``[handlers]`` section. These names must appear in the
546``[handlers]`` section and have corresponding sections in the configuration
547file.
548
549For loggers other than the root logger, some additional information is required.
550This is illustrated by the following example. ::
551
552 [logger_parser]
553 level=DEBUG
554 handlers=hand01
555 propagate=1
556 qualname=compiler.parser
557
558The ``level`` and ``handlers`` entries are interpreted as for the root logger,
559except that if a non-root logger's level is specified as ``NOTSET``, the system
560consults loggers higher up the hierarchy to determine the effective level of the
561logger. The ``propagate`` entry is set to 1 to indicate that messages must
562propagate to handlers higher up the logger hierarchy from this logger, or 0 to
563indicate that messages are **not** propagated to handlers up the hierarchy. The
564``qualname`` entry is the hierarchical channel name of the logger, that is to
565say the name used by the application to get the logger.
566
567Sections which specify handler configuration are exemplified by the following.
568::
569
570 [handler_hand01]
571 class=StreamHandler
572 level=NOTSET
573 formatter=form01
574 args=(sys.stdout,)
575
576The ``class`` entry indicates the handler's class (as determined by :func:`eval`
577in the ``logging`` package's namespace). The ``level`` is interpreted as for
578loggers, and ``NOTSET`` is taken to mean 'log everything'.
579
580The ``formatter`` entry indicates the key name of the formatter for this
581handler. If blank, a default formatter (``logging._defaultFormatter``) is used.
582If a name is specified, it must appear in the ``[formatters]`` section and have
583a corresponding section in the configuration file.
584
585The ``args`` entry, when :func:`eval`\ uated in the context of the ``logging``
586package's namespace, is the list of arguments to the constructor for the handler
587class. Refer to the constructors for the relevant handlers, or to the examples
588below, to see how typical entries are constructed. ::
589
590 [handler_hand02]
591 class=FileHandler
592 level=DEBUG
593 formatter=form02
594 args=('python.log', 'w')
595
596 [handler_hand03]
597 class=handlers.SocketHandler
598 level=INFO
599 formatter=form03
600 args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
601
602 [handler_hand04]
603 class=handlers.DatagramHandler
604 level=WARN
605 formatter=form04
606 args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
607
608 [handler_hand05]
609 class=handlers.SysLogHandler
610 level=ERROR
611 formatter=form05
612 args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
613
614 [handler_hand06]
615 class=handlers.NTEventLogHandler
616 level=CRITICAL
617 formatter=form06
618 args=('Python Application', '', 'Application')
619
620 [handler_hand07]
621 class=handlers.SMTPHandler
622 level=WARN
623 formatter=form07
624 args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
625
626 [handler_hand08]
627 class=handlers.MemoryHandler
628 level=NOTSET
629 formatter=form08
630 target=
631 args=(10, ERROR)
632
633 [handler_hand09]
634 class=handlers.HTTPHandler
635 level=NOTSET
636 formatter=form09
637 args=('localhost:9022', '/log', 'GET')
638
639Sections which specify formatter configuration are typified by the following. ::
640
641 [formatter_form01]
642 format=F1 %(asctime)s %(levelname)s %(message)s
643 datefmt=
644 class=logging.Formatter
645
646The ``format`` entry is the overall format string, and the ``datefmt`` entry is
647the :func:`strftime`\ -compatible date/time format string. If empty, the
648package substitutes ISO8601 format date/times, which is almost equivalent to
649specifying the date format string ``'%Y-%m-%d %H:%M:%S'``. The ISO8601 format
650also specifies milliseconds, which are appended to the result of using the above
651format string, with a comma separator. An example time in ISO8601 format is
652``2003-01-23 00:29:50,411``.
653
654The ``class`` entry is optional. It indicates the name of the formatter's class
655(as a dotted module and class name.) This option is useful for instantiating a
656:class:`Formatter` subclass. Subclasses of :class:`Formatter` can present
657exception tracebacks in an expanded or condensed format.
658
659.. seealso::
660
661 Module :mod:`logging`
662 API reference for the logging module.
663
664 Module :mod:`logging.handlers`
665 Useful handlers included with the logging module.
666
667