redis-py 集成 OpenTelemetry 可观测性:从原生 Metrics 采集到 Uptrace 分布式链路追踪实战 redis-py 集成 OpenTelemetry 可观测性从原生 Metrics 采集到 Uptrace 分布式链路追踪实战【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py本文以 docs/examples/opentelemetry/README.md 与 docs/opentelemetry.rst 为骨架系统讲解 redis-py 的两条可观测性集成路径官方推荐的原生 OpenTelemetry Metrics 集成通过redis.observability模块以及基于opentelemetry-instrumentation-redis的分布式追踪替代方案。读完本文你将掌握如何初始化指标采集、按 Metric Group 精细化配置、自定义直方图分桶、使用上下文管理器自动清理并通过仓库自带的 Docker 示例快速在 Uptrace 上查看 Redis 客户端的完整调用链。OpenTelemetry 与分布式追踪基础OpenTelemetry 是一个开源的、厂商无关的可观测性框架统一覆盖 traces、metrics 与 logs 三类遥测数据。它由 OpenCensus 与 OpenTracing 两个项目合并而来由云原生计算基金会CNCF托管。核心价值在于一次埋点、随处迁移应用只需按 OpenTelemetry 标准完成一次插桩之后更换 DataDog、Uptrace、Jaeger 等后端时无需改动业务代码。Span跨度是应用处理一次请求时执行的某个操作单元例如一次数据库查询或一次网络调用。Trace链路则是由 Span 构成的树状结构反映一次请求在应用内的完整路径根 Spanroot span是链路中的第一个 Span。在分布式环境下tracing 还能揭示微服务之间的调用关系与相互影响帮助定位某个服务自身的性能瓶颈及其对外部服务的连带效应。对 redis-py 而言可观测性有两个层面一是客户端指标本仓库内置原生支持推荐使用二是分布式链路追踪记录客户端到 Redis Server 的调用 Span需要外部 instrumentation 包。原生 OpenTelemetry 集成推荐redis-py 内置了对 OpenTelemetry 指标采集的原生支持。相比外部插桩原生集成的优势在于无需 monkey-patching且指标覆盖更全面连接池、PubSub、Stream、客户端缓存等。核心入口在 redis/observability/init.py对外暴露get_observability_instance、OTelConfig、MetricGroup、TelemetryOption等 API。安装依赖使用 extras 安装方式一次性拉取 OTel 所需的 API、SDK 与 OTLP HTTP 导出器pip install redis[otel]基本初始化原生集成采用单例模式只需在应用启动时初始化一次之后所有 Redis 客户端都会自动采集指标。初始化前必须先设置好全局MeterProvider因为 redis-py 直接使用应用设置的全局 Provider见 redis/observability/providers.py 中get_meter_provider的实现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(endpointhttp://localhost:4318/v1/metrics) reader PeriodicExportingMetricReader(exporterexporter, export_interval_millis10000) 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(hostlocalhost, port6379) r.set(key, value) # 指标自动采集 r.get(key) # 4. 应用退出时关闭可观测性并刷新待导出指标 otel.shutdown()两点实现细节值得注意若 metrics 已启用但应用未设置全局MeterProvider即仍为NoOpMeterProviderget_meter_provider会抛出RuntimeError并附上完整的排查与初始化指引otel.shutdown()不会关闭应用自有的全局MeterProvider只做一次force_flush以确保待导出指标不丢失见 providers.py。OTelConfig 配置项详解OTelConfig是全部可观测性配置的载体位于 redis/observability/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_namesTrue, # 在 PubSub 指标中隐藏频道名 hide_stream_namesTrue, # 在流式指标中隐藏 Stream 名 ) otel get_observability_instance() otel.init(config)其中MetricGroup是IntFlag枚举config.py支持按位组合。命令过滤通过should_track_command实现优先判断 include 列表若指定则白名单生效否则按 exclude 列表排除config.py。命令名会统一转为大写后匹配避免大小写差异。指标分组Metric Group速查表Metric Group描述CONNECTION_BASIC连接创建耗时、relaxed timeout、连接交接handoffCONNECTION_ADVANCED连接等待耗时、超时、关闭连接数COMMAND命令执行耗时RESILIENCY错误计数、维护通知、地理故障切换PUBSUBPubSub 消息计数发布/接收STREAMINGStream 消息滞后XREAD/XREADGROUPCSC客户端缓存请求、逐出、节省字节数注意MetricGroup.RESILIENCY在 redis/observability/metrics.py 中还额外注册了redis.client.geofailover.failoversMultiDbClient 故障切换计数这是对文档表格的补充。可用指标清单以下指标在 metrics.py 中定义按分组启用RedisMetricsCollector.__init__会按config.metric_groups条件初始化对应仪器连接指标CONNECTION_BASIC / CONNECTION_ADVANCEDdb.client.connection.create_time—— 新建连接耗时直方图单位秒db.client.connection.timeouts—— 从连接池获取连接时的超时次数计数器db.client.connection.wait_time—— 从连接池获取连接的等待耗时直方图单位秒db.client.connection.count—— 当前连接池中的连接数按状态idle/used标记UpDownCounterredis.client.connection.closed—— 关闭连接总数计数器带 close.reason 属性application_close / error / healthcheck_failedredis.client.connection.relaxed_timeout—— relaxed timeout 事件UpDownCounterrelaxed 加 1、unrelaxed 减 1redis.client.connection.handoff—— 连接交接事件计数计数器例如 MOVING 通知后的交接命令指标COMMANDdb.client.operation.duration—— 命令执行耗时直方图单位秒韧性指标RESILIENCYredis.client.errors—— 按错误类型计数的错误总数计数器redis.client.maintenance.notifications—— 服务端维护通知计数计数器redis.client.geofailover.failovers—— 使用 MultiDbClient 发生的故障切换总数计数器PubSub 指标PUBSUBredis.client.pubsub.messages—— 发布与接收的消息计数计数器带 directionpublish/receive与频道名属性流式指标STREAMINGredis.client.stream.lag—— 消息端到端滞后直方图单位秒体现应用开始处理消息时的陈旧程度客户端缓存指标CSCredis.client.csc.requests—— 缓存请求计数带 hit/miss 结果属性计数器redis.client.csc.evictions—— 缓存逐出计数带原因属性full / invalidation计数器redis.client.csc.network_saved—— 缓存节省的字节数计数器redis.client.csc.items—— 当前缓存条目数observable gauge需通过init_csc_items(callback)注册回调这些指标遵循 OTel 数据库客户端语义约定通用属性如db.systemredis、server.address、server.port、network.peer.address等由 redis/observability/attributes.py 中的AttributeBuilder统一构建。自定义直方图分桶不同业务对延迟分布的关注粒度不同OTelConfig提供四个分桶参数分别对应命令耗时、连接创建、连接等待、流处理耗时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], )若不传则使用config.py中的默认分桶命令耗时默认 14 个桶从 0.0001s 到 2.5s其余默认 11 个桶从 0.0001s 到 10s。这些值会作为explicit_bucket_boundaries_advisory传给Meter.create_histogram见 metrics.py。如需在 SDK 层面强制生效还可以通过 OpenTelemetry 的ViewExplicitBucketHistogramAggregation指定db.client.operation.duration等仪器名的分桶边界OTelConfig的 docstring 提供了完整示例。上下文管理器用法需要自动清理时可使用get_provider_manager()上下文管理器退出with块时自动执行 shutdown 并刷新指标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) # 退出时指标自动刷新导出实现上OTelProviderManager.__exit__会调用shutdown()providers.py。错误处理与侵入性保证原生集成被设计为非侵入式所有指标记录方法都包裹在 try-except 逻辑中采集器初始化时对 OTel SDK 做可选导入未安装时OTEL_AVAILABLEFalse指标层优雅降级并且每个 record 方法在对应仪器未启用时直接返回如if not hasattr(self, operation_duration): return。因此指标采集过程中的任何异常都不会影响你的 Redis 业务操作。外部 OpenTelemetry 插桩备选方案若需要的是分布式链路追踪Span 记录而非指标可以选用外部opentelemetry-instrumentation-redis包。它通过 monkey-patching 对 redis-py 进行插桩pip install opentelemetry-instrumentation-redis插桩后业务代码无需改动from opentelemetry.instrumentation.redis import RedisInstrumentor RedisInstrumentor().instrument()之后同步与异步客户端均自动产生 Span# 同步客户端 client redis.Redis() client.get(my-key) # 异步客户端 client redis.asyncio.Redis() await client.get(my-key)仓库自带的示例 docs/examples/opentelemetry/main.py 正是走这条路径通过uptrace.configure_opentelemetry配置 DSN调用RedisInstrumentor().instrument()后在handle_request中执行get、set、mset与 pipeline 批量操作并以tracer.start_as_current_span(handle-request, kindtrace.SpanKind.CLIENT)包裹业务逻辑。OpenTelemetry API 手动埋点即便不依赖任何 Redis 专用包你也可以直接用 OpenTelemetry API 为关键操作手动埋点。先获取 tracer再创建 Spanfrom opentelemetry import trace tracer trace.get_tracer(app_or_package_name, 1.0.0) # 创建一个名为 operation-name、kindCLIENT 的 Span with tracer.start_as_current_span(operation-name, kindtrace.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)))端到端示例Docker Uptrace 查看 Redis 调用链仓库在 docs/examples/opentelemetry 下提供了完整可运行的监控示例README 原文步骤它同时启动 Redis Server 与 Uptrace需要 Docker 环境。Step 1获取示例代码将仓库克隆到本地后进入示例目录git clone https://gitcode.com/GitHub_Trending/re/redis-py cd docs/examples/opentelemetryStep 2可选创建虚拟环境python3 -m venv .venv source .venv/bin/activeStep 3安装依赖requirements.txt 声明了redis、uptrace与opentelemetry-instrumentation-redis三个包pip install -e .Step 4用 Docker 启动服务并确认 Uptrace 正常运行docker-compose up -d docker-compose logs uptracedocker-compose.yml 共编排了 8 个服务分工如下clickhouseUptrace 的存储后端数据保留策略由 uptrace.yml 中的ch_schema控制默认 spans 保留 30 天、metrics 保留 90 天uptraceAPM 前端与 OTLP 接收端监听 14317gRPC与 14318HTTP/UIotel-collectorOpenTelemetry Collector接收 OTLP 并转发给 Uptrace端口 4317/4318vector日志流水线alertmanagermailhog告警路由与测试邮箱redis-server被监控的 Redis 实例端口 6379。uptrace.yml中预置了两个隔离项目项目 1 用于监控 Uptrace 自身项目 2token 为project2_secret_token用于监控你的应用——这与 main.py 中dsnhttp://project2_secret_tokenlocalhost:14317/2一一对应。Step 5运行 Redis 客户端示例根据 CLI 输出的链接查看链路python3 main.py trace: http://localhost:14318/traces/ee029d8782242c8ed38b16d961093b35示例程序main.py会先执行一次请求并打印 trace URL随后循环 10000 次、每秒执行一次handle_request持续产生遥测数据。你还可以直接打开 Uptrace UIhttp://localhost:14318查看可用的 spans、日志与指标。关于 tracing 中 Span 与 Trace 的关系可参考 docs/opentelemetry.rst 中的配套图示Span 是操作单元Trace 是 Span 的树状聚合。监控 Redis Server 性能与告警除了监控客户端还可以通过 OpenTelemetry Collector 的 Redis receiver 监控Redis Server 自身的性能。Collector 是应用与 APM 工具Uptrace、Jaeger 等之间的代理接收遥测数据、处理后导出给可持久化存储的后端。示例中的 config/otel-collector.yaml 已经配置好receivers: redis: endpoint: redis-server:6379 collection_interval: 10s该配置每 10 秒抓取一次 Redis 实例指标配合 hostmetrics 一起进入metrics/hostmetrics管道经batch与resourcedetection处理器后导出到 Uptrace可以在 Uptrace 中查看 Redis 的实时指标面板。告警方面Uptrace 支持基于 OpenTelemetry 指标编写告警规则。例如以下监控按 cluster、bdb、node 分组当单个 Redis 分片宕机redis_up低于 1持续 5 分钟时触发告警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也可以构造更复杂的表达式例如当键空间命中率低于 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示例仓库中的 config/alertmanager.yml 与uptrace.yml的alertmanager_client段已经将 Uptrace 与 AlertManager9093 端口打通告警可通过邮件等渠道下发。源码验证与测试以上原生集成能力均有源码与测试背书可进一步深入阅读配置解析与默认值redis/observability/config.py指标仪器定义与记录方法redis/observability/metrics.py单例生命周期与 Provider 管理redis/observability/providers.py语义约定属性构建redis/observability/attributes.py公开 API 入口redis/observability/init.py测试用例tests/test_observability 与 tests/test_asyncio/test_observability含集群指标错误处理与 Recorder 行为验证完整文档docs/opentelemetry.rst需要说明的适用前提原生指标集成要求应用自行设置全局MeterProvider且不能是 NoOp因此初始化顺序必须是先 Provider 后otel.init()Metrics 之外仍处于规划阶段的 traces/logs 则由外部 instrumentation 方案opentelemetry-instrumentation-redis与 OpenTelemetry API 手动埋点补齐。在规划生产环境的可观测性时可按原生指标兜底 外部插桩补链路 手动埋点补业务语义的组合落地。【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考