7

I'm writing a central logging configuration file for a dozen or so Python components and I need one specific logger to log time in the UNIX time format (either milliseconds or seconds with fractions, both is good).

Is there a way to configure a formatter in the config file, to output %(asctime)s like that? I'm trying to avoid having to monkey-patch a Formatter instance in multiple independent Python scripts, and it's unfeasible to post-process the log-file.

Related: Python logging: override log time

Community
  • 1
  • 1
Irfy
  • 9,323
  • 1
  • 45
  • 67

3 Answers3

6

Just add

datefmt = %s

to your corresponding formatter config section or formatter constructor call, e.g.:

[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %s

See also logging.Formatter constructor and strftime(3).

abbot
  • 27,408
  • 6
  • 54
  • 57
  • Have you actually tried this? I know it looks like it should work, but I get `ValueError: Invalid format string` (only) when I use the small `%s`. – Irfy Feb 13 '12 at 20:18
  • Yes, works perfectly for me. See minimal working example here: https://gist.github.com/1819970 – abbot Feb 13 '12 at 20:33
  • 1
    Bah. `time.strftime` fails as described on Windows and I could confirm your solution on Linux. Apparently, Python's strftime is [documented](http://docs.python.org/library/time.html#time.strftime) as not having `%s`, so it's effectively an undocumented platform-specific feature... – Irfy Feb 13 '12 at 22:54
  • If you really need that on windows, you could consider monkey-patching `time.strftime`. `%s` is apparently supported on Linux, FreeBSD and MacOS X, but apparently it is missing on Windows and Solaris. – abbot Feb 14 '12 at 05:25
  • 1
    This solution doesn't appear to answer the original question (as posed) to give milliseconds since epoch (or seconds+fraction). It only gives seconds since epoch. Is there a variant where I could actually get milliseconds since the epoch? – higginse Feb 15 '17 at 14:31
4

I have just found the following solution:

import logging

class UnixTimeStampFormatter(logging.Formatter):
    def formatTime(self, record, datefmt = None):
        return "{0:.6f}".format(record.created)

def main():
    logChannel = logging.StreamHandler()
    logChannel.setFormatter(UnixTimeStampFormatter("%(asctime)s %(levelname)-5.5s [%(name)s] %(message)s"))
    logging.getLogger().setLevel(logging.DEBUG)
    logging.getLogger().addHandler(logChannel)
    logging.debug('hello');

if __name__ == "__main__":
    main()
user1202136
  • 11,171
  • 4
  • 41
  • 62
  • I was trying to avoid having to do something like this, because I have many independent, no-code-shared scripts that need to log the time in the asked fashion. – Irfy May 24 '13 at 10:34
3

The LogRecord object has the attribute created which is used as basis for the asctime and is already in the format you want (seconds with fractions). The easiest solution therefore might be to replace all occurrences of %(asctime)s in the format strings with %(created)f:

[formatter_generic]
format = %(created)f %(levelname)-5.5s [%(name)s] %(message)s
schot
  • 10,958
  • 2
  • 46
  • 71