diff --git a/example/otel/README.md b/example/otel/README.md index 60d4d121..40db8aca 100644 --- a/example/otel/README.md +++ b/example/otel/README.md @@ -1,9 +1,16 @@ -### OpenTelemetry Example -Prints spans and metrics to the console. -#### To Run: -- `docker-compose up -d` -- `go run .` +# Example for go-redis OpenTelemetry instrumentation -When you're finished, be sure to run `docker-compose down` to shutdown -the redis server. +This example requires running Redis Server. You can start Redis Server using Docker: +```shell +docker-compose up -d +``` + +To run this example: + +```shell +go run . +``` + +See [Monitoring performance and errors](https://redis.uptrace.dev/guide/tracing.html) for more +details. diff --git a/example/otel/docker-compose.yml b/example/otel/docker-compose.yml index c2d7f1d4..ff8f0669 100644 --- a/example/otel/docker-compose.yml +++ b/example/otel/docker-compose.yml @@ -1,8 +1,9 @@ version: '3' + services: redis-server: image: redis ports: - - "6379:6379" + - '6379:6379' redis-cli: image: redis diff --git a/example/otel/example-client.go b/example/otel/main.go similarity index 54% rename from example/otel/example-client.go rename to example/otel/main.go index 546d6c8f..9bb272eb 100644 --- a/example/otel/example-client.go +++ b/example/otel/main.go @@ -2,35 +2,45 @@ package main import ( "context" - "log" "sync" - "time" "github.com/go-redis/redis/extra/redisotel/v8" "github.com/go-redis/redis/v8" "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) +var tracer = otel.Tracer("redisexample") + func main() { ctx := context.Background() - stop := runExporter(ctx) - defer stop(ctx) + stop := configureOpentelemetry(ctx) + defer stop() rdb := redis.NewClient(&redis.Options{ Addr: ":6379", }) - rdb.AddHook(redisotel.TracingHook{}) - tracer := otel.Tracer("Example tracer") - ctx, span := tracer.Start(ctx, "start-test-span") + ctx, span := tracer.Start(ctx, "handleRequest") + defer span.End() - rdb.Set(ctx, "First value", "value_1", 0) + if err := handleRequest(ctx); err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, err.Error()) + } +} - rdb.Set(ctx, "Second value", "value_2", 0) +func handleRequest(ctx context.Context) error { + if err := rdb.Set(ctx, "First value", "value_1", 0).Err(); err != nil { + return err + } + if err := rdb.Set(ctx, "Second value", "value_2", 0).Err(); err != nil { + return err + } var group sync.WaitGroup @@ -40,27 +50,30 @@ func main() { defer group.Done() val := rdb.Get(ctx, "Second value").Val() if val != "value_2" { - log.Fatalf("val was not set. expected: %s but got: %s", "value_2", val) + panic(err) } }() } + group.Wait() - rdb.Del(ctx, "First value") - rdb.Del(ctx, "Second value") + if err := rdb.Del(ctx, "First value").Err(); err != nil { + return err + } + if err := rdb.Del(ctx, "Second value").Err(); err != nil { + return err + } - // Wait some time to allow spans to export - <-time.After(5 * time.Second) - span.End() + return nil } -func runExporter(ctx context.Context) func(context.Context) { +func configureOpentelemetry(ctx context.Context) func() { provider := sdktrace.NewTracerProvider() otel.SetTracerProvider(provider) exp, err := stdouttrace.New(stdouttrace.WithPrettyPrint()) if err != nil { - log.Fatal(err) + panic(err) } bsp := sdktrace.NewBatchSpanProcessor(exp) @@ -68,7 +81,7 @@ func runExporter(ctx context.Context) func(context.Context) { return func(ctx context.Context) { if err := provider.Shutdown(ctx); err != nil { - log.Printf("Shutdown failed: %s", err) + panic(err) } } } diff --git a/tx.go b/tx.go index 08d381a9..8c9d8720 100644 --- a/tx.go +++ b/tx.go @@ -13,7 +13,8 @@ const TxFailedErr = proto.RedisError("redis: transaction failed") // Tx implements Redis transactions as described in // http://redis.io/topics/transactions. It's NOT safe for concurrent use // by multiple goroutines, because Exec resets list of watched keys. -// If you don't need WATCH it is better to use Pipeline. +// +// If you don't need WATCH, use Pipeline instead. type Tx struct { baseClient cmdable