severb / graypy

Python logging handler for Graylog that sends messages in GELF (Graylog Extended Log Format).
https://www.graylog.org/
BSD 3-Clause "New" or "Revised" License
258 stars 90 forks source link

Support RFC 5424 timestamp #99

Closed ypid-geberit closed 5 years ago

ypid-geberit commented 5 years ago

Would you be open to supporting a timestamp format as specified by RFC 5424 (section 6.2.3) for readability? I know that this is not specified by GELF 1.1 so I would suggest to make it configurable using a timestamp_format='rfc-3339' parameter.

Related standards: ISO 8601, RFC 3339.

nklapste commented 5 years ago

I'm hesitant to add functionality that conflicts with GrayLog's standard formats.

However, you could specify to include extra_fields in your graypy based GELF handler and provide a custom logging.Filter to inject custom fields into a log record. These extra fields would then be included in outputted GLEF logs.

For example for your use case of having a more readable timestamp.

import datetime
import logging

from graypy import GELFUDPHandler

class HumanTimestampFilter(logging.Filter):
    """Filter which injects a human readable timestamp into the log"""
    def filter(self, record):
        # convert the created epoch float into a ISO formatted timestamp
        record.human_timestamp = datetime.datetime.fromtimestamp(record.created).isoformat()
        return True

logger = logging.getLogger("test_logger")
logger.addHandler(GELFUDPHandler("127.0.0.1", 12202, extra_fields=True))
logger.addFilter(HumanTimestampFilter())
logger.error("Log message")

This should yield a GLEF log with a _human_timestamp field with a ISO timestamp with equivalent value to the raw log record's created epoch timestamp.

Let me know if this works for you!

Note: This was tested with the newest master (1.0.0 is still not deployed on pypy), ~but, it should work with 0.3.+.~

ypid-geberit commented 5 years ago

I like your solution to this because breaking a standard should be avoided. I was only able to get this filter working with the 1.0.0.

With the following line instead, my requirement of timestamp format as specified by RFC 5424 (section 6.2.3) is met:

record.human_timestamp = datetime.datetime.fromtimestamp(record.created, datetime.timezone.utc).astimezone().isoformat()

I commented on GELF spec 1.2 to see if there is an interest to get a RFC 5424 (section 6.2.3) compliant timestamp format supported.

You may close this issue if you like. Thanks very much for your help!