# Valkey

> Instrument Valkey clients in Go applications with automatic command tracing using valkey-go and valkeyotel

Source: https://last9.io/docs/integrations/frameworks/go/valkey/

Use the `valkey-go` client with its built-in OpenTelemetry instrumentation (`valkeyotel`) to trace every Valkey command automatically. Each command produces a span with the command name, key, and server address.

## Prerequisites

- Go 1.22 or higher
- Valkey server running
- Last9 account with OTLP credentials

## Installation

1. **Install the Last9 Go Agent and valkey-go**

   ```bash
   go get github.com/last9/go-agent
   go get github.com/valkey-io/valkey-go
   ```

2. **Set Environment Variables**

   ```bash
   export OTEL_SERVICE_NAME="your-service"
   export OTEL_EXPORTER_OTLP_ENDPOINT="$last9_otlp_endpoint"
   export OTEL_EXPORTER_OTLP_HEADERS="Authorization=$last9_otlp_auth_header"
   export OTEL_TRACES_SAMPLER="always_on"
   export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production"
   ```

3. **Create an instrumented Valkey client**

   ```go
   package main

   import (
       "context"
       "log"

       "github.com/last9/go-agent"
       "github.com/valkey-io/valkey-go"
       "github.com/valkey-io/valkey-go/valkeyotel"
   )

   func main() {
       if err := agent.Start(); err != nil {
           log.Fatalf("failed to start agent: %v", err)
       }
       defer agent.Shutdown()

       client, err := valkey.NewClient(valkey.ClientOption{
           InitAddress: []string{"localhost:6379"},
       })
       if err != nil {
           log.Fatalf("failed to create valkey client: %v", err)
       }
       defer client.Close()

       // Wrap with OTel instrumentation — every command is now traced
       tracedClient := valkeyotel.NewClient(client)

       ctx := context.Background()

       // Commands are traced automatically
       if err := tracedClient.Do(ctx, tracedClient.B().Set().Key("hello").Value("world").Ex(60).Build()).Error(); err != nil {
           log.Printf("set failed: %v", err)
       }

       val, err := tracedClient.Do(ctx, tracedClient.B().Get().Key("hello").Build()).ToString()
       if err != nil {
           log.Printf("get failed: %v", err)
       }
       log.Println("got:", val)
   }
   ```

## Using with Gin

Pass `c.Request.Context()` into every Valkey command so the command span is parented to the incoming HTTP request span:

```go
package main

import (
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/last9/go-agent"
    ginagent "github.com/last9/go-agent/instrumentation/gin"
    "github.com/valkey-io/valkey-go"
    "github.com/valkey-io/valkey-go/valkeyotel"
)

var tracedClient valkey.Client

func main() {
    if err := agent.Start(); err != nil {
        log.Fatalf("failed to start agent: %v", err)
    }
    defer agent.Shutdown()

    client, err := valkey.NewClient(valkey.ClientOption{
        InitAddress: []string{"localhost:6379"},
    })
    if err != nil {
        log.Fatalf("failed to create valkey client: %v", err)
    }
    defer client.Close()

    tracedClient = valkeyotel.NewClient(client)

    r := ginagent.Default()
    r.GET("/cache/:key", getCacheHandler)
    log.Fatal(r.Run(":8080"))
}

func getCacheHandler(c *gin.Context) {
    // Pass c.Request.Context() so this span is a child of the HTTP span
    val, err := tracedClient.Do(c.Request.Context(),
        tracedClient.B().Get().Key(c.Param("key")).Build(),
    ).ToString()
    if err != nil {
        c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
        return
    }
    c.JSON(http.StatusOK, gin.H{"value": val})
}
```

## What Gets Traced Automatically

| Attribute       | Example              |
| --------------- | -------------------- |
| `db.system`     | `valkey`             |
| `db.operation`  | `GET`, `SET`, `HGET` |
| `net.peer.name` | `localhost`          |
| `net.peer.port` | `6379`               |

## View Traces

Navigate to [Trace Explorer](https://app.last9.io/traces) in Last9. Filter by `db.system = valkey` to see all Valkey commands.

---

## Troubleshooting

Please get in touch with us on [Discord](https://discord.com/invite/Q3p2EEucx9) or [Email](mailto:support@last9.io) if you have any questions.
