Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Structlog JSON

I am currently using the python structlog JSONRenderer and hoping to change my log configuration to render the event as the 1st JSON attribute for better readability.

Current Configuration:

structlog.configure(processors=[structlog.processors.JSONRenderer()])
log = structlog.get_logger()

Current log call site:

log.msg("Response: ",
                        content_type=content_type,
                        content_length=resp.headers.get('content-length'),
                        status_code=resp.status_code
                )

Current Output:

{"content_type": "application/json", "content_length": null, "status_code": 200, "event": "Response: "}

Desired Output:

{"event": "Response: ", "content_type": "application/json", "content_length": null, "status_code": 200}

Any assistance would be greatly appreciated.

like image 638
Patrick Bray Avatar asked Oct 19 '25 11:10

Patrick Bray


2 Answers

The structlog.processors.JSONRenderer just passes the log object to json.dumps unless you specify another callable instead:

structlog.configure(processors=[structlog.processors.JSONRenderer(serializer=mydumps)])

The mydumps will then be a function that does what json.dumps does but puts event first. This could look like:

def mydumps(dic,**kw):
   mod = {}
   if 'event' in dic:
      mod["event"] = dic["event"]
   for k in dic:
      if k!="event":
         mod[k] = dic[k]
   return json.dumps(mod,**kw)

What it does is to make a new object then look for event key in the input object and put it first to the new object then proceeding to put rest of keys into the object and pass it along with **kw to json.dumps.

Note that this way you would not need to specify beforehand what other keys your logs might have (like content-type) as any event type might have different info.

like image 99
kdcode Avatar answered Oct 22 '25 02:10

kdcode


It looks like you might be using an older version of python than 3.6 which keeps keys ordered in insertion order. You can use the KeyValueRenderer to set the key order and use OrderedDict as the context_class:

from collections import OrderedDict

structlog.configure(
    processors=[
        structlog.processors.KeyValueRenderer(
            key_order=["event", "content_type", "content_length", "status_code"]
        ),
        structlog.processors.JSONRenderer()
    ],
    context_class = OrderedDict
)
log = structlog.get_logger()

Reference: KeyValueRenderer

like image 23
Abdul Aziz Barkat Avatar answered Oct 22 '25 02:10

Abdul Aziz Barkat