跳转到主要内容

Python CloudWatch Logging

项目描述

Watchtower是Amazon Web Services CloudWatch Logs的日志处理器。

CloudWatch Logs是AWS内置的日志管理服务。它在概念上类似于Splunk、Datadog和Loggly等服务,但更轻量级、更便宜,并与AWS的其余部分紧密集成。

反过来,Watchtower是Python日志系统和CloudWatch Logs之间的轻量级适配器。它使用boto3 AWS SDK,并允许您直接将应用程序日志连接到CloudWatch,无需安装系统范围的日志收集器如awscli-cwlogs,并绕过实例的syslog进行日志轮转。它将日志汇总成批次,以避免为每条日志消息发送API请求,同时保证交付截止日期(默认为60秒)。

安装

pip install watchtower

概述

安装awscli并设置您的AWS凭证(运行aws configure)。

import watchtower, logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
logger.addHandler(watchtower.CloudWatchLogHandler())
logger.info("Hi")
logger.info(dict(foo="bar", details={}))

运行示例后,您可以在AWS控制台watchtower日志组下查看日志输出。

IAM权限

运行Watchtower进程需要访问IAM凭证以调用CloudWatch Logs API。加载和配置凭证的标准程序在Boto3凭证文档中描述。在EC2实例或其他AWS计算资源上运行Watchtower时,boto3会自动从实例元数据(IMDS)或容器凭证提供者(AWS_WEB_IDENTITY_TOKEN_FILE或AWS_CONTAINER_CREDENTIALS_FULL_URI)中加载凭证。为与这些凭证关联的IAM角色授予正确的权限的最简单方法是将AWS管理IAM策略附加到该角色。虽然AWS没有提供通用的管理CloudWatch Logs写入策略,但我们建议您使用具有恰到好处的权限而不太广泛的arn:aws:iam::aws:policy/AWSOpsWorksCloudWatchLogs管理策略。

日志组标记

Watchtower支持日志组的标记。这可以通过将log_group_tags参数添加到CloudWatchLogHandler构造函数中来实现。此参数应是将应用于日志组的标记的字典。

如果您要向日志组添加标记,您需要添加对logs:TagResource操作的权限到您的策略。这需要除AWSOpsWorksCloudWatchLogs策略之外。注意:旧的logs:TagLogGroup权限是用于即将弃用的tag_log_group()调用,而Watchtower不使用该调用。

示例:使用Watchtower进行Flask日志记录

使用以下配置将Flask日志发送到名为“loggable”的CloudWatch Logs流

import watchtower, flask, logging

logging.basicConfig(level=logging.INFO)
app = flask.Flask("loggable")
handler = watchtower.CloudWatchLogHandler(log_group_name=app.name)
app.logger.addHandler(handler)
logging.getLogger("werkzeug").addHandler(handler)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

(也请参阅https://flask.org.cn/docs/errorhandling/。)

示例:使用Watchtower进行Django日志记录

这是Watchtower与Django集成的示例。在您的Django项目中,将以下内容添加到settings.py

import boto3

AWS_REGION_NAME = "us-west-2"

boto3_logs_client = boto3.client("logs", region_name=AWS_REGION_NAME)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'root': {
        'level': 'DEBUG',
        # Adding the watchtower handler here causes all loggers in the project that
        # have propagate=True (the default) to send messages to watchtower. If you
        # wish to send only from specific loggers instead, remove "watchtower" here
        # and configure individual loggers below.
        'handlers': ['watchtower', 'console'],
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
        'watchtower': {
            'class': 'watchtower.CloudWatchLogHandler',
            'boto3_client': boto3_logs_client,
            'log_group_name': 'YOUR_DJANGO_PROJECT_NAME',
            # Decrease the verbosity level here to send only those logs to watchtower,
            # but still see more verbose logs in the console. See the watchtower
            # documentation for other parameters that can be set here.
            'level': 'DEBUG'
        }
    },
    'loggers': {
        # In the debug server (`manage.py runserver`), several Django system loggers cause
        # deadlocks when using threading in the logging handler, and are not supported by
        # watchtower. This limitation does not apply when running on production WSGI servers
        # (gunicorn, uwsgi, etc.), so we recommend that you set `propagate=True` below in your
        # production-specific Django settings file to receive Django system logs in CloudWatch.
        'django': {
            'level': 'DEBUG',
            'handlers': ['console'],
            'propagate': False
        }
        # Add any other logger-specific configuration here.
    }
}

使用此配置,Django的日志将发送到名为YOUR_DJANGO_PROJECT_NAME的日志组中。要在开发中为此配置提供AWS凭证,请使用aws configure设置您的AWS CLI配置文件设置。在生产环境中或在EC2实例上运行时,为您的实例分配IAM角色,这将导致boto3自动从实例元数据中获取IAM角色凭证。

(也请参阅Django日志记录文档。)

示例:查询CloudWatch日志

本节并非特定于Watchtower。它展示了使用awscli和jq在命令行中读取和搜索CloudWatch日志的使用方法。

对于上面的Flask示例,您可以使用以下两个命令检索应用程序日志

aws logs get-log-events --log-group-name watchtower --log-stream-name loggable | jq '.events[].message'
aws logs get-log-events --log-group-name watchtower --log-stream-name werkzeug | jq '.events[].message'

除了原始get-log-events API之外,CloudWatch Logs支持将日志提取到S3存储桶,使用查询语言进行日志分析,以及基于度量过滤器的警报和仪表板,这些是提取信息并馈送到警报和仪表板图标的模式规则。如果您想通过命令行使用这些功能,Watchtower的作者已经发布了一个名为aegea的开源CLI工具包,其中包括aegea logsaegea grep命令,以便轻松访问S3导出和洞察功能。

示例:Python 日志配置

Python 的 logging.config 模块具有提供配置文件的能力,该文件可以被加载以将日志配置与代码分离。

以下是用 PyYAML 加载的两种示例 YAML 配置文件。结果 dict 对象可以随后加载到 logging.config.dictConfig。第一个示例是一个基本示例,它依赖于 boto3 提供的默认配置

# Default AWS Config
version: 1
disable_existing_loggers: False
handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    stream: ext://sys.stdout
  logfile:
    class: logging.handlers.RotatingFileHandler
    level: DEBUG
    filename: watchtower.log
    maxBytes: 1000000
    backupCount: 3
  watchtower:
    class: watchtower.CloudWatchLogHandler
    level: DEBUG
    log_group_name: watchtower
    log_stream_name: "{logger_name}-{strftime:%y-%m-%d}"
    send_interval: 10
    create_log_group: False
root:
  level: DEBUG
  propagate: True
  handlers: [console, logfile, watchtower]
loggers:
  botocore:
    level: INFO
  urllib3:
    level: INFO

如果可以使用 boto3 的默认凭证配置,或者依赖于环境变量,上述方法运行良好。然而,有时可能需要为日志使用与用于其他功能的凭证不同的凭证;在这种情况下,可以使用 Watchtower 的 boto3_profile_name 选项来提供 boto3 配置文件名

# AWS Config Profile
version: 1
...
handlers:
  ...
  watchtower:
    boto3_profile_name: watchtowerlogger
    ...

最后,以下展示了如何将配置加载到工作应用程序中

import logging.config

import flask
import yaml

app = flask.Flask("loggable")

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    with open('logging.yml') as log_config:
        config_yml = log_config.read()
        config_dict = yaml.safe_load(config_yml)
        logging.config.dictConfig(config_dict)
        app.run()

日志流命名

对于使用进程池的高容量日志应用程序,建议您保留默认的日志流名称({machine_name}/{program_name}/{logger_name}/{process_id}),或者使用这些模板变量的组合使每个源具有唯一性。由于日志必须按顺序提交到每个日志流,因此独立进程向同一日志流发送日志将遇到序列令牌同步错误,并消耗额外资源来自动恢复。随着进程数量的增加,这种开销将增长,直到日志无法传递并丢失(导致在 stderr 上发出警告)。通过按源将日志流分区可以避免这种竞争。

Boto3/botocore/urllib3 日志

因为 watchtower 使用 boto3 发送日志,因此发送日志的行为会产生 boto3 依赖项 botocore 和 urllib3 的许多 DEBUG 级别日志消息。为了避免生成自我维持的日志消息流,watchtower.CloudWatchLogHandler 将一个 过滤器附加到自身,丢弃这些库的所有 DEBUG 级别消息,并在关闭时(特别是在 watchtower.CloudWatchLogHandler.flush()watchtower.CloudWatchLogHandler.close() 中)丢弃所有级别的消息。该过滤器不应用于您可能用于处理消息的任何其他处理程序,因此以下基本配置会导致 botocore 调试日志打印到 stderr 但不会打印到 Cloudwatch

import watchtower, logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger()
logger.addHandler(watchtower.CloudWatchLogHandler())

AWS Lambda

Watchtower 不适用于 AWS Lambda 上运行的应用程序,也不是必需的。所有 AWS Lambda 日志(即 Lambda 运行时打印到 stderr 的所有行)都会自动发送到 CloudWatch Logs,进入 以 /aws/lambda/ 前缀下的日志组

AWS Lambda 在调用完成后和下一个调用(如果有)之前暂停(冻结)其执行环境中的所有进程。这意味着任何异步后台进程和线程(包括 watchtower),都将被暂停且无法工作,因此 watchtower 不能在执行模型中正常工作。

作者

  • Andrey Kislyuk

错误

请在 GitHub 上报告错误、问题、功能请求等。

版本控制

此软件包遵循 语义版本控制 2.0.0 标准。为了控制更改,建议应用程序开发人员固定软件包版本,并使用 pip-tools 或类似工具进行管理。对于库开发人员,建议固定主版本。

许可证

根据 Apache 许可证 2.0 版本许可。

https://github.com/kislyuk/watchtower/workflows/CI/badge.svg https://codecov.io/github/kislyuk/watchtower/coverage.svg?branch=master https://img.shields.io/pypi/v/watchtower.svg https://img.shields.io/pypi/l/watchtower.svg

项目详情


下载文件

下载适用于您平台的文件。如果您不确定该选择哪个,请了解有关安装包的更多信息。

源分布

watchtower-3.3.1.tar.gz (26.1 kB 查看哈希)

上传时间

构建分布

watchtower-3.3.1-py3-none-any.whl (18.0 kB 查看哈希)

上传时间 Python 3

支持者