在 python 记录器中做等效的 log_struct

Dav*_*542 7 python logging python-3.x google-cloud-platform google-cloud-stackdriver

在谷歌示例中,它给出了以下内容:

logger.log_struct({
    'message': 'My second entry',
    'weather': 'partly cloudy',
})
Run Code Online (Sandbox Code Playgroud)

我将如何在 python 的记录器中做同样的事情。例如:

import logging
log.info(
    msg='My second entry', 
    extra = {'weather': "partly cloudy"}
)
Run Code Online (Sandbox Code Playgroud)

当我在 stackdriver 中查看这个时,额外的字段没有得到正确解析:

2018-11-12 15:41:12.366 PST
My second entry

Expand all | Collapse all 

{
 insertId:  "1de1tqqft3x3ri"  
 jsonPayload: {
  message:  "My second entry"   
  python_logger:  "Xhdoo8x"   
 }
 logName:  "projects/Xhdoo8x/logs/python"  
 receiveTimestamp:  "2018-11-12T23:41:12.366883466Z"  
 resource: {…}  
 severity:  "INFO"  
 timestamp:  "2018-11-12T23:41:12.366883466Z"  
}
Run Code Online (Sandbox Code Playgroud)

我该怎么做?

我现在能做的最接近的是:

log.handlers[-1].client.logger('').log_struct("...")
Run Code Online (Sandbox Code Playgroud)

但这仍然需要第二次调用...

Voy*_*Voy 7

当前解决方案:

更新 1 - 用户 Seth Nickell改进了我提出的解决方案,所以我更新了这个答案,因为他的方法更胜一筹。以下是基于他在 GitHub 上的回复:

https://github.com/snickell/google_structlog

pip install google-structlog
Run Code Online (Sandbox Code Playgroud)

像这样使用:

pip install google-structlog
Run Code Online (Sandbox Code Playgroud)

原答案:

根据此 GitHub 线程的答案,我使用以下 bodge 将自定义对象记录为信息有效负载。它更多地来自原始_Worker.enqueue并支持传递自定义字段。

import google_structlog

google_structlog.setup(log_name="here-is-mylilapp")

# Now you can use structlog to get searchable json details in stackdriver...
import structlog
logger = structlog.get_logger()
logger.error("Uhoh, something bad did", moreinfo="it was bad", years_back_luck=5)

# Of course, you can still use plain ol' logging stdlib to get { "message": ... } objects
import logging
logger = logging.getLogger("yoyo")
logger.error("Regular logging calls will work happily too")

# Now you can search stackdriver with the query:
# logName: 'here-is-mylilapp'
Run Code Online (Sandbox Code Playgroud)

然后

from google.cloud.logging import _helpers
from google.cloud.logging.handlers.transports.background_thread import _Worker

def my_enqueue(self, record, message, resource=None, labels=None, trace=None, span_id=None):
    queue_entry = {
        "info": {"message": message, "python_logger": record.name},
        "severity": _helpers._normalize_severity(record.levelno),
        "resource": resource,
        "labels": labels,
        "trace": trace,
        "span_id": span_id,
        "timestamp": datetime.datetime.utcfromtimestamp(record.created),
    }

    if 'custom_fields' in record:
        entry['info']['custom_fields'] = record.custom_fields

    self._queue.put_nowait(queue_entry)

_Worker.enqueue = my_enqueue
Run Code Online (Sandbox Code Playgroud)

导致:

图片

这使得根据这些 custom_fields 进行过滤变得更加容易。

让我们承认这不是一个好的编程,尽管在正式支持此功能之前,似乎没有什么可以做的了。