Python Google Cloud Function 缺少日志条目
Python Google Cloud Function Missing Log Entries
我第一次尝试使用 GCP 的云功能和 python,并希望充分集成 python 的日志记录,以便它们能够很好地适应 GCP 的日志记录基础架构(特别是这样识别严重级别,理想情况下 execution_ids 和跟踪 ID 也包括在内。
我一直在关注 https://cloud.google.com/logging/docs/setup/python 以完成此设置。
我的代码:
import base64
import logging
import google.cloud.logging
client = google.cloud.logging.Client()
client.get_default_handler()
client.setup_logging()
logging.getLogger().setLevel(logging.DEBUG)
def sample_pubsub(event, context):
pubsub_message = base64.b64decode(event['data']).decode('utf-8')
print('BEFORE LOG')
logging.info(f'Event received: payload data == [{pubsub_message}]')
logging.debug('This is debug')
logging.warn('This should be a warning')
logging.error('This should be an error')
print('AFTER LOG')
当我 运行 在本地使用函数框架时,它完美地工作(据我所知)输出到控制台:
{"message": " * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)", "timestamp": {"seconds": 1609443581, "nanos": 119384527}, "thread": 140519851886400, "severity": "INFO"}
{"message": " * Restarting with inotify reloader", "timestamp": {"seconds": 1609443581, "nanos": 149804115}, "thread": 140519851886400, "severity": "INFO"}
{"message": " * Debugger is active!", "timestamp": {"seconds": 1609443584, "nanos": 529310703}, "thread": 140233360983872, "severity": "WARNING"}
{"message": " * Debugger PIN: 327-539-151", "timestamp": {"seconds": 1609443584, "nanos": 533129930}, "thread": 140233360983872, "severity": "INFO"}
BEFORE LOG
{"message": "Event received: payload data == []", "timestamp": {"seconds": 1609443585, "nanos": 77324390}, "thread": 140232720623360, "severity": "INFO"}
{"message": "This is debug", "timestamp": {"seconds": 1609443585, "nanos": 77804565}, "thread": 140232720623360, "severity": "DEBUG"}
{"message": "This should be a warning", "timestamp": {"seconds": 1609443585, "nanos": 78260660}, "thread": 140232720623360, "severity": "WARNING"}
{"message": "This should be an error", "timestamp": {"seconds": 1609443585, "nanos": 78758001}, "thread": 140232720623360, "severity": "ERROR"}
AFTER LOG
{"message": "127.0.0.1 - - [31/Dec/2020 14:39:45] \"\u001b[37mPOST / HTTP/1.1\u001b[0m\" 200 -", "timestamp": {"seconds": 1609443585, "nanos": 82943439}, "thread": 140232720623360, "severity": "INFO"}
所以...然后我将它部署到云端并通过其相关主题触发它,然后我看到:
因此,stdout 似乎工作正常,但缺少记录器输出。最后评论:我确实创建了帐户密钥并将 json 文件放入功能部署根文件夹中,并创建了环境变量 GOOGLE_APPLICATION_CREDENTIALS=key.json。如果问题是文件未被拾取,我还使用引用不存在文件的值对此进行了测试。如果我这样做,部署会失败,所以我确信密钥文件正在被提取。
这让我想到了我的问题:我做错了什么?
编辑 - 添加环境细节
我正在使用 GSDK 部署函数,如下所示:
gcloud functions deploy sample_pubsub --source=${SOURCE_DIR} --runtime=python38 --trigger-topic=${PUBSUB_TOPIC} --set-env-vars GOOGLE_APPLICATION_CREDENTIALS=key.json,PYTHONUNBUFFERED=1
在与函数 py 文件相同的文件夹中有一个 requirements.txt 文件指定仅“google-cloud-logging”,没有任何版本限制。
** 对于本地调试,我有一个用 python 3.8.5 创建的 venv,我只安装了 pip-installed google-cloud-logging 和 functions-framework - 同样没有任何版本限制。
话虽如此,如果我在激活的虚拟环境中进行 pip 冻结:
appdirs==1.4.3
CacheControl==0.12.6
cachetools==4.2.0
certifi==2019.11.28
chardet==3.0.4
click==7.1.2
cloudevents==1.2.0
colorama==0.4.3
contextlib2==0.6.0
deprecation==2.1.0
distlib==0.3.0
distro==1.4.0
Flask==1.1.2
functions-framework==2.1.0
google-api-core==1.24.1
google-auth==1.24.0
google-cloud-core==1.5.0
google-cloud-logging==2.0.2
googleapis-common-protos==1.52.0
grpcio==1.34.0
gunicorn==20.0.4
html5lib==1.0.1
idna==2.8
ipaddr==2.2.0
itsdangerous==1.1.0
Jinja2==2.11.2
lockfile==0.12.2
MarkupSafe==1.1.1
msgpack==0.6.2
packaging==20.3
pep517==0.8.2
progress==1.5
proto-plus==1.13.0
protobuf==3.14.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pyparsing==2.4.6
pytoml==0.1.21
pytz==2020.5
requests==2.22.0
retrying==1.3.3
rsa==4.6
six==1.14.0
urllib3==1.25.8
watchdog==1.0.2
webencodings==0.5.1
Werkzeug==1.0.1
看起来这是 Cloud Functions 运行 Python 3.8 的一个已知问题。这是目前在 issue tracker.
上打开的一个类似案例
我现在已将此线程附加到问题跟踪器,但也可以随意在其中发表评论。
作为当前的解决方法,我建议您使用 Python 3.7,直到问题得到解决。
您可以使用打印语句作为默认日志级别,或者使用 json 格式化字符串在信息、调试、错误等级别进行日志记录。
代码示例:
import json
print("print statement")
log_message_info = dict(
severity="INFO",
message="This is an info message",
custom_property="I will appear inside the log's jsonPayload field",
)
log_message_error = dict(
severity="ERROR",
message="This is an error message",
custom_property="I will appear inside the log's jsonPayload field",
)
log_message_debug = dict(
severity="DEBUG",
message="This is a debug message",
custom_property="I will appear inside the log's jsonPayload field",
)
print(json.dumps(log_message_info))
print(json.dumps(log_message_error))
print(json.dumps(log_message_debug))
另请参阅:Google Cloud Functions Python Logging issue
有关 GCP 日志记录的更多信息:https://cloud.google.com/functions/docs/monitoring/logging#writing_structured_logs
如果您使用第一代云功能,您将在云日志中找到您的日志消息:resource.type="cloud_function"
对于第二代 Cloud Functions 使用:resource.type="cloud_run_revision"
python 3.9 没有问题。您可以在那里执行以下操作以使日志记录正常工作:
import google.cloud.logging
client = google.cloud.logging.Client()
client.setup_logging()
import logging
logging.warning("A warning")
我第一次尝试使用 GCP 的云功能和 python,并希望充分集成 python 的日志记录,以便它们能够很好地适应 GCP 的日志记录基础架构(特别是这样识别严重级别,理想情况下 execution_ids 和跟踪 ID 也包括在内。
我一直在关注 https://cloud.google.com/logging/docs/setup/python 以完成此设置。
我的代码:
import base64
import logging
import google.cloud.logging
client = google.cloud.logging.Client()
client.get_default_handler()
client.setup_logging()
logging.getLogger().setLevel(logging.DEBUG)
def sample_pubsub(event, context):
pubsub_message = base64.b64decode(event['data']).decode('utf-8')
print('BEFORE LOG')
logging.info(f'Event received: payload data == [{pubsub_message}]')
logging.debug('This is debug')
logging.warn('This should be a warning')
logging.error('This should be an error')
print('AFTER LOG')
当我 运行 在本地使用函数框架时,它完美地工作(据我所知)输出到控制台:
{"message": " * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)", "timestamp": {"seconds": 1609443581, "nanos": 119384527}, "thread": 140519851886400, "severity": "INFO"}
{"message": " * Restarting with inotify reloader", "timestamp": {"seconds": 1609443581, "nanos": 149804115}, "thread": 140519851886400, "severity": "INFO"}
{"message": " * Debugger is active!", "timestamp": {"seconds": 1609443584, "nanos": 529310703}, "thread": 140233360983872, "severity": "WARNING"}
{"message": " * Debugger PIN: 327-539-151", "timestamp": {"seconds": 1609443584, "nanos": 533129930}, "thread": 140233360983872, "severity": "INFO"}
BEFORE LOG
{"message": "Event received: payload data == []", "timestamp": {"seconds": 1609443585, "nanos": 77324390}, "thread": 140232720623360, "severity": "INFO"}
{"message": "This is debug", "timestamp": {"seconds": 1609443585, "nanos": 77804565}, "thread": 140232720623360, "severity": "DEBUG"}
{"message": "This should be a warning", "timestamp": {"seconds": 1609443585, "nanos": 78260660}, "thread": 140232720623360, "severity": "WARNING"}
{"message": "This should be an error", "timestamp": {"seconds": 1609443585, "nanos": 78758001}, "thread": 140232720623360, "severity": "ERROR"}
AFTER LOG
{"message": "127.0.0.1 - - [31/Dec/2020 14:39:45] \"\u001b[37mPOST / HTTP/1.1\u001b[0m\" 200 -", "timestamp": {"seconds": 1609443585, "nanos": 82943439}, "thread": 140232720623360, "severity": "INFO"}
所以...然后我将它部署到云端并通过其相关主题触发它,然后我看到:
因此,stdout 似乎工作正常,但缺少记录器输出。最后评论:我确实创建了帐户密钥并将 json 文件放入功能部署根文件夹中,并创建了环境变量 GOOGLE_APPLICATION_CREDENTIALS=key.json。如果问题是文件未被拾取,我还使用引用不存在文件的值对此进行了测试。如果我这样做,部署会失败,所以我确信密钥文件正在被提取。
这让我想到了我的问题:我做错了什么?
编辑 - 添加环境细节
我正在使用 GSDK 部署函数,如下所示:
gcloud functions deploy sample_pubsub --source=${SOURCE_DIR} --runtime=python38 --trigger-topic=${PUBSUB_TOPIC} --set-env-vars GOOGLE_APPLICATION_CREDENTIALS=key.json,PYTHONUNBUFFERED=1
在与函数 py 文件相同的文件夹中有一个 requirements.txt 文件指定仅“google-cloud-logging”,没有任何版本限制。 ** 对于本地调试,我有一个用 python 3.8.5 创建的 venv,我只安装了 pip-installed google-cloud-logging 和 functions-framework - 同样没有任何版本限制。
话虽如此,如果我在激活的虚拟环境中进行 pip 冻结:
appdirs==1.4.3
CacheControl==0.12.6
cachetools==4.2.0
certifi==2019.11.28
chardet==3.0.4
click==7.1.2
cloudevents==1.2.0
colorama==0.4.3
contextlib2==0.6.0
deprecation==2.1.0
distlib==0.3.0
distro==1.4.0
Flask==1.1.2
functions-framework==2.1.0
google-api-core==1.24.1
google-auth==1.24.0
google-cloud-core==1.5.0
google-cloud-logging==2.0.2
googleapis-common-protos==1.52.0
grpcio==1.34.0
gunicorn==20.0.4
html5lib==1.0.1
idna==2.8
ipaddr==2.2.0
itsdangerous==1.1.0
Jinja2==2.11.2
lockfile==0.12.2
MarkupSafe==1.1.1
msgpack==0.6.2
packaging==20.3
pep517==0.8.2
progress==1.5
proto-plus==1.13.0
protobuf==3.14.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pyparsing==2.4.6
pytoml==0.1.21
pytz==2020.5
requests==2.22.0
retrying==1.3.3
rsa==4.6
six==1.14.0
urllib3==1.25.8
watchdog==1.0.2
webencodings==0.5.1
Werkzeug==1.0.1
看起来这是 Cloud Functions 运行 Python 3.8 的一个已知问题。这是目前在 issue tracker.
上打开的一个类似案例我现在已将此线程附加到问题跟踪器,但也可以随意在其中发表评论。
作为当前的解决方法,我建议您使用 Python 3.7,直到问题得到解决。
您可以使用打印语句作为默认日志级别,或者使用 json 格式化字符串在信息、调试、错误等级别进行日志记录。
代码示例:
import json
print("print statement")
log_message_info = dict(
severity="INFO",
message="This is an info message",
custom_property="I will appear inside the log's jsonPayload field",
)
log_message_error = dict(
severity="ERROR",
message="This is an error message",
custom_property="I will appear inside the log's jsonPayload field",
)
log_message_debug = dict(
severity="DEBUG",
message="This is a debug message",
custom_property="I will appear inside the log's jsonPayload field",
)
print(json.dumps(log_message_info))
print(json.dumps(log_message_error))
print(json.dumps(log_message_debug))
另请参阅:Google Cloud Functions Python Logging issue
有关 GCP 日志记录的更多信息:https://cloud.google.com/functions/docs/monitoring/logging#writing_structured_logs
如果您使用第一代云功能,您将在云日志中找到您的日志消息:resource.type="cloud_function"
对于第二代 Cloud Functions 使用:resource.type="cloud_run_revision"
python 3.9 没有问题。您可以在那里执行以下操作以使日志记录正常工作:
import google.cloud.logging
client = google.cloud.logging.Client()
client.setup_logging()
import logging
logging.warning("A warning")