How to set timestamps on GMT/UTC on Python logging?
Asked Answered
R

7

75

Is it possible and how to set the logging timezone to GMT?

(i.e. the %(asctime)s parameter in the format)

Roslyn answered 12/6, 2011 at 9:16 Comment(0)
D
98
logging.Formatter.converter = time.gmtime

(documented in the docstring of logging.Formatter.formatTime)

Diastrophism answered 12/6, 2011 at 9:31 Comment(7)
And I've now also updated the official HTML documentation - should show up soon for 3.2 and 3.3, and in a few days for 2.7.Acutance
Described here. If you want to attach formatter to a handler, you first need to create a formatter with formatter = logging.Formatter(fmt), then do formatter.converter = time.gmtime, then myHandler.setFormatter(formatter)Cicerone
@VinaySajip How to set it in a logging dictConfig? I use Django that uses a logging.dictConfig to configure the logging part. ThanksFajardo
@YAmikep see the answer by rakslice for one way to do it.Acutance
@VinaySajip Ok thanks, I had to set '()' : 'my.package.customFormatterFactory', We cannot set the 'class': 'my.package.customFormatterFactory' for a formatter.Fajardo
Any idea on how to make it work as well for django.request logger? #62315086Alurta
@Alurta setting logging.Formatter.converter = time.gmtime will work for any formatter that inherits from the logging.Formatter class. Just check whether Django formatter is inheriting from Python's main Formatter class, which I bet it does.Scalenus
J
8

From the python 3 docs:

import time

class UTCFormatter(logging.Formatter):
    converter = time.gmtime

https://docs.python.org/3/howto/logging-cookbook.html#formatting-times-using-utc-gmt-via-configuration

Joviality answered 21/2, 2020 at 15:45 Comment(0)
T
7

Just setting logging.Formatter.converter = time.gmtime is ineffective for me in Python 2.5.

So I created a child class with it set, and use that in place of logging.Formatter:

class UTCFormatter(logging.Formatter):
    converter = time.gmtime
Triserial answered 30/11, 2011 at 23:13 Comment(1)
Worked for me in Python 2.7. Added a suggested edit showing the YAML syntax for instantiation, since it's a bit tricky. (There's no need for a __init__() method, as my first edit suggested.)Julenejulep
B
3

Here is code example:

import logging, logging.handlers
import time

logit = logging.getLogger('logit')
handler = logging.handlers.RotatingFileHandler("file.log", maxBytes=20000, backupCount=5)
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s %(levelname)8s: %(message)s')
handler.setFormatter(formatter)
logging.Formatter.converter = time.gmtime
logit.addHandler(handler)

logit.info("test log message")

Output:

2019-11-14 16:34:22,967     INFO: test log message
Begone answered 14/11, 2019 at 16:39 Comment(0)
R
1

I had problems getting the popular answers from this post and similar posts related to using time.gmtime with the logging converter. I stumbled across this helpful post about logging timestamps in iso8601 which sent me in the right direction to eventually solve my issue.

This solution works in Python 3.10.8. It involved setting the converter = time.gmtime and overriding the formatTime. This may be unnecessary in future releases of Python and there may be an easier way to do it as well. Note, setting converter = time.gmtime() will not work and results in an error.

import logging
import time

class UtcIsoFormatter(logging.Formatter):
  """Custom logging.Formatter class for logging UTC time in ISO8601 format
  """
  
  # Use gmtime or universal coordinated time or utc
  converter = time.gmtime # must not include '()'
  
  # Format the time for this log event
  def formatTime(self, record, datefmt=None):
    ct = self.converter(record.created)
    if datefmt:
      s = time.strftime(datefmt, ct)
    else:
      # Default UTC ISO8601 format of "YYYY-mm-ddTHH:MM:SS.fffZ"
      t = time.strftime("%Y-%m-%dT%H:%M:%S", ct)
      s = f"{t}.{record.msecs:03.0f}Z"
    return s

logger = logging.getLogger(__name__)
logger.setLevel(level="DEBUG")

formatter = UtcIsoFormatter(fmt="%(asctime)s - %(levelname)s - %(message)s")

logHandlerConsole = logging.StreamHandler()
logHandlerConsole.setFormatter(formatter)
logger.addHandler(logHandlerConsole)

logger.debug("Testing")
Rettarettig answered 14/7, 2023 at 21:6 Comment(0)
I
-1

This works:

os.environ['TZ'] = 'UTC'
time.tzset()

But does change the TZ environment for the whole process and any sub-processes. Not necessarily a bad thing, but something to be aware of before doing this.

Alternately if you set the TZ environment variable from outside (whether just in whatever runs the python, or at a whole system level) before you run python, that also works.

Introversion answered 2/12, 2021 at 0:56 Comment(0)
H
-3

I've had problems with both of these answers. So I just changed global timezone for the whole script:

os.environ['TZ'] = 'Europe/London'
time.tzset()
Haynor answered 22/4, 2012 at 10:31 Comment(4)
Be careful as London is not on GMT time in the summer.Royo
I found this was the answer that worked, using Python 2.7 on Linux. Worth checking using the Linux tzselect command that whatever you specify is a valid timezone on your system, and testing outside Python with the 'date' command. Django seems to handle this OK for its setup, but I'm getting the wrong timezone when doing Python logging from non-Django Python scripts.Daytoday
This is incorrect! The timezone in London is not guaranteed to be UTC forever.Wasson
It is an interesting approach, yet this changes the timezone for the entire process, which might have some unwanted side effects, like if you only wanted to change the timezone of the displayed time, but not for other stuff.Riposte

© 2022 - 2024 — McMap. All rights reserved.