【问题标题】:Error Reporting with App Engine Flexible EnvironmentApp Engine 柔性环境的错误报告
【发布时间】:2016-04-29 14:40:02
【问题描述】:

我在使用带有 Python 2.7 的 App Engine 灵活环境使 Google Stackdriver 错误报告正常工作时遇到了问题

文档说灵活的环境需要手动配置:https://cloud.google.com/error-reporting/docs/setting-up-on-app-engine

默认情况下,使用 python 运行时,看起来 google-fluentd 已安装,因为 ps ax | grep fluentd 返回文档建议的内容。但是,执行 sudo service google-fluentd restart 失败。

我的 requirements.txt 文件中有fluent-logger==0.4.1

我切换到自定义运行时以便能够将 forward.conf 文件放在文档建议的 /etc/google-fluentd/config.d 中。

我的 Docker 文件如下所示:

FROM gcr.io/google_appengine/python
RUN virtualenv /env -p python2.7

# stackdriver logging (for error reporting)
RUN mkdir -p /etc/google-fluentd/config.d
ADD forward.conf /etc/google-fluentd/config.d/    

# Set virtualenv environment variables. This is equivalent to running
# source /env/bin/activate
ENV VIRTUAL_ENV /env
ENV PATH /env/bin:$PATH
ADD requirements.txt /app/
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

ADD . /app/
RUN python manage.py collectstatic --noinput
RUN python manage.py migrate --noinput

CMD gunicorn -b :$PORT project_name.wsgi

和 forward.conf 看起来像:

<source>
  type forward
  port 24224
</source>

在我的应用程序中,我有一个应该报告错误的视图,但没有任何反应:

from django.http import HttpResponse
from django.views.generic import View

from fluent import sender
from fluent import event
import traceback

sender.setup('myapp', host='localhost', port=24224)


def report(ex):
    data = {}
    data['message'] = '{0}'.format(ex)
    data['serviceContext'] = {'service' : 'myapp'}
    # ... add more metadata
    event.Event('errors', data)


class ErrorView(View):

    def get(self, request, *args, **kwargs):
        # report exception data using:
        try:
            Exception("Woops.. an Error Occurred")
        except Exception as e:
            report(traceback.format_exc())
            raise e

我的设置有什么遗漏吗? Web 服务器访问日志正常,但没有异常或写入 stderr 或 stdout

2016 年 5 月 9 日更新

感谢@Steren 的回答...它比我在 Python 灵活环境中使用 Django 时简单得多。不需要自定义运行时和安装fluentd。下面是一个工作示例,它将文件日志输出到 /var/log/app_engine/custom_logs/error.log 和一个日志格式化程序以将日志以适当的格式放置。

日志设置:

    'formatters': {
        'gcp_json': {
            '()': 'helloworld.gcp_logger.GCPJsonFormatter',
        },
    },
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': '/var/log/app_engine/custom_logs/errors.json',
            'formatter': 'gcp_json',
        },
    },
    'loggers': {
        'django.request': {
            'filters': ['require_debug_false'],
            'handlers': ['file'],
            'level': 'ERROR',
            'propagate': True,
        },
    },

和格式化程序:

    import logging
    import json
    import os


    class GCPJsonFormatter(logging.Formatter):

        def format(self, record):
            # https://cloud.google.com/error-reporting/docs/formatting-error-messages
            return json.dumps({
                'eventTime': record.created,
                'message': self.formatException(record.exc_info),
                'level': record.levelname,
                'serviceContext': {


          'service': os.environ.get('GAE_MODULE_NAME', ''),
                'version': os.environ.get('GAE_MODULE_VERSION', ''),
            },
            "context": {
                "httpRequest": self._get_request_info(record),
                'user': str(record.request.user) if record.request else "",
                "reportLocation": {
                    "filePath": record.pathname,
                    "lineNumber": record.lineno,
                    "functionName": record.funcName,
                },
            }
        })

    def _get_request_info(self, record):
        try:
            request = record.request
            return {
                "method": request.method,
                "url": request.get_full_path(),
                "userAgent": request.META.get("HTTP_USER_AGENT", ""),
                "referrer": request.META.get("HTTP_REFERER", ""),
                "responseStatusCode": record.status_code,
                "remoteIp": request.META.get("REMOTE_ADDR", "")
            }
        except Exception:
            return {}

【问题讨论】:

  • 您好 Aaron,我是 Stackdriver 错误报告产品经理。您能否确认您将日志查看器中报告的错误视为结构化负载?如果是,日志流的名称是什么?
  • 嗨@Steren 我在日志查看器中看到了访问日志,但错误不会像在标准环境中那样出现在日志查看器中。标准环境显示了堆栈跟踪的一部分(以及记录的任何特定内容),这非常方便。
  • 感谢您的回复。确实,灵活的环境不支持请求日志,我们正在努力使错误报告更易于灵活设置。您是否在任何日志流中看到堆栈跟踪?如果没有,这是第一步。我将在下周尝试发布使其在 Node.js 上运行的说明,它们应该很容易适应 Python。
  • @Steren - 我无法在任何我不相信的日志流中看到堆栈跟踪。我在哪里可以留意您使用 Node.js 的说明?

标签: google-app-engine google-cloud-platform stackdriver


【解决方案1】:

有一种方法可以在不需要自定义运行时的情况下配置 App Engine 灵活运行时,它很快就会记录在官方文档中,我们也在努力简化这些步骤:

您应该使用与Google Compute Engine samples 中详述的代码类似的代码,将异常数据作为结构化日志发送到名为/var/log/app_engine/custom_logs/errors.json 的文件中(不要通过 TCP 端口发送)

重要的是:

  • 文件路径以/var/log/app_engine/custom_logs/开头
  • 文件扩展名是.json
  • 文件名中包含err
  • 该文件仅包含结构化 JSON 对象。

然后,您可以在 Stackdriver Logging 中确认您看到错误在自定义日志流中显示为 structPayload: 在第一个下拉列表中选择 App Engine,然后选择 custom.var.lop.app_engine.app.custom_logs.errors.json

如果是这种情况,那么错误报告应该会自动开始处理这些错误。

如果不是这样,请告诉我。

【讨论】:

  • 谢谢,这非常有帮助,让我看到 Stackdriver Logging 中的错误!我仍然没有在错误报告中看到它.. 是否需要一段时间才能开始,或者在 JSON 结构中我可能需要其他结构?
  • 我使用的文件名是:/var/log/app_engine/custom_logs/errors.json 当我 ssh 进入盒子时,日志似乎真的位于 /var/log/app_engine/app/custom_logs/errors.json
  • 是本页所述的 JSON 有效负载:cloud.google.com/error-reporting/docs/formatting-error-messages。消息字段应包含堆栈跟踪。
  • 哦,明白了.. 我没有意识到该消息必须是堆栈跟踪。效果很棒。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 2019-04-24
  • 2018-11-28
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
相关资源
最近更新 更多