我正在使用Google App Engine python 3.7标准,并且试图对相关的请求日志条目进行分组。 根据{{3}}文档,我应该:
在应用程序日志的LogEntry跟踪字段中设置跟踪标识符 条目。预期格式为 项目/ [PROJECT_ID] /跟踪/ [TRACE_ID]
在何处/如何使用LogEntry?
Writing Application Logs并未显示出这种可能性。我想念什么吗?
代码示例将不胜感激。
[更新] 根据{{3}}的建议,我尝试了以下操作,但没有成功:
trace_id = request.headers.get('X-Cloud-Trace-Context', 'no_trace_id').split('/')[0]
client = logging.Client()
logger = client.logger('appengine.googleapis.com%2Fstdout') # Not shown
# logger = client.logger('projects/{}/logs/stdout'.format(GOOGLE_CLOUD_PROJECT)) # error
# logger = client.logger('projects/{}/logs/appengine.googleapis.com%2Fstdout'.format(GOOGLE_CLOUD_PROJECT)) # error
logger.log_text('log_message', trace=trace_id)
中
答案 0 :(得分:1)
Stackdriver Logging Client Library可用于实现此目的。 logger.log_text函数将LogEntry对象发送到API。示例:
from google.cloud import logging
client = logging.Client()
logger = client.logger('appengine.googleapis.com%2Fstdout')
logger.log_text('log_message', trace=trace_id)
应该从请求标头中检索trace_id,如文档所述。这样做的方法取决于您如何处理请求,但是例如在Flask中,它很简单,例如trace_id = request.headers['X-Cloud-Trace-Context'].split('/')[0]
答案 1 :(得分:1)
您可能想看看我提供的答案here。
(此答案解决了如何将日志记录严重性添加到写入Stackdriver的Cloud Functions日志中,但是基本工作流程相同)
报价:
[...],您仍然可以使用 Stackdriver Logging Client Libraries。 选中this documentation 参考Python库,以及this one 有关一些用例示例。
请注意,为了使日志位于正确的资源下, 您将需要手动配置它们,请参见this list 支持的资源类型。同样,每种资源类型都有 一些required labels 需要在日志结构中显示的内容。
编辑:
使用App Engine的示例更新上一个答案:
from google.cloud import logging
from google.cloud.logging.resource import Resource
from flask import Flask
app = Flask(__name__)
@app.route('/')
def logger():
log_client = logging.Client()
log_name = 'appengine.googleapis.com%2Fstdout'
res = Resource( type='gae_app',
labels={
"project_id": "MY-PROJECT-ID",
"module_id": "MY-SERVICE-NAME"
})
logger = log_client.logger(log_name)
logger.log_struct({"message": "message string to log"}, resource=res, severity='ERROR') # As an example log message with a ERROR warning level
return 'Wrote logs to {}.'.format(logger.name)
以该代码为例,将日志的资源类型更改为appengine.googleapis.com%2Fstdout
应该可以,并且将Resource
字段更改为与所描述的gae_app
标签中的相同在here中。
答案 2 :(得分:1)
使用Google Cloud Logging中的AppEngineHandler可以提供许多基础架构。这允许将其附加到python日志记录模块,以便进行标准的日志记录导入。
设置起来很简单:
# Setup google cloud logging.
import logging
import google.cloud.logging # Don't conflict with standard logging
from google.cloud.logging.handlers import AppEngineHandler, setup_logging
client = google.cloud.logging.Client()
handler = AppEngineHandler(client, name='stdout')
logging.getLogger().setLevel(logging.INFO)
setup_logging(handler)
https://googleapis.dev/python/logging/latest/usage.html#cloud-logging-handler上的文档建议非常相似,但不是使用AppEngineHandler,而是使用“ CloudLoggingHandler”。它还指出“ AppEngineHandler”用于灵活的环境,但这在标准的python3环境中有效。
答案 3 :(得分:0)
这是我的基本解决方案:
trace_id = request.headers.get('X-Cloud-Trace-Context', 'no_trace_id').split('/')[0]
trace_str = "projects/{}/traces/{}".format(os.getenv('GOOGLE_CLOUD_PROJECT'), trace_id)
log_client = logging.Client()
# This is the resource type of the log
log_name = 'stdout'
# Inside the resource, nest the required labels specific to the resource type
labels = {
'module_id': os.getenv('GAE_SERVICE'),
'project_id': os.getenv('GOOGLE_CLOUD_PROJECT'),
'version_id': os.getenv('GAE_VERSION')
}
res = Resource(type="gae_app",
labels=labels,
)
logger = log_client.logger(log_name)
logger.log_text("MESSAGE_STRING_TO_LOG", resource=res, severity='ERROR', trace=trace_str)
工作之后,我将其包装在一个文件中,以使其类似于Google的python2.7记录器。
这是my_gae_logging.py:
import logging as python_logging
import os
from flask import request
from google.cloud import logging as gcp_logging
from google.cloud.logging.resource import Resource
# From GCP logging lib for Python2.7
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
_levelNames = {
CRITICAL: 'CRITICAL',
ERROR: 'ERROR',
WARNING: 'WARNING',
INFO: 'INFO',
DEBUG: 'DEBUG',
NOTSET: 'NOTSET',
'CRITICAL': CRITICAL,
'ERROR': ERROR,
'WARN': WARNING,
'WARNING': WARNING,
'INFO': INFO,
'DEBUG': DEBUG,
'NOTSET': NOTSET,
}
def get_trace_id():
trace_str = None
try:
trace_id = request.headers.get('X-Cloud-Trace-Context', 'no_trace_id').split('/')[0]
trace_str = "projects/{project_id}/traces/{trace_id}".format(
project_id=os.getenv('GOOGLE_CLOUD_PROJECT'),
trace_id=trace_id)
except:
pass
return trace_str
class Logging:
def __init__(self):
self._logger = None
@property
def logger(self):
if self._logger is not None:
return self._logger
log_client = gcp_logging.Client()
# This is the resource type of the log
log_name = 'appengine.googleapis.com%2Fstdout'
# Inside the resource, nest the required labels specific to the resource type
self._logger = log_client.logger(log_name)
return self._logger
@property
def resource(self):
resource = Resource(
type="gae_app",
labels={
'module_id': os.getenv('GAE_SERVICE'),
'project_id': os.getenv('GOOGLE_CLOUD_PROJECT'),
'version_id': os.getenv('GAE_VERSION')
}
)
return resource
def log(self, text):
text = str(text)
self.logger.log_text(text, resource=self.resource, trace=get_trace_id())
def debug(self, text):
text = str(text)
self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(DEBUG), trace=get_trace_id())
def info(self, text):
text = str(text)
self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(INFO), trace=get_trace_id())
def warning(self, text):
text = str(text)
self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(WARNING), trace=get_trace_id())
def warn(self, text):
return self.warning(text)
def error(self, text):
text = str(text)
self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(ERROR), trace=get_trace_id())
def critical(self, text):
text = str(text)
self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(CRITICAL), trace=get_trace_id())
if os.getenv('GAE_VERSION'): # check if running under gcp env
logging = Logging()
else:
# when not running under gcp env, use standard python_logging
logging = python_logging
用法:
from my_gae_logging import logging
logging.warn('this is my warning')