1

我目前正在使用 python structlog JSONRenderer 并希望更改我的日志配置以将事件呈现为第一个 JSON 属性以获得更好的可读性。

当前配置:

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

当前日志调用站点:

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

电流输出:

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

期望的输出:

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

任何帮助将不胜感激。

4

2 回答 2

2

看起来您可能使用的是比 3.6 更旧的 python 版本,它使键按插入顺序排列。您可以使用KeyValueRenderer设置键顺序并OrderedDict用作 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()

参考:KeyValueRenderer

于 2021-01-26T05:00:12.257 回答
1

除非您指定另一个可调用对象,否则structlog.processors.JSONRenderer只需将日志对象传递给:json.dumps

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

然后,mydumps将是一个功能,它做什么json.dumpsevent放在第一位。这可能看起来像:

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)

它所做的是创建一个新对象,然后event在输入对象中查找键并将其首先放入新对象,然后继续将其余键放入对象中并将其与**kwto一起传递json.dumps

请注意,这样您就不需要事先指定您的日志可能具有的其他键(如内容类型),因为任何事件类型都可能具有不同的信息。

于 2021-01-26T04:59:47.817 回答