GCP Logging每秒提交超1条日志时触发权限拒绝错误
问题描述
部署在Google App Engine上的Flask API使用GCP Logging服务记录日志时,当每秒日志提交量超过1条左右就会触发权限错误,但部分日志能正常写入,说明服务本身具备创建日志的基础权限。
代码示例
... import logging import google.cloud.logging ... @app.route("/log", methods=['GET']) def log(): logging.basicConfig( level=logging.INFO, ) logging.info('Hello') client = google.cloud.logging.Client() client.get_default_handler() client.setup_logging() return 'info log'
报错信息
Failed to submit 1 logs.
堆栈跟踪
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/api_core/grpc_helpers.py", line 57, in error_remapped_callable return callable_(*args, **kwargs) File "/layers/google.python.pip/pip/lib/python3.10/site-packages/grpc/_channel.py", line 946, in __call__ return _end_unary_response_blocking(state, call, False, None) File "/layers/google.python.pip/pip/lib/python3.10/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking raise _InactiveRpcError(state) grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with: status = StatusCode.PERMISSION_DENIED details = "Permission 'logging.logEntries.create' denied on resource (or it may not exist)." The above exception was the direct cause of the following exception: File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/cloud/logging_v2/handlers/transports/background_thread.py", line 114, in _safely_commit_batch batch.commit() File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/cloud/logging_v2/logger.py", line 453, in commit client.logging_api.write_entries(entries, **kwargs) File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/cloud/logging_v2/_gapic.py", line 160, in write_entries self._gapic_api.write_log_entries(request=request) File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/cloud/logging_v2/services/logging_service_v2/client.py", line 631, in write_log_entries response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/api_core/gapic_v1/method.py", line 154, in __call__ return wrapped_func(*args, **kwargs) File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/api_core/retry.py", line 283, in retry_wrapped_func return retry_target( File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/api_core/retry.py", line 190, in retry_target return target() File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/api_core/grpc_helpers.py", line 59, in error_remapped_callable raise exceptions.from_grpc_error(exc) from exc google.api_core.exceptions.PermissionDenied: 403 Permission 'logging.logEntries.create' denied on resource (or it may not exist). [reason: "IAM_PERMISSION_DENIED" domain: "iam.googleapis.com"
补充信息
- 已遵循GCP官方Python日志配置流程,本地测试使用Python logging库无异常
- 尝试修改代码仅实例化一次handler后,所有请求都会触发该权限错误
解决方案
1. 修正日志初始化逻辑(核心修复)
当前代码在每次请求时重复初始化logging配置和GCP Logging客户端,会导致多个handler并发写入触发权限冲突或限流。正确做法是在应用启动时仅初始化一次GCP Logging客户端:
import logging import google.cloud.logging from flask import Flask # 全局初始化,仅在应用启动时执行一次 client = google.cloud.logging.Client() client.setup_logging() app = Flask(__name__) @app.route("/log", methods=['GET']) def log(): # 直接使用logging记录,无需重复初始化 logging.info('Hello') return 'info log'
2. 验证服务账号权限
确保App Engine默认服务账号([项目ID]@appspot.gserviceaccount.com)拥有roles/logging.logWriter预定义角色,该角色包含logging.logEntries.create权限,避免使用细分权限导致隐含限制。
3. 调整日志批量写入配置(可选)
高并发场景下,可自定义后台线程传输的批量参数,减少提交频率避免限流:
from google.cloud.logging_v2.handlers import CloudLoggingHandler, BackgroundThreadTransport # 自定义批量配置:每10条日志或每5秒提交一次 transport = BackgroundThreadTransport( client, batch_size=10, batch_timeout=5.0 ) handler = CloudLoggingHandler(client, transport=transport) logging.getLogger().addHandler(handler)
4. 移除logging.basicConfig调用
logging.basicConfig会覆盖已有handler配置,使用GCP Logging时无需调用该方法,client.setup_logging()已完成日志级别和handler的配置。
内容的提问来源于stack exchange,提问作者joachim
相关产品推荐
相关产品推荐

