python - 使用 Google Cloud Stackdriver 在 Kubernetes Engine 上记录 Python 代码的重复日志条目

标签 python logging google-kubernetes-engine google-cloud-stackdriver python-logging

我有一个简单的 Python 应用程序在 Google Kubernetes Engine 上的容器中运行。我正在尝试将标准 Python 日志记录连接到 Google Stackdriver 日志记录 using this guide 。我几乎成功了,但我收到了重复的日志条目,其中一个始终处于“错误”级别...

<小时/>

显示重复条目的 Stackdriver 日志屏幕截图

Screenshot of Stackdriver logs showing duplicate entries

这是我的 python 代码,根据上述指南设置日志记录:

import webapp2
from paste import httpserver
import rpc

# Imports the Google Cloud client library
import google.cloud.logging
# Instantiates a client
client = google.cloud.logging.Client()
# Connects the logger to the root logging handler; by default this captures
# all logs at INFO level and higher
client.setup_logging()

app = webapp2.WSGIApplication([('/rpc/([A-Za-z]+)', rpc.RpcHandler),], debug=True)
httpserver.serve(app, host='0.0.0.0', port='80')

下面是屏幕截图中触发日志的代码:

import logging

logging.info("INFO Entering PostEchoPost...")
logging.warning("WARNING Entering PostEchoPost...")
logging.error("ERROR Entering PostEchoPost...")
logging.critical("CRITICAL Entering PostEchoPost...")

以下是完整的 Stackdriver 日志,从屏幕截图展开,其中包含错误解释的错误级别:

{
 insertId:  "1mk4fkaga4m63w1"  
 labels: {
  compute.googleapis.com/resource_name:  "gke-alg-microservice-default-pool-xxxxxxxxxx-ttnz"   
  container.googleapis.com/namespace_name:  "default"   
  container.googleapis.com/pod_name:  "esp-alg-xxxxxxxxxx-xj2p2"   
  container.googleapis.com/stream:  "stderr"   
 }
 logName:  "projects/projectname/logs/algorithm"  
 receiveTimestamp:  "2018-01-03T12:18:22.479058645Z"  
 resource: {
  labels: {
   cluster_name:  "alg-microservice"    
   container_name:  "alg"    
   instance_id:  "703849119xxxxxxxxxx"   
   namespace_id:  "default"    
   pod_id:  "esp-alg-xxxxxxxxxx-xj2p2"    
   project_id:  "projectname"    
   zone:  "europe-west1-b"    
  }
  type:  "container"   
 }
 severity:  "ERROR"  
 textPayload:  "INFO Entering PostEchoPost...
"  
 timestamp:  "2018-01-03T12:18:20Z"  
}

这是完整的 Stackdriver 日志,从屏幕截图展开,并具有正确解释的 INFO 级别:

{
 insertId:  "1mk4fkaga4m63w0"  
 jsonPayload: {
  message:  "INFO Entering PostEchoPost..."   
  thread:  140348659595008   
 }
 labels: {
  compute.googleapis.com/resource_name:  "gke-alg-microservi-default-pool-xxxxxxxxxx-ttnz"   
  container.googleapis.com/namespace_name:  "default"   
  container.googleapis.com/pod_name:  "esp-alg-xxxxxxxxxx-xj2p2"   
  container.googleapis.com/stream:  "stderr"   
 }
 logName:  "projects/projectname/logs/algorithm"  
 receiveTimestamp:  "2018-01-03T12:18:22.479058645Z"  
 resource: {
  labels: {
   cluster_name:  "alg-microservice"    
   container_name:  "alg"    
   instance_id:  "703849119xxxxxxxxxx"    
   namespace_id:  "default"    
   pod_id:  "esp-alg-xxxxxxxxxx-xj2p2"    
   project_id:  "projectname"    
   zone:  "europe-west1-b"    
  }
  type:  "container"   
 }
 severity:  "INFO"  
 timestamp:  "2018-01-03T12:18:20.260099887Z"  
}

所以,这个条目可能是关键:

container.googleapis.com/stream:  "stderr" 

看起来除了我的日志设置工作之外,来自容器的所有日志都被发送到容器中的 stderr,并且我相信默认情况下,至少在 Kubernetes 容器引擎上,所有 stdout/stderr 都会被选中由 Google Stackdriver 通过 FluentD 提供...话虽如此,但我目前还无法理解。

知道为什么我会收到这些重复的条目吗?

最佳答案

我通过在调用 setup_logging 方法后立即覆盖根记录器上的 handlers 属性解决了这个问题

import logging
from google.cloud import logging as gcp_logging
from google.cloud.logging.handlers import CloudLoggingHandler, ContainerEngineHandler, AppEngineHandler

logging_client = gcp_logging.Client()
logging_client.setup_logging(log_level=logging.INFO)
root_logger = logging.getLogger()
# use the GCP handler ONLY in order to prevent logs from getting written to STDERR
root_logger.handlers = [handler
                        for handler in root_logger.handlers
                        if isinstance(handler, (CloudLoggingHandler, ContainerEngineHandler, AppEngineHandler))]

为了详细说明这一点,client.setup_logging 方法设置2 个处理程序,一个普通的 logging.StreamHandler 和一个 GCP - 特定处理程序。因此,日志将同时发送到 stderr 和 Cloud Logging。您需要从处理程序列表中删除流处理程序以防止重复。

编辑: 我已提交 issue与 Google 添加一个参数,以减少这种黑客行为。

关于python - 使用 Google Cloud Stackdriver 在 Kubernetes Engine 上记录 Python 代码的重复日志条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48078051/

相关文章:

python - python float 的精度(小数点)是多少?

python - 在许多点计算许多单项式

apache - 使用 Vagrant 访问日志文件夹

sql - 在 PostgreSQL 8.4 中记录 SELECT 语句

java - org.slf4j.helpers.SubstituteLogger 无法转换为 ch.qos.logback.classic.Logger

kubernetes - GKE 外部负载均衡器配置,NEG 为空,运行状况检查不起作用

Python selenium 获取所选元素的标签值

python - 使用 beautifulsoup 读取 html 标签属性时出错

Kubernetes Ingress 负载均衡器将所有内容重写为索引;为什么?

google-cloud-platform - 云容器集群创建 `compute.networks.get`权限错误