问题描述
在Google App Engine标准环境中针对python3.8的Google Cloud Logging设置过程中,我遇到了问题。 我将FastAPI与独角兽一起使用。我的代码记录配置:
import logging.config
import sys
from google.cloud import logging as google_logging
from app.settings import ENV,_settings
if _settings.ENV == ENV.LOCAL:
MAIN_LOGGER = 'console'
LOGGER_CONF_DICT = {
'class': 'logging.StreamHandler','formatter': 'verbose','stream': sys.stdout,'level': _settings.LOG_LEVEL.upper(),}
else:
log_client = google_logging.Client()
MAIN_LOGGER = 'stackdriver_logging'
LOGGER_CONF_DICT = {
'class': 'app.gcloud_logs.GCLHandler','client': log_client,'name': 'appengine.googleapis.com%2Frequest_log'
# I've tried other names: stdout,%2FA instead of / symbol,appengine.googleapis.com/stdout
# the same result or no logs at all
}
LOGGING = {
'version': 1,'disable_existing_loggers': False,'formatters': {
'verbose': {
'format': '%(log_color)s%(asctime)s [%(levelname)s] [%(name)s] %(message)s (%(filename)s:%(lineno)d)','()': 'colorlog.ColoredFormatter','log_colors': {
'DEBUG': 'cyan','INFO': 'green','WARNING': 'yellow','ERROR': 'red','CRITICAL': 'bold_red',},}
},'handlers': {
MAIN_LOGGER: {**LOGGER_CONF_DICT},'blackhole': {'level': 'DEBUG','class': 'logging.NullHandler'},'loggers': {
'fastapi': {'level': 'INFO','handlers': [MAIN_LOGGER]},'uvicorn.error': {'level': 'INFO','handlers': [MAIN_LOGGER],'propagate': False},'uvicorn.access': {'level': 'INFO','uvicorn': {'level': 'INFO','google.cloud.logging.handlers.transports.background_thread': {'level': 'DEBUG','handlers': ['blackhole'],'': {
'level': _settings.LOG_LEVEL.upper(),'propagate': True,}
}
logging.config.dictConfig(LOGGING)
我的日志记录处理程序代码:
import os
from typing import Any,Dict,Optional
from google.cloud.logging.handlers import CloudLoggingHandler
from google.cloud.logging.resource import Resource
from starlette.requests import Request
from starlette_context import context
from app.settings import _settings
class GCLHandler(CloudLoggingHandler):
def emit(self,record):
message = super(GCLHandler,self).format(record)
request: Optional[Request] = None
trace: Optional[str] = None
span_id: Optional[str] = None
user_id: Optional[int] = None
resource = Resource(
type='gae_app',labels={
'module_id': os.environ['GAE_SERVICE'],'project_id': _settings.PROJECT_NAME,'version_id': os.environ['GAE_VERSION'],'zone': 'us16' # tried without zone - the same result
}
)
labels: Dict[str,Any] = {}
if context.exists(): # I'm sure that it works
request = context.get('request') # I'm sure that it works
user_id = context.get('user_id') # I'm sure that it works
if user_id is not None:
labels['user_id'] = user_id
if request:
if request.headers.get('X-Cloud-Trace-Context'):
cloud_trace = request.headers.get('X-Cloud-Trace-Context').split('/')
if len(cloud_trace) > 1:
span_id = cloud_trace[1].split(';')[0]
trace = f'projects/{_settings.PROJECT_NAME}/traces/{cloud_trace[0]}'
labels['logging.googleapis.com/trace'] = cloud_trace[0] # Found in some guides,not sure that its neccessary
labels['appengine.googleapis.com/trace_id'] = cloud_trace[0] # Found in some guides,not sure that its neccessary
self.transport.send(
record,message,resource=resource,labels=labels,trace=trace,span_id=span_id
)
在日志查看器中我得到了一些奇怪的结果,即我的日志与请求日志具有相同的跟踪,但是没有将它们分组
有什么想法吗?
解决方法
App Engine中有两种日志类型:
-
请求日志:发送到您的应用程序的请求的日志。 App Engine会在请求日志中自动创建条目。
-
应用程序日志:按照此页面上的说明记录您写入支持的框架或文件的条目。
这两个日志均由App Engine标准自动发送到 Cloud Logging Agent 。
在第一次请求时,应用程序日志和请求日志不相关,这就是为什么未在组中显示的原因,这是known issue stated in App Engine Official Documentation。但是,在第二个请求中,您可以看到日志显示在一个组中。
已经为此行为在Public Issue Tracker中创建了功能请求,您将在其中获得有关此修复程序的所有更新。
,S = list(range(2008,2020))
将名称更改为log_client = google_logging.Client()
MAIN_LOGGER = 'stackdriver_logging'
LOGGER_CONF_DICT = {
'class': 'app.gcloud_logs.GCLHandler','client': log_client,'name': 'app'
}
会有帮助