{
  "id": "observability",
  "title": "Observability",
  "url": "https://redis.io/docs/latest/develop/clients/redis-py/observability/",
  "summary": "Monitor your client's activity for optimization and debugging.",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-04-01T08:10:08-05:00",
  "page_type": "content",
  "content_hash": "90185b7fe607cf2f2a8d54fbdb386c9ecc4eb17d1a7c9626b90f40d17914ec92",
  "sections": [
    {
      "id": "installation",
      "title": "Installation",
      "role": "setup",
      "text": "Install OTel support for `redis-py` with the following command:\n\n[code example]"
    },
    {
      "id": "import",
      "title": "Import",
      "role": "content",
      "text": "Start by importing the required OTel and Redis modules:\n\n#### Code Examples\n\n**Redis CLI:**\n\n[code example]\n\n**Available in:** Redis CLI, Go, Python\n\n**Go:**\n\n[code example]\n\n**Python:**\n\n[code example]"
    },
    {
      "id": "configure-the-meter-provider",
      "title": "Configure the meter provider",
      "role": "configuration",
      "text": "Otel uses a [Meter provider](https://opentelemetry.io/docs/concepts/signals/metrics/#meter-provider)\nto create the objects that collect the metric information. The example below\nconfigures a meter provider to export metrics to a local Grafana instance\nevery 10 seconds, but see the [OpenTelemetry Python docs](https://opentelemetry.io/docs/languages/python/)\nto learn more about other export options.\n\n#### Code Examples\n\n**Redis CLI:**\n\n[code example]\n\n**Available in:** Redis CLI, Go, Python\n\n**Go:**\n\n[code example]\n\n**Python:**\n\n[code example]"
    },
    {
      "id": "configure-the-redis-client",
      "title": "Configure the Redis client",
      "role": "configuration",
      "text": "You configure the client library for OTel only once per application. This will\nenable OTel for all Redis connections you create. The example below shows the\noptions you can pass to the observability instance via the `OTelConfig` object\nduring initialization.\n\n#### Code Examples\n\n**Redis CLI:**\n\n[code example]\n\n**Available in:** Redis CLI, Go, Python\n\n**Go:**\n\n[code example]\n\n**Python:**\n\n[code example]\n\n\n\nThe available options for `OTelConfig` are described in the table below:\n\n| Option | Type | Description |\n| --- | --- | --- |\n| `metric_groups` | `List[MetricGroup]` | List of metric groups to enable. By default, only `CONNECTION_BASIC` and `RESILIENCY` are enabled. See [Redis metric groups]() for a list of available groups. |\n| `include_commands` | `List[str]` | List of Redis commands to track. If set, only these commands will be tracked. Note that you should use the Redis command name rather than the Python method name where the two differ. |\n| `exclude_commands` | `List[str]` | List of Redis commands to exclude from tracking. If set, all commands except these will be tracked. Note that you should use the Redis command name rather than the Python method name where the two differ. |\n| `hide_pubsub_channel_names` | `bool` | If true, channel names in pub/sub metrics will be hidden. |\n| `hide_stream_names` | `bool` | If true, stream names in streaming metrics will be hidden. |\n| `buckets_operation_duration` | `List[float]` | List of bucket boundaries for the [`operation.duration`]() histogram (see [Custom histogram buckets](#custom-histogram-buckets) below). |\n| `buckets_stream_processing_duration` | `List[float]` | List of bucket boundaries for the [`stream.processing.duration`]() histogram (see [Custom histogram buckets](#custom-histogram-buckets) below). |\n| `buckets_connection_create_time` | `List[float]` | List of bucket boundaries for the [`connection.create.time`]() histogram (see [Custom histogram buckets](#custom-histogram-buckets) below). |\n| `buckets_connection_wait_time` | `List[float]` | List of bucket boundaries for the [`connection.wait.time`]() histogram (see [Custom histogram buckets](#custom-histogram-buckets) below). |"
    },
    {
      "id": "custom-histogram-buckets",
      "title": "Custom histogram buckets",
      "role": "content",
      "text": "For the histogram metrics, a reasonable default set of buckets is defined, but\nyou can customize the bucket boundaries to suit your needs (the buckets are the\nranges of data values counted for each bar of the histogram). Pass an increasing\nlist of float values to the `buckets_xxx` options when you create the `OTelConfig`\nobject. The first and last values in the list are the lower and upper bounds of the\nhistogram, respectively, and the values in between define the bucket boundaries."
    },
    {
      "id": "use-redis",
      "title": "Use Redis",
      "role": "content",
      "text": "Once you have configured the client, all Redis connections you create will be\nautomatically instrumented and the collected metrics will be exported to your\nconfigured destination.\n\nThe example below shows the simplest Redis connection and a few commands,\nbut see the\n[observability demonstration repository](https://github.com/redis-developer/redis-client-observability)\nfor an example that calls a variety of commands in a more realistic way.\n\n#### Code Examples\n\n**Redis CLI:**\n\n[code example]\n\n**Available in:** Redis CLI, Go, Python\n\n**Go:**\n\n[code example]\n\n**Python:**\n\n[code example]"
    },
    {
      "id": "shutdown",
      "title": "Shutdown",
      "role": "content",
      "text": "When your application exits, you should call the `shutdown()` method to ensure\nthat all pending metrics are exported.\n\n#### Code Examples\n\n**Redis CLI:**\n\n[code example]\n\n**Available in:** Redis CLI, Go, Python\n\n**Go:**\n\n[code example]\n\n**Python:**\n\n[code example]"
    }
  ],
  "examples": [
    {
      "id": "installation-ex0",
      "language": "bash",
      "code": "pip install redis[otel]",
      "section_id": "installation"
    },
    {
      "id": "import-ex0",
      "language": "go",
      "code": "import (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/redis/go-redis/extra/redisotel-native/v9\"\n\t\"github.com/redis/go-redis/v9\"\n\t\"go.opentelemetry.io/otel\"\n\t\"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc\"\n\t\"go.opentelemetry.io/otel/sdk/metric\"\n\t\"go.opentelemetry.io/otel/sdk/resource\"\n\tsemconv \"go.opentelemetry.io/otel/semconv/v1.24.0\"\n)",
      "section_id": "import"
    },
    {
      "id": "import-ex1",
      "language": "python",
      "code": "# OpenTelemetry metrics API\nfrom opentelemetry import metrics\nfrom opentelemetry.sdk.metrics import MeterProvider\nfrom opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader\nfrom opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter\n\n# Redis observability API\nfrom redis.observability.providers import get_observability_instance\nfrom redis.observability.config import OTelConfig, MetricGroup\n\n# Redis client\nimport redis",
      "section_id": "import"
    },
    {
      "id": "configure-the-meter-provider-ex0",
      "language": "go",
      "code": "ctx := context.Background()\n\n\t// Create OTLP exporter that sends metrics to the collector\n\t// Default endpoint is localhost:4317 (gRPC)\n\texporter, err := otlpmetricgrpc.New(ctx,\n\t\totlpmetricgrpc.WithInsecure(), // Use insecure for local development\n\t\t// For production, configure TLS and authentication:\n\t\t// otlpmetricgrpc.WithEndpoint(\"your-collector:4317\"),\n\t\t// otlpmetricgrpc.WithTLSCredentials(...),\n\t)\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Create resource with service name\n\tres, err := resource.New(ctx,\n\t\tresource.WithAttributes(\n\t\t\tsemconv.ServiceName(\n\t\t\t\tfmt.Sprintf(\"go-redis-examples:%d\", time.Now().Unix()),\n\t\t\t),\n\t\t),\n\t)\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Create meter provider with periodic reader\n\t// Metrics are exported every 10 seconds\n\tmeterProvider := metric.NewMeterProvider(\n\t\tmetric.WithResource(res),\n\t\tmetric.WithReader(\n\t\t\tmetric.NewPeriodicReader(exporter,\n\t\t\t\tmetric.WithInterval(10*time.Second),\n\t\t\t),\n\t\t),\n\t)\n\n\t// Set the global meter provider\n\totel.SetMeterProvider(meterProvider)",
      "section_id": "configure-the-meter-provider"
    },
    {
      "id": "configure-the-meter-provider-ex1",
      "language": "python",
      "code": "exporter = OTLPMetricExporter(endpoint=\"http://localhost:4318/v1/metrics\")\nreader = PeriodicExportingMetricReader(exporter=exporter, export_interval_millis=10000)\nprovider = MeterProvider(metric_readers=[reader])\nmetrics.set_meter_provider(provider)",
      "section_id": "configure-the-meter-provider"
    },
    {
      "id": "configure-the-redis-client-ex0",
      "language": "go",
      "code": "// Initialize OTel instrumentation BEFORE creating Redis clients\n\totelInstance := redisotel.GetObservabilityInstance()\n\tconfig := redisotel.NewConfig().\n\t\t// You must enable OTel explicitly\n\t\tWithEnabled(true).\n\t\t// Enable the metric groups you want to collect. Use bitwise OR\n\t\t// to combine multiple groups. The default is `MetricGroupAll`\n\t\t// which includes all groups.\n\t\tWithMetricGroups(redisotel.MetricGroupFlagCommand |\n\t\t\tredisotel.MetricGroupFlagConnectionBasic |\n\t\t\tredisotel.MetricGroupFlagResiliency |\n\t\t\tredisotel.MetricGroupFlagConnectionAdvanced).\n\t\t// Filter which commands to track\n\t\tWithIncludeCommands([]string{\"GET\", \"SET\"}).\n\t\tWithExcludeCommands([]string{\"DEBUG\", \"SLOWLOG\"}).\n\t\t// Privacy controls\n\t\tWithHidePubSubChannelNames(true).\n\t\tWithHideStreamNames(true).\n\t\t// Custom histogram buckets\n\t\tWithHistogramBuckets([]float64{\n\t\t\t0.0001, // 0.1ms\n\t\t\t0.0005, // 0.5ms\n\t\t\t0.001,  // 1ms\n\t\t\t0.005,  // 5ms\n\t\t\t0.01,   // 10ms\n\t\t\t0.05,   // 50ms\n\t\t\t0.1,    // 100ms\n\t\t\t0.5,    // 500ms\n\t\t\t1.0,    // 1s\n\t\t\t5.0,    // 5s\n\t\t\t10.0,   // 10s\n\t\t})\n\n\tif err := otelInstance.Init(config); err != nil {\n\t\tpanic(err)\n\t}",
      "section_id": "configure-the-redis-client"
    },
    {
      "id": "configure-the-redis-client-ex1",
      "language": "python",
      "code": "otel = get_observability_instance()\notel.init(OTelConfig(\n    # Metric groups to enable (default: CONNECTION_BASIC | RESILIENCY)\n    metric_groups=[\n        MetricGroup.CONNECTION_BASIC,    # Connection creation time, relaxed timeout\n        MetricGroup.CONNECTION_ADVANCED, # Connection wait time, timeouts, closed connections\n        MetricGroup.COMMAND,             # Command execution duration\n        MetricGroup.RESILIENCY,          # Error counts, maintenance notifications\n        MetricGroup.PUBSUB,              # PubSub message counts\n        MetricGroup.STREAMING,           # Stream message lag\n        MetricGroup.CSC,                 # Client Side Caching metrics\n    ],\n\n    # Filter which commands to track\n    include_commands=['GET', 'SET', 'HGET'],  # Only track these commands\n    # OR\n    exclude_commands=['DEBUG', 'SLOWLOG'],    # Track all except these\n\n    # Privacy controls\n    hide_pubsub_channel_names=True,  # Hide channel names in PubSub metrics\n    hide_stream_names=True,          # Hide stream names in streaming metrics\n\n    # Custom histogram buckets\n    buckets_operation_duration=[\n        0.0001, 0.00025, 0.0005, 0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1,\n        0.25, 0.5, 1, 2.5,\n    ],\n    buckets_stream_processing_duration=[\n        0.0001, 0.00025, 0.0005, 0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1,\n        0.25, 0.5, 1, 2.5,\n    ],\n    buckets_connection_create_time=[\n        0.0001, 0.00025, 0.0005, 0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1,\n        0.25, 0.5, 1, 2.5,\n    ],\n    buckets_connection_wait_time=[\n        0.0001, 0.00025, 0.0005, 0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1,\n        0.25, 0.5, 1, 2.5,\n    ],\n))",
      "section_id": "configure-the-redis-client"
    },
    {
      "id": "use-redis-ex0",
      "language": "go",
      "code": "rdb := redis.NewClient(&redis.Options{\n\t\tAddr:     \"localhost:6379\",\n\t\tPassword: \"\", // no password set\n\t\tDB:       0,  // use default DB\n\t})\n\n\trdb.Set(ctx, \"key\", \"value\", 0)\n\tv, err := rdb.Get(ctx, \"key\").Result()\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tfmt.Println(v)",
      "section_id": "use-redis"
    },
    {
      "id": "use-redis-ex1",
      "language": "python",
      "code": "r = redis.Redis(host='localhost', port=6379)\nr.set('key', 'value')  # Metrics collected automatically\nr.get('key')",
      "section_id": "use-redis"
    },
    {
      "id": "shutdown-ex0",
      "language": "go",
      "code": "rdb.Close()\n\totelInstance.Shutdown()\n\tmeterProvider.Shutdown(context.Background())",
      "section_id": "shutdown"
    },
    {
      "id": "shutdown-ex1",
      "language": "python",
      "code": "otel.shutdown()",
      "section_id": "shutdown"
    }
  ]
}
