redis-py 原生 OpenTelemetry 集成指南:指标采集、分布式追踪与告警实战
【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py
本指南以 docs/opentelemetry.rst 为核心骨架,系统讲解 redis-py 的 OpenTelemetry 可观测性能力:从 tracing 基础概念、原生指标集成(推荐方案)的安装与配置,到外部插桩、Uptrace 可视化、OpenTelemetry Collector 监控 Redis Server 以及告警规则编写。读完本文,你将能够为生产环境的 redis-py 应用一键接入标准化的指标采集与分布式追踪,并用源码级视角理解其内部工作原理。
1. OpenTelemetry 是什么
OpenTelemetry 是一个开源的可观测性框架,覆盖 traces(链路追踪)、metrics(指标)和 logs(日志)三大信号。它由 CNCF(Cloud Native Computing Foundation)托管,是 OpenCensus 与 OpenTracing 两个项目合并的产物。
其核心价值在于供应商无关(vendor agnostic):开发者只需插桩一次,之后可以随时新增或替换后端(如各种兼容 OpenTelemetry 的 APM 厂商),而无需改动业务代码中的插桩逻辑。采集到的遥测数据通过统一的 OpenTelemetry 协议(OTLP)导出,可供任意兼容后端消费。
2. 什么是 Tracing:从 Span 到 Trace
分布式追踪(Distributed Tracing)用于观察一个请求如何在多个服务和系统之间流转,记录每个操作的耗时、产生的日志以及发生的错误。在微服务架构中,追踪还能揭示服务之间的依赖关系与相互影响——某个微服务自身的性能问题如何传导到下游服务。
追踪把请求拆解为一个个Span(跨度)。一个 Span 代表应用处理请求时执行的一个操作单元(unit of work),例如一次数据库查询或一次网络调用。
而Trace(追踪)是 Span 构成的树,展示请求在应用中的完整路径。树中的第一个 Span 称为Root Span(根跨度)。
3. 原生 OpenTelemetry 集成(推荐方案)
redis-py 内置了对 OpenTelemetry指标采集的完整支持。相比外部插桩包,原生集成无需 monkey-patching,即可提供全面且细粒度的指标,因此是官方推荐的使用方式。
3.1 安装依赖
使用[otel]extra 安装原生支持所需依赖:
pip install redis[otel]从仓库的 pyproject.toml 可以看到,该 extra 实际引入的依赖包括:
opentelemetry-api>=1.39.1opentelemetry-sdk>=1.39.1opentelemetry-exporter-otlp-proto-http>=1.39.1
3.2 基本设置:一次初始化,全客户端生效
在应用启动时初始化一次 OpenTelemetry 可观测性,之后所有 Redis 客户端都会自动采集指标,无需逐个客户端配置:
from opentelemetry import metrics from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter # 1. 设置 OpenTelemetry MeterProvider exporter = OTLPMetricExporter(endpoint="http://localhost:4318/v1/metrics") reader = PeriodicExportingMetricReader(exporter=exporter, export_interval_millis=10000) provider = MeterProvider(metric_readers=[reader]) metrics.set_meter_provider(provider) # 2. 初始化 redis-py 可观测性 from redis.observability import get_observability_instance, OTelConfig otel = get_observability_instance() otel.init(OTelConfig()) # 3. 正常使用 Redis —— 指标自动采集 import redis r = redis.Redis(host='localhost', port=6379) r.set('key', 'value') # 指标自动采集 r.get('key') # 4. 应用退出时关闭可观测性(冲刷待导出指标) otel.shutdown()关键点说明:
PeriodicExportingMetricReader每 10 秒(export_interval_millis=10000)将累积指标导出到 OTLP HTTP 端点http://localhost:4318/v1/metrics,该端点通常是 OpenTelemetry Collector 或兼容后端(如 Uptrace、Jaeger)的监听地址;- MeterProvider 必须由应用先设置好,redis-py 复用全局 MeterProvider,而不是自建一套(见 providers.py 的模块注释)。
3.3 OTelConfig 配置选项:细粒度控制
OTelConfig类提供对指标采集的精细控制。其全部参数定义在 config.py:
from redis.observability import OTelConfig, MetricGroup config = OTelConfig( # 启用的指标组(默认:CONNECTION_BASIC | RESILIENCY) metric_groups=[ MetricGroup.CONNECTION_BASIC, # 连接创建耗时、relaxed timeout MetricGroup.CONNECTION_ADVANCED, # 连接等待耗时、超时、关闭的连接 MetricGroup.COMMAND, # 命令执行耗时 MetricGroup.RESILIENCY, # 错误计数、维护通知 MetricGroup.PUBSUB, # PubSub 消息计数 MetricGroup.STREAMING, # Stream 消息延迟 MetricGroup.CSC, # Client Side Caching 指标 ], # 过滤需要跟踪的命令 include_commands=['GET', 'SET', 'HGET'], # 只跟踪这些命令 # 或者 exclude_commands=['DEBUG', 'SLOWLOG'], # 跟踪除这些之外的所有命令 # 隐私控制 hide_pubsub_channel_names=True, # 在 PubSub 指标中隐藏频道名 hide_stream_names=True, # 在流式指标中隐藏流名 ) otel = get_observability_instance() otel.init(config)各参数的源码级行为:
- 命令过滤逻辑(
should_track_command,见 config.py):命令名统一转为大写后比较;include_commands与exclude_commands互斥生效——若设置了 allowlist 则仅跟踪列表内的命令,否则跟踪除 blocklist 外的全部命令; - 默认指标组为
CONNECTION_BASIC | RESILIENCY(见 config.py),即默认只开启连接基础指标与弹性指标; - 隐私开关实际在录制阶段生效:
record_pubsub_message与record_streaming_lag在调用采集器前会把频道名/流名替换为None(见 recorder.py 与 recorder.py)。
3.4 可用指标组一览
| Metric Group | 描述 |
|---|---|
CONNECTION_BASIC | 连接创建耗时、relaxed timeout、连接交接(handoff) |
CONNECTION_ADVANCED | 连接等待耗时、超时、关闭的连接 |
COMMAND | 命令执行耗时 |
RESILIENCY | 错误计数、维护通知 |
PUBSUB | PubSub 消息计数(发布/接收) |
STREAMING | Stream 消息延迟(XREAD/XREADGROUP) |
CSC | Client Side Caching(请求、驱逐、节省字节数) |
MetricGroup在源码中使用IntFlag枚举实现(见 config.py),因此多个组可以按位或组合。上述每个组都对应 metrics.py 中RedisMetricsCollector.__init__里的一组仪器初始化分支。
3.5 可用指标明细
根据启用的指标组,采集以下指标(仪器定义见 metrics.py):
连接类指标(Connection Metrics)
db.client.connection.create_time—— 新建连接耗时(histogram,单位 s)db.client.connection.timeouts—— 连接超时次数(counter)db.client.connection.wait_time—— 从连接池获取连接的耗时(histogram,单位 s)db.client.connection.count—— 当前连接数(按连接池、状态 idle/used 维度)redis.client.connection.closed—— 累计关闭连接数(counter)redis.client.connection.relaxed_timeout—— relaxed timeout 事件(up/down counter:放宽 +1,恢复 -1)redis.client.connection.handoff—— 连接交接事件(counter,如收到 MOVING 通知后)
命令类指标(Command Metrics)
db.client.operation.duration—— 命令执行耗时(histogram,单位 s)
弹性类指标(Resiliency Metrics)
redis.client.errors—— 错误计数,按错误类型等属性细分(counter)redis.client.maintenance.notifications—— 服务端维护通知计数(counter)
此外,源码中还定义了redis.client.geofailover.failovers(通过 MultiDbClient 发生的故障转移总数),与 MultiDB/地理故障转移功能配套使用。
PubSub 指标
redis.client.pubsub.messages—— 发布与接收的消息数(counter)
流式指标(Streaming Metrics)
redis.client.stream.lag—— 消息端到端延迟(histogram,单位 s)
Client Side Caching(CSC)指标
redis.client.csc.requests—— 缓存请求数,带 hit/miss 结果属性(counter)redis.client.csc.evictions—— 缓存驱逐数(counter)redis.client.csc.network_saved—— 通过缓存节省的网络字节数(counter,单位 By)redis.client.csc.items—— 当前缓存大小(observable gauge)
版本演进提示(来自源码):文档中
db.client.connection.count早期以 observable gauge 方式实现,但当前源码已改为push-based UpDownCounter跟踪(connection_count_updown,见 metrics.py);旧的 gauge 实现被标记为已弃用,指标名改为db.client.connection.count.deprecated,将在下一个主版本移除(见 metrics.py 的弃用说明)。如果你在生产中依赖该指标,建议以新实现为准。
3.6 自定义直方图桶边界
为获得更合适的统计粒度,可以自定义直方图桶(bucket)边界。源码中每个直方图都通过explicit_bucket_boundaries_advisory将配置透传给 OTel SDK(见 metrics.py):
config = OTelConfig( buckets_operation_duration=[0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1], buckets_connection_create_time=[0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5], buckets_connection_wait_time=[0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1], buckets_stream_processing_duration=[0.001, 0.01, 0.1, 1, 10], )若不指定,源码默认值分别为:
- 操作耗时桶(
default_operation_duration_buckets,见 config.py):[0.0001, 0.00025, 0.0005, 0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5](秒) - 其余直方图桶(
default_histogram_buckets,见 config.py):[0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10](秒)
3.7 上下文管理器用法:自动冲刷
需要自动清理时,使用上下文管理器模式——退出with块时会自动冲刷(force flush)待导出的指标:
from redis.observability import get_observability_instance, OTelConfig otel = get_observability_instance() with otel.get_provider_manager(): # 在此执行 Redis 操作 r = redis.Redis() r.set('key', 'value') # 退出时自动冲刷指标get_provider_manager()返回OTelProviderManager(见 providers.py),其__exit__调用shutdown(),而shutdown()实际执行的是force_flush()——不会关闭应用拥有的全局 MeterProvider,只负责把待导出指标冲刷出去,避免与应用自身的 Provider 生命周期冲突。
3.8 错误处理:非侵入式设计
原生集成的设计目标是非侵入:所有指标录制函数都被 try-except 包裹,指标采集过程中发生的任何异常都不会影响 Redis 操作本身。
从源码看,这一保证体现在两个层面:
- 录制函数(如 recorder.py 的
record_operation_duration)在调用采集器时捕获所有异常并静默忽略; - 存在快速路径(fast path)优化:若可观测性未初始化,
_metrics_collector为None,录制函数直接返回,几乎零开销(见 recorder.py)。即使初始化失败(例如 OpenTelemetry 未安装),_get_or_create_collector也会返回None而不抛错(见 recorder.py)。
另外需要注意:若指标已启用但应用未设置全局 MeterProvider,get_meter_provider()会抛出带完整指引的RuntimeError,提示必须先创建并设置MeterProvider(见 providers.py)。
4. 源码级原理:指标如何从客户端流向 OTel
理解原生集成,只需掌握三个层次的模块(均在 redis/observability 目录下):
① 单例入口层—— providers.py 中的get_observability_instance()返回全局单例ObservabilityInstance;init(config)可安全重复调用(再次初始化前会先 shutdown 旧实例,见 providers.py)。它还提供reset_observability_instance()用于测试/基准场景重置全局状态。
② 采集器层—— metrics.py 中的RedisMetricsCollector按METER_NAME = "redis-py"、METER_VERSION = "1.0.0"从全局 Meter 创建仪器(Counter / Histogram / UpDownCounter / ObservableGauge),并根据metric_groups决定初始化哪些仪器。
③ 录制层(recorder)—— recorder.py 提供record_operation_duration、record_connection_create_time、record_error_count、record_pubsub_message、record_streaming_lag等简洁 API,供 Redis 核心代码直接调用,无需了解 OTel 内部细节。
录制链路示例(以命令耗时为例):客户端执行命令时,在 client.py 的execute_command成功路径上调用record_operation_duration(command_name=..., duration_seconds=...);失败路径则调用record_error_count(...)(见 client.py)。录制函数内部解析出_metrics_collector后调用RedisMetricsCollector.record_operation_duration,后者通过should_track_command做命令过滤,再用AttributeBuilder(见 attributes.py)构建符合语义约定(semantic conventions)的属性集(db.system="redis"、db.operation.name、server.address、error.type等),最终写入直方图。
属性构建遵循 OTel 数据库客户端语义约定(源码头部注释指向对应规范),例如基础属性固定包含db.system: redis和redis.client.library: redis-py:v<版本号>(见 attributes.py),便于多语言、多客户端数据统一聚合。
异步客户端同样支持:redis/asyncio/observability/recorder.py提供 async-safe 的录制 API,复用与同步端相同的RedisMetricsCollector与配置(见 redis/asyncio/observability/recorder.py),因此一次otel.init(OTelConfig())即可同时覆盖同步与异步客户端。
仓库中还提供了完整的单元测试验证录制链路:tests/test_observability/test_recorder.py通过 mock MeterProvider,逐一验证各record_*函数是否正确地把参数透传给底层 OTel 仪器(Counter、Histogram、UpDownCounter),以及属性键是否符合语义约定。
5. 外部 OpenTelemetry 插桩(替代方案)
除原生集成外,也可以使用外部opentelemetry-instrumentation-redis包作为替代方案。该方案通过monkey-patching方式对 redis-py 进行插桩。
插桩(Instrumentation)是为流行框架和库开发的 OpenTelemetry 插件,用于记录重要操作(HTTP 请求、数据库查询、日志、错误等)。
安装:
pip install opentelemetry-instrumentation-redis插桩用法:
from opentelemetry.instrumentation.redis import RedisInstrumentor RedisInstrumentor().instrument()插桩完成后即可照常使用 redis-py,同步与异步客户端均受支持:
# 同步客户端 client = redis.Redis() client.get("my-key") # 异步客户端 client = redis.asyncio.Redis() await client.get("my-key")两种方案的选择建议:原生集成不依赖对客户端内部方法的运行时补丁,指标更全面(覆盖连接池、PubSub、Streaming、CSC 等维度),且与库的演进同步维护,是官方推荐路径;外部插桩更轻量,适合只想快速获得命令级 tracing 的场景,但指标维度有限且依赖第三方包的维护节奏。
6. OpenTelemetry API 使用入门
OpenTelemetry API 是用于插桩代码并采集 traces、metrics、logs 遥测数据的编程接口。即使不借助插桩包,你也可以直接用它对关键操作进行手工埋点:
from opentelemetry import trace tracer = trace.get_tracer("app_or_package_name", "1.0.0") # 创建名为 "operation-name"、kind="server" 的 span with tracer.start_as_current_span("operation-name", kind=trace.SpanKind.CLIENT) as span: do_some_work()用属性记录上下文信息:
if span.is_recording(): span.set_attribute("http.method", "GET") span.set_attribute("http.route", "/projects/:id")监控异常:
except ValueError as exc: # 记录异常并更新 span 状态 span.record_exception(exc) span.set_status(trace.Status(trace.StatusCode.ERROR, str(exc)))7. 用 Uptrace 可视化 redis-py 遥测数据
Uptrace 是一款支持分布式追踪、指标与日志的开源 APM 工具,可用于监控应用并配置自动告警,通过邮件、Slack、Telegram 等渠道接收通知。
仓库在 docs/examples/opentelemetry 提供了完整的 Uptrace 集成示例(含 docker-compose.yml、otel-collector.yaml 与 main.py)。运行步骤概览:
- 克隆仓库后进入
docs/examples/opentelemetry目录; - (可选)创建虚拟环境:
python3 -m venv .venv && source .venv/bin/activate; - 安装依赖:
pip install -e .(依赖见 requirements.txt); - 用 Docker 启动 Redis 与 Uptrace:
docker-compose up -d,并用docker-compose logs uptrace确认 Uptrace 已就绪; - 运行示例:
python3 main.py,随后按 CLI 输出的 trace 链接查看追踪(示例输出形如trace: http://localhost:14318/traces/...)。
示例main.py的核心逻辑(见 main.py):调用uptrace.configure_opentelemetry(...)配置导出端点,然后RedisInstrumentor().instrument()完成插桩,在handle_request中执行GET/SET/MSET及 pipeline 批量写入,并在自定义 span 内观察这些 Redis 命令的耗时。
8. 用 OpenTelemetry Collector 监控 Redis Server 性能
除了监控 redis-py 客户端,还可以用 OpenTelemetry Collector Agent 监控Redis Server 自身的性能。
OpenTelemetry Collector 是应用与追踪/指标后端(如 Uptrace、Jaeger)之间的代理(proxy/middleman):它接收遥测数据、进行处理,再导出到能够持久化存储的 APM 工具。
例如,使用 Otel Collector 的OpenTelemetry Redis receiver(redisreceiver)即可采集 Redis 服务端指标——包括内存使用、键命中率(keyspace hit rate)、连接数、命令处理速率等。仓库示例中docs/examples/opentelemetry/config/otel-collector.yaml演示了 Collector 的接收与导出管道配置,配合 docker-compose 即可一键拉起完整的采集链路。
9. 告警与通知配置
Uptrace 还支持基于 OpenTelemetry 指标配置告警规则(alerting rules)。以下 monitor 使用group by node表达式,当某个 Redis 分片(shard)宕机时触发告警:
monitors: - name: Redis shard is down metrics: - redis_up as $redis_up query: - group by cluster # 监控每个集群 - group by bdb # 每个数据库 - group by node # 每个分片 - $redis_up min_allowed_value: 1 # 分片需持续宕机 5 分钟才触发告警 for_duration: 5m也可以编写更复杂的表达式。例如,当 keyspace 命中率低于 75% 时告警:
monitors: - name: Redis read hit rate < 75% metrics: - redis_keyspace_read_hits as $hits - redis_keyspace_read_misses as $misses query: - group by cluster - group by bdb - group by node - $hits / ($hits + $misses) as hit_rate min_allowed_value: 0.75 for_duration: 5m这类告警依赖redis_up、redis_keyspace_read_hits等由 Redis receiver 导出的服务端指标,可与客户端指标互为补充:客户端指标反映调用侧体验,服务端指标反映实例侧健康状况。
10. 下一步学习方向
在打通 redis-py → OTel → 后端的采集链路后,可以进一步:
- 学习为应用配置
uptrace-python,把 spans、metrics、logs 统一导出到 Uptrace; - 将本文的指标采集与应用的 Web 框架(如 Django、Flask、FastAPI)及 ORM(如 SQLAlchemy)的 OpenTelemetry 插桩结合,构建覆盖 HTTP 入口 → 业务逻辑 → Redis 调用的完整调用链;
- 深入阅读本仓库源码:指标定义见 redis/observability/metrics.py,配置解析见 redis/observability/config.py,录制 API 见 redis/observability/recorder.py,属性语义约定见 redis/observability/attributes.py;
- 参考测试用例 tests/test_observability/test_recorder.py 与 tests/test_observability/test_cluster_metrics_error_handling.py,理解各指标录制与异常场景的处理方式。
【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考