From 3d25b7590530800e85362fdf7443513f279b3e16 Mon Sep 17 00:00:00 2001 From: hossein Date: Thu, 2 Jan 2025 15:13:02 +0330 Subject: [PATCH] feat(rueidis): add auto instrumentation for github.com/redis/rueidis. --- Dockerfile | 3 + Makefile | 3 +- examples/httpPlusdb/docker-compose.yaml | 1 + examples/rueidis/Dockerfile | 7 + examples/rueidis/README.md | 20 + examples/rueidis/docker-compose.yaml | 52 + examples/rueidis/go.mod | 7 + examples/rueidis/go.sum | 9 + examples/rueidis/jaeger.png | Bin 0 -> 135343 bytes examples/rueidis/main.go | 75 + internal/pkg/inject/offset_results.json | 1622 +++++++++++++++++ .../github.com/redis/rueidis/bpf/probe.bpf.c | 143 ++ .../redis/rueidis/bpf_arm64_bpfel.go | 212 +++ .../github.com/redis/rueidis/bpf_x86_bpfel.go | 212 +++ .../bpf/github.com/redis/rueidis/probe.go | 178 ++ .../github.com/redis/rueidis/probe_test.go | 79 + internal/pkg/instrumentation/manager.go | 2 + internal/tools/inspect/cmd/offsetgen/main.go | 20 + internal/tools/inspect/render.go | 1 + .../github.com/redis/rueidis/go.mod.tmpl | 7 + .../github.com/redis/rueidis/main.go.tmpl | 7 + 21 files changed, 2659 insertions(+), 1 deletion(-) create mode 100644 examples/rueidis/Dockerfile create mode 100644 examples/rueidis/README.md create mode 100644 examples/rueidis/docker-compose.yaml create mode 100644 examples/rueidis/go.mod create mode 100644 examples/rueidis/go.sum create mode 100644 examples/rueidis/jaeger.png create mode 100644 examples/rueidis/main.go create mode 100644 internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf/probe.bpf.c create mode 100644 internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf_arm64_bpfel.go create mode 100644 internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf_x86_bpfel.go create mode 100644 internal/pkg/instrumentation/bpf/github.com/redis/rueidis/probe.go create mode 100644 internal/pkg/instrumentation/bpf/github.com/redis/rueidis/probe_test.go create mode 100644 internal/tools/inspect/templates/github.com/redis/rueidis/go.mod.tmpl create mode 100644 internal/tools/inspect/templates/github.com/redis/rueidis/main.go.tmpl diff --git a/Dockerfile b/Dockerfile index 4cac326a3..9f4006dac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,9 @@ FROM --platform=$BUILDPLATFORM golang:1.23.4-bookworm@sha256:2e838582004fab0931 RUN apt-get update && apt-get install -y curl clang gcc llvm make libbpf-dev +ARG GOPROXY +ENV GOPROXY=$GOPROXY + WORKDIR /app # pre-copy/cache go.mod for pre-downloading dependencies and only redownloading diff --git a/Makefile b/Makefile index 69f328b2c..49ad698f2 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ license-header-check: exit 1; \ fi -.PHONY: fixture-nethttp fixture-gin fixture-databasesql fixture-nethttp-custom fixture-otelglobal fixture-autosdk fixture-kafka-go +.PHONY: fixture-nethttp fixture-gin fixture-databasesql fixture-nethttp-custom fixture-otelglobal fixture-autosdk fixture-kafka-go fixture-rueidis fixture-nethttp-custom: fixtures/nethttp_custom fixture-nethttp: fixtures/nethttp fixture-gin: fixtures/gin @@ -168,6 +168,7 @@ fixture-grpc: fixtures/grpc fixture-otelglobal: fixtures/otelglobal fixture-autosdk: fixtures/autosdk fixture-kafka-go: fixtures/kafka-go +fixture-rueidis: fixtures/rueidis fixtures/%: LIBRARY=$* fixtures/%: $(MAKE) docker-build diff --git a/examples/httpPlusdb/docker-compose.yaml b/examples/httpPlusdb/docker-compose.yaml index 2a99d3847..cc0aaed6c 100644 --- a/examples/httpPlusdb/docker-compose.yaml +++ b/examples/httpPlusdb/docker-compose.yaml @@ -10,6 +10,7 @@ services: depends_on: - jaeger build: + no_cache: true context: . dockerfile: ./Dockerfile pid: "host" diff --git a/examples/rueidis/Dockerfile b/examples/rueidis/Dockerfile new file mode 100644 index 000000000..19c4beb20 --- /dev/null +++ b/examples/rueidis/Dockerfile @@ -0,0 +1,7 @@ +FROM golang:1.23.4@sha256:7ea4c9dcb2b97ff8ee80a67db3d44f98c8ffa0d191399197007d8459c1453041 +WORKDIR /app +COPY ./*.go . +RUN go mod init main +RUN go mod tidy +RUN go build -o main +ENTRYPOINT ["/app/main"] diff --git a/examples/rueidis/README.md b/examples/rueidis/README.md new file mode 100644 index 000000000..d67e251f2 --- /dev/null +++ b/examples/rueidis/README.md @@ -0,0 +1,20 @@ +# Example of Auto instrumentation of HTTP server + +Server exposes an endpoint `/do.` When we hit the endpoint, it sets a random value for `test_key` in redis and then +retrieves it using rueidis client. + +For testing auto instrumentation, we can use the docker compose. + +To run the example, bring up the services using the command. + +``` +docker compose up --build +``` + +Now, you can hit roll dice server using the below command +``` +curl localhost:8081/do +``` +Every hit to the server should generate a trace that we can observe in [Jaeger UI](http://localhost:16686/) + +Example trace ![Image](jaeger.png) diff --git a/examples/rueidis/docker-compose.yaml b/examples/rueidis/docker-compose.yaml new file mode 100644 index 000000000..b52247ed0 --- /dev/null +++ b/examples/rueidis/docker-compose.yaml @@ -0,0 +1,52 @@ +networks: + default: + name: rueidis + driver: bridge + +services: + redis: + image: redis:7.2 + + app: + depends_on: + - jaeger + - redis + build: + context: . + dockerfile: ./Dockerfile + pid: "host" + ports: + - "8081:8081" + volumes: + - /proc:/host/proc + + go-auto: + depends_on: + - app + build: + context: ../.. + dockerfile: Dockerfile + privileged: true + pid: "host" + environment: + - OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318 + - OTEL_GO_AUTO_TARGET_EXE=/app/main + - OTEL_SERVICE_NAME=rueidis-app + - OTEL_PROPAGATORS=tracecontext,baggage + volumes: + - /proc:/host/proc + + jaeger: + image: jaegertracing/all-in-one:1.60@sha256:4fd2d70fa347d6a47e79fcb06b1c177e6079f92cba88b083153d56263082135e + ports: + - "16686:16686" + - "14268:14268" + environment: + - COLLECTOR_OTLP_ENABLED=true + - LOG_LEVEL=debug + - JAEGER_DISABLED=true + deploy: + resources: + limits: + memory: 300M + restart: unless-stopped diff --git a/examples/rueidis/go.mod b/examples/rueidis/go.mod new file mode 100644 index 000000000..887adaec8 --- /dev/null +++ b/examples/rueidis/go.mod @@ -0,0 +1,7 @@ +module go.opentelemetry.io/auto/examples/rueidis + +go 1.20 + +require github.com/redis/rueidis v1.0.40 + +require golang.org/x/sys v0.19.0 // indirect diff --git a/examples/rueidis/go.sum b/examples/rueidis/go.sum new file mode 100644 index 000000000..58831ca59 --- /dev/null +++ b/examples/rueidis/go.sum @@ -0,0 +1,9 @@ +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/redis/rueidis v1.0.40 h1:zoC+GUTdNHhP7ZHrnMiIDcP16DUEVcxsPThQsvD7yDg= +github.com/redis/rueidis v1.0.40/go.mod h1:bnbkk4+CkXZgDPEbUtSos/o55i4RhFYYesJ4DS2zmq0= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/examples/rueidis/jaeger.png b/examples/rueidis/jaeger.png new file mode 100644 index 0000000000000000000000000000000000000000..c4af6d162356a4b17dc605e758601308d3b7260e GIT binary patch literal 135343 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

V}Zl2aRVFbK5G8 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

_@ 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 E2iL?`m;e9( literal 0 HcmV?d00001 diff --git a/examples/rueidis/main.go b/examples/rueidis/main.go new file mode 100644 index 000000000..d8df87bbd --- /dev/null +++ b/examples/rueidis/main.go @@ -0,0 +1,75 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "math/rand" + "net/http" + + "github.com/redis/rueidis" +) + +const testKey = "test_key" + +type server struct { + client rueidis.Client +} + +func (s *server) Do(w http.ResponseWriter, req *http.Request) { + randomValue := fmt.Sprintf("random_value_%d", rand.Intn(1000)) + err := setKey(req.Context(), s.client, testKey, randomValue) + if err != nil { + fmt.Println(fmt.Errorf("failed to set key: %v", err)) + } + fmt.Printf("Set key '%s' with value: %s\n", testKey, randomValue) + + value, err := getKey(req.Context(), s.client, testKey) + if err != nil { + fmt.Println(fmt.Errorf("failed to get key: %v", err)) + } + fmt.Printf("Got value for key '%s': %s\n", testKey, value) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + _ = json.NewEncoder(w).Encode(map[string]string{"value": value}) +} + +func main() { + address := "redis:6379" + fmt.Println("Connecting to redis server...") + fmt.Println(address) + + client, err := rueidis.NewClient(rueidis.ClientOption{ + InitAddress: []string{address}, + SelectDB: 0, + }) + if err != nil { + log.Fatalf("Failed to create Redis client: %v", err) + } + defer client.Close() + + s := &server{client: client} + + http.HandleFunc("/do", s.Do) + port := ":8081" + fmt.Printf("Server starting on port %s\n", port) + log.Fatal(http.ListenAndServe(port, nil)) +} + +func setKey(ctx context.Context, client rueidis.Client, key, value string) error { + cmd := client.B().Set().Key(key).Value(value).Build() + return client.Do(ctx, cmd).Error() +} + +func getKey(ctx context.Context, client rueidis.Client, key string) (string, error) { + cmd := client.B().Get().Key(key).Build() + result := client.Do(ctx, cmd) + if result.Error() != nil { + return "", result.Error() + } + return result.ToString() +} diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index 608c44886..a51e1ad45 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -1,4 +1,1083 @@ [ + { + "module": "github.com/redis/rueidis", + "packages": [ + { + "package": "github.com/redis/rueidis", + "structs": [ + { + "struct": "RedisResult", + "fields": [ + { + "field": "err", + "offsets": [ + { + "offset": null, + "versions": [ + "0.0.1", + "0.0.2", + "0.0.3", + "0.0.4", + "0.0.5", + "0.0.6", + "0.0.7", + "0.0.8", + "0.0.9", + "0.0.10", + "0.0.11", + "0.0.12", + "0.0.13", + "0.0.14", + "0.0.15", + "0.0.16", + "0.0.17", + "0.0.18", + "0.0.19", + "0.0.20", + "0.0.21", + "0.0.22", + "0.0.23", + "0.0.24", + "0.0.25", + "0.0.26", + "0.0.27", + "0.0.28", + "0.0.29", + "0.0.30", + "0.0.31", + "0.0.32", + "0.0.33", + "0.0.34", + "0.0.35", + "0.0.36", + "0.0.37", + "0.0.38", + "0.0.39", + "0.0.40", + "0.0.41", + "0.0.42", + "0.0.43", + "0.0.44", + "0.0.45", + "0.0.46", + "0.0.47", + "0.0.48", + "0.0.49", + "0.0.50", + "0.0.51", + "0.0.52", + "0.0.53", + "0.0.54", + "0.0.55", + "0.0.56", + "0.0.57", + "0.0.58", + "0.0.59", + "0.0.60", + "0.0.61", + "0.0.62", + "0.0.63", + "0.0.64", + "0.0.65", + "0.0.66", + "0.0.67", + "0.0.68", + "0.0.69", + "0.0.70", + "0.0.71", + "0.0.72", + "0.0.73", + "0.0.74", + "0.0.75", + "0.0.76", + "0.0.77", + "0.0.78", + "0.0.79", + "0.0.80", + "0.0.81", + "0.0.82", + "0.0.83", + "0.0.84", + "0.0.85", + "0.0.86", + "0.0.87", + "0.0.88", + "0.0.89", + "0.0.90", + "0.0.91", + "0.0.92", + "0.0.93", + "0.0.94", + "0.0.95", + "0.0.96", + "0.0.97", + "0.0.98", + "0.0.99-go1.18", + "0.0.99", + "0.0.100-go1.18", + "0.0.100", + "1.0.0-go1.18", + "1.0.0", + "1.0.1-go1.18", + "1.0.1", + "1.0.2-go1.18", + "1.0.2", + "1.0.3-go1.18", + "1.0.3", + "1.0.4-go1.18", + "1.0.4", + "1.0.5-go1.18", + "1.0.5", + "1.0.6-go1.18", + "1.0.6-go1.19", + "1.0.6", + "1.0.7-go1.18", + "1.0.7-go1.19", + "1.0.7", + "1.0.8-go1.18", + "1.0.8-go1.19", + "1.0.8", + "1.0.9-go1.18", + "1.0.9-go1.19", + "1.0.9" + ] + }, + { + "offset": 0, + "versions": [ + "1.0.10-go1.18", + "1.0.10-go1.19", + "1.0.10", + "1.0.11-go1.18", + "1.0.11-go1.19", + "1.0.11", + "1.0.12-go1.18", + "1.0.12-go1.19", + "1.0.12", + "1.0.13-go1.18", + "1.0.13-go1.19", + "1.0.13", + "1.0.14-go1.18", + "1.0.14-go1.19", + "1.0.14", + "1.0.15-go1.18", + "1.0.15-go1.19", + "1.0.15", + "1.0.16-go1.18", + "1.0.16-go1.19", + "1.0.16", + "1.0.17-go1.18", + "1.0.17-go1.19", + "1.0.17", + "1.0.18-go1.18", + "1.0.18-go1.19", + "1.0.18", + "1.0.19-go1.18", + "1.0.19-go1.19", + "1.0.19", + "1.0.20-go1.18", + "1.0.20-go1.19", + "1.0.20-pre.1", + "1.0.20-pre.2", + "1.0.20-pre.3", + "1.0.20-pre.4", + "1.0.20-pre.5", + "1.0.20", + "1.0.21-go1.18", + "1.0.21-go1.19", + "1.0.21", + "1.0.22-go1.18", + "1.0.22-go1.19", + "1.0.22-go119", + "1.0.22", + "1.0.23-go1.18", + "1.0.23-go1.19", + "1.0.23", + "1.0.24-go1.18", + "1.0.24-go1.19", + "1.0.24", + "1.0.25-go1.18", + "1.0.25-go1.19", + "1.0.25", + "1.0.26-debug438", + "1.0.26-go1.18", + "1.0.26-go1.19", + "1.0.26", + "1.0.27-go1.18", + "1.0.27-go1.19", + "1.0.27", + "1.0.28-pre", + "1.0.28-pre2", + "1.0.28-pre3", + "1.0.28-pre4", + "1.0.28-pre5", + "1.0.28", + "1.0.29", + "1.0.30", + "1.0.31-cap", + "1.0.31", + "1.0.32", + "1.0.33", + "1.0.34", + "1.0.35-dev1", + "1.0.35", + "1.0.36", + "1.0.37", + "1.0.38", + "1.0.39", + "1.0.40-alpha", + "1.0.40", + "1.0.41", + "1.0.42-alpha", + "1.0.42-alpha.2", + "1.0.42", + "1.0.43", + "1.0.44-alpha.1", + "1.0.44", + "1.0.45-alpha.1", + "1.0.45-alpha.2", + "1.0.45-alpha.3", + "1.0.45", + "1.0.46-alpha.1", + "1.0.46-alpha.2", + "1.0.46", + "1.0.47-alpha.1", + "1.0.47-alpha.2", + "1.0.47", + "1.0.48-alpha.1", + "1.0.48", + "1.0.49-alpha.1", + "1.0.49-alpha.2", + "1.0.49-alpha.3", + "1.0.49", + "1.0.50-alpha.1", + "1.0.50-alpha.2", + "1.0.50-alpha.3", + "1.0.50-alpha.4", + "1.0.50-alpha.5", + "1.0.50-alpha.6", + "1.0.50", + "1.0.51-alpha.1", + "1.0.51-debug.1", + "1.0.51", + "1.0.52-alpha.1", + "1.0.52-alpha.2", + "1.0.52-alpha.3", + "1.0.52", + "1.0.53-alpha.1" + ] + } + ] + } + ] + }, + { + "struct": "pipe", + "fields": [ + { + "field": "conn", + "offsets": [ + { + "offset": null, + "versions": [ + "0.0.1", + "0.0.2", + "0.0.3", + "0.0.4", + "0.0.5", + "0.0.6", + "0.0.7", + "0.0.8", + "0.0.9", + "0.0.10", + "0.0.11", + "0.0.12", + "0.0.13", + "0.0.14", + "0.0.15", + "0.0.16", + "0.0.17", + "0.0.18", + "0.0.19", + "0.0.20", + "0.0.21", + "0.0.22", + "0.0.23", + "0.0.24", + "0.0.25", + "0.0.26", + "0.0.27", + "0.0.28", + "0.0.29", + "0.0.30", + "0.0.31", + "0.0.32", + "0.0.33", + "0.0.34", + "0.0.35", + "0.0.36", + "0.0.37", + "0.0.38", + "0.0.39", + "0.0.40", + "0.0.41", + "0.0.42", + "0.0.43", + "0.0.44", + "0.0.45", + "0.0.46", + "0.0.47", + "0.0.48", + "0.0.49", + "0.0.50", + "0.0.51", + "0.0.52", + "0.0.53", + "0.0.54", + "0.0.55", + "0.0.56", + "0.0.57", + "0.0.58", + "0.0.59", + "0.0.60", + "0.0.61", + "0.0.62", + "0.0.63", + "0.0.64", + "0.0.65", + "0.0.66", + "0.0.67", + "0.0.68", + "0.0.69", + "0.0.70", + "0.0.71", + "0.0.72", + "0.0.73", + "0.0.74", + "0.0.75", + "0.0.76", + "0.0.77", + "0.0.78", + "0.0.79", + "0.0.80", + "0.0.81", + "0.0.82", + "0.0.83", + "0.0.84", + "0.0.85", + "0.0.86", + "0.0.87", + "0.0.88", + "0.0.89", + "0.0.90", + "0.0.91", + "0.0.92", + "0.0.93", + "0.0.94", + "0.0.95", + "0.0.96", + "0.0.97", + "0.0.98", + "0.0.99-go1.18", + "0.0.99", + "0.0.100-go1.18", + "0.0.100", + "1.0.0-go1.18", + "1.0.0", + "1.0.1-go1.18", + "1.0.1", + "1.0.2-go1.18", + "1.0.2", + "1.0.3-go1.18", + "1.0.3", + "1.0.4-go1.18", + "1.0.4", + "1.0.5-go1.18", + "1.0.5", + "1.0.6-go1.18", + "1.0.6-go1.19", + "1.0.6", + "1.0.7-go1.18", + "1.0.7-go1.19", + "1.0.7", + "1.0.8-go1.18", + "1.0.8-go1.19", + "1.0.8", + "1.0.9-go1.18", + "1.0.9-go1.19", + "1.0.9", + "1.0.10-go1.18", + "1.0.10-go1.19", + "1.0.10", + "1.0.11-go1.18", + "1.0.11-go1.19", + "1.0.11", + "1.0.12-go1.18", + "1.0.12-go1.19", + "1.0.12", + "1.0.13-go1.18", + "1.0.13-go1.19", + "1.0.13", + "1.0.14-go1.18", + "1.0.14-go1.19", + "1.0.14", + "1.0.15-go1.18", + "1.0.15-go1.19", + "1.0.15", + "1.0.16-go1.18", + "1.0.16-go1.19", + "1.0.16", + "1.0.17-go1.18", + "1.0.17-go1.19", + "1.0.17", + "1.0.18-go1.18", + "1.0.18-go1.19", + "1.0.18", + "1.0.19-go1.18", + "1.0.19-go1.19", + "1.0.19", + "1.0.20-go1.18", + "1.0.20-go1.19", + "1.0.20-pre.1", + "1.0.20-pre.2", + "1.0.20-pre.3", + "1.0.20-pre.4", + "1.0.20-pre.5", + "1.0.20", + "1.0.21-go1.18", + "1.0.21-go1.19", + "1.0.21", + "1.0.22-go1.18", + "1.0.22-go1.19", + "1.0.22-go119", + "1.0.22", + "1.0.23-go1.18", + "1.0.23-go1.19", + "1.0.23", + "1.0.24-go1.18", + "1.0.24-go1.19", + "1.0.24", + "1.0.25-go1.18", + "1.0.25-go1.19", + "1.0.25", + "1.0.26-debug438", + "1.0.26-go1.18", + "1.0.26-go1.19", + "1.0.26", + "1.0.27-go1.18", + "1.0.27-go1.19", + "1.0.27", + "1.0.28-pre", + "1.0.28-pre2", + "1.0.28-pre3", + "1.0.28-pre4", + "1.0.28-pre5", + "1.0.28" + ] + }, + { + "offset": 0, + "versions": [ + "1.0.29", + "1.0.30", + "1.0.31-cap", + "1.0.31", + "1.0.32", + "1.0.33", + "1.0.34", + "1.0.35-dev1", + "1.0.35", + "1.0.36", + "1.0.37", + "1.0.38", + "1.0.39", + "1.0.40-alpha", + "1.0.40", + "1.0.41", + "1.0.42-alpha", + "1.0.42-alpha.2", + "1.0.42", + "1.0.43", + "1.0.44-alpha.1", + "1.0.44", + "1.0.45-alpha.1", + "1.0.45-alpha.2", + "1.0.45-alpha.3", + "1.0.45", + "1.0.46-alpha.1", + "1.0.46-alpha.2", + "1.0.46", + "1.0.47-alpha.1", + "1.0.47-alpha.2", + "1.0.47", + "1.0.48-alpha.1", + "1.0.48", + "1.0.49-alpha.1", + "1.0.49-alpha.2", + "1.0.49-alpha.3", + "1.0.49", + "1.0.50-alpha.1", + "1.0.50-alpha.2", + "1.0.50-alpha.3", + "1.0.50-alpha.4", + "1.0.50-alpha.5", + "1.0.50-alpha.6", + "1.0.50", + "1.0.51-alpha.1", + "1.0.51-debug.1", + "1.0.51", + "1.0.52-alpha.1", + "1.0.52-alpha.2", + "1.0.52-alpha.3", + "1.0.52", + "1.0.53-alpha.1" + ] + } + ] + } + ] + } + ] + }, + { + "package": "github.com/redis/rueidis/internal/cmds", + "structs": [ + { + "struct": "CommandSlice", + "fields": [ + { + "field": "s", + "offsets": [ + { + "offset": null, + "versions": [ + "0.0.1", + "0.0.2", + "0.0.3", + "0.0.4", + "0.0.5", + "0.0.6", + "0.0.7", + "0.0.8", + "0.0.9", + "0.0.10", + "0.0.11", + "0.0.12", + "0.0.13", + "0.0.14", + "0.0.15", + "0.0.16", + "0.0.17", + "0.0.18", + "0.0.19", + "0.0.20", + "0.0.21", + "0.0.22", + "0.0.23", + "0.0.24", + "0.0.25", + "0.0.26", + "0.0.27", + "0.0.28", + "0.0.29", + "0.0.30", + "0.0.31", + "0.0.32", + "0.0.33", + "0.0.34", + "0.0.35", + "0.0.36", + "0.0.37", + "0.0.38", + "0.0.39", + "0.0.40", + "0.0.41", + "0.0.42", + "0.0.43", + "0.0.44", + "0.0.45", + "0.0.46", + "0.0.47", + "0.0.48", + "0.0.49", + "0.0.50", + "0.0.51", + "0.0.52", + "0.0.53", + "0.0.54", + "0.0.55", + "0.0.56", + "0.0.57", + "0.0.58", + "0.0.59", + "0.0.60", + "0.0.61", + "0.0.62", + "0.0.63", + "0.0.64", + "0.0.65", + "0.0.66", + "0.0.67", + "0.0.68", + "0.0.69", + "0.0.70", + "0.0.71", + "0.0.72", + "0.0.73", + "0.0.74", + "0.0.75", + "0.0.76", + "0.0.77", + "0.0.78", + "0.0.79", + "0.0.80", + "0.0.81", + "0.0.82", + "0.0.83", + "0.0.84", + "0.0.85", + "0.0.86", + "0.0.87", + "0.0.88", + "0.0.89", + "0.0.90", + "0.0.91", + "0.0.92", + "0.0.93", + "0.0.94", + "0.0.95", + "0.0.96", + "0.0.97", + "0.0.98", + "0.0.99-go1.18", + "0.0.99", + "0.0.100-go1.18", + "0.0.100", + "1.0.5", + "1.0.6-go1.18", + "1.0.6-go1.19", + "1.0.6", + "1.0.7-go1.18", + "1.0.7-go1.19", + "1.0.7", + "1.0.8-go1.18", + "1.0.8-go1.19", + "1.0.8", + "1.0.9-go1.18" + ] + }, + { + "offset": 0, + "versions": [ + "1.0.0-go1.18", + "1.0.0", + "1.0.1-go1.18", + "1.0.1", + "1.0.2-go1.18", + "1.0.2", + "1.0.3-go1.18", + "1.0.3", + "1.0.4-go1.18", + "1.0.4", + "1.0.5-go1.18", + "1.0.9-go1.19", + "1.0.9", + "1.0.10-go1.18", + "1.0.10-go1.19", + "1.0.10", + "1.0.11-go1.18", + "1.0.11-go1.19", + "1.0.11", + "1.0.12-go1.18", + "1.0.12-go1.19", + "1.0.12", + "1.0.13-go1.18", + "1.0.13-go1.19", + "1.0.13", + "1.0.14-go1.18", + "1.0.14-go1.19", + "1.0.14", + "1.0.15-go1.18", + "1.0.15-go1.19", + "1.0.15", + "1.0.16-go1.18", + "1.0.16-go1.19", + "1.0.16", + "1.0.17-go1.18", + "1.0.17-go1.19", + "1.0.17", + "1.0.18-go1.18", + "1.0.18-go1.19", + "1.0.18", + "1.0.19-go1.18", + "1.0.19-go1.19", + "1.0.19", + "1.0.20-go1.18", + "1.0.20-go1.19", + "1.0.20-pre.1", + "1.0.20-pre.2", + "1.0.20-pre.3", + "1.0.20-pre.4", + "1.0.20-pre.5", + "1.0.20", + "1.0.21-go1.18", + "1.0.21-go1.19", + "1.0.21", + "1.0.22-go1.18", + "1.0.22-go1.19", + "1.0.22-go119", + "1.0.22", + "1.0.23-go1.18", + "1.0.23-go1.19", + "1.0.23", + "1.0.24-go1.18", + "1.0.24-go1.19", + "1.0.24", + "1.0.25-go1.18", + "1.0.25-go1.19", + "1.0.25", + "1.0.26-debug438", + "1.0.26-go1.18", + "1.0.26-go1.19", + "1.0.26", + "1.0.27-go1.18", + "1.0.27-go1.19", + "1.0.27", + "1.0.28-pre", + "1.0.28-pre2", + "1.0.28-pre3", + "1.0.28-pre4", + "1.0.28-pre5", + "1.0.28", + "1.0.29", + "1.0.30", + "1.0.31-cap", + "1.0.31", + "1.0.32", + "1.0.33", + "1.0.34", + "1.0.35-dev1", + "1.0.35", + "1.0.36", + "1.0.37", + "1.0.38", + "1.0.39", + "1.0.40-alpha", + "1.0.40", + "1.0.41", + "1.0.42-alpha", + "1.0.42-alpha.2", + "1.0.42", + "1.0.43", + "1.0.44-alpha.1", + "1.0.44", + "1.0.45-alpha.1", + "1.0.45-alpha.2", + "1.0.45-alpha.3", + "1.0.45", + "1.0.46-alpha.1", + "1.0.46-alpha.2", + "1.0.46", + "1.0.47-alpha.1", + "1.0.47-alpha.2", + "1.0.47", + "1.0.48-alpha.1", + "1.0.48", + "1.0.49-alpha.1", + "1.0.49-alpha.2", + "1.0.49-alpha.3", + "1.0.49", + "1.0.50-alpha.1", + "1.0.50-alpha.2", + "1.0.50-alpha.3", + "1.0.50-alpha.4", + "1.0.50-alpha.5", + "1.0.50-alpha.6", + "1.0.50", + "1.0.51-alpha.1", + "1.0.51-debug.1", + "1.0.51", + "1.0.52-alpha.1", + "1.0.52-alpha.2", + "1.0.52-alpha.3", + "1.0.52", + "1.0.53-alpha.1" + ] + } + ] + } + ] + }, + { + "struct": "Completed", + "fields": [ + { + "field": "cs", + "offsets": [ + { + "offset": null, + "versions": [ + "0.0.1", + "0.0.2", + "0.0.3", + "0.0.4", + "0.0.5", + "0.0.6", + "0.0.7", + "0.0.8", + "0.0.9", + "0.0.10", + "0.0.11", + "0.0.12", + "0.0.13", + "0.0.14", + "0.0.15", + "0.0.16", + "0.0.17", + "0.0.18", + "0.0.19", + "0.0.20", + "0.0.21", + "0.0.22", + "0.0.23", + "0.0.24", + "0.0.25", + "0.0.26", + "0.0.27", + "0.0.28", + "0.0.29", + "0.0.30", + "0.0.31", + "0.0.32", + "0.0.33", + "0.0.34", + "0.0.35", + "0.0.36", + "0.0.37", + "0.0.38", + "0.0.39", + "0.0.40", + "0.0.41", + "0.0.42", + "0.0.43", + "0.0.44", + "0.0.45", + "0.0.46", + "0.0.47", + "0.0.48", + "0.0.49", + "0.0.50", + "0.0.51", + "0.0.52", + "0.0.53", + "0.0.54", + "0.0.55", + "0.0.56", + "0.0.57", + "0.0.58", + "0.0.59", + "0.0.60", + "0.0.61", + "0.0.62", + "0.0.63", + "0.0.64", + "0.0.65", + "0.0.66", + "0.0.67", + "0.0.68", + "0.0.69", + "0.0.70", + "0.0.71", + "0.0.72", + "0.0.73", + "0.0.74", + "0.0.75", + "0.0.76", + "0.0.77", + "0.0.78", + "0.0.79", + "0.0.80", + "0.0.81", + "0.0.82", + "0.0.83", + "0.0.84", + "0.0.85", + "0.0.86", + "0.0.87", + "0.0.88", + "0.0.89", + "0.0.90", + "0.0.91", + "0.0.92", + "0.0.93", + "0.0.94", + "0.0.95", + "0.0.96", + "0.0.97", + "0.0.98", + "0.0.99-go1.18", + "0.0.99", + "0.0.100-go1.18", + "0.0.100", + "1.0.5", + "1.0.6-go1.18", + "1.0.6-go1.19", + "1.0.6", + "1.0.7-go1.18", + "1.0.7-go1.19", + "1.0.7", + "1.0.8-go1.18", + "1.0.8-go1.19", + "1.0.8", + "1.0.9-go1.18" + ] + }, + { + "offset": 0, + "versions": [ + "1.0.0-go1.18", + "1.0.0", + "1.0.1-go1.18", + "1.0.1", + "1.0.2-go1.18", + "1.0.2", + "1.0.3-go1.18", + "1.0.3", + "1.0.4-go1.18", + "1.0.4", + "1.0.5-go1.18", + "1.0.9-go1.19", + "1.0.9", + "1.0.10-go1.18", + "1.0.10-go1.19", + "1.0.10", + "1.0.11-go1.18", + "1.0.11-go1.19", + "1.0.11", + "1.0.12-go1.18", + "1.0.12-go1.19", + "1.0.12", + "1.0.13-go1.18", + "1.0.13-go1.19", + "1.0.13", + "1.0.14-go1.18", + "1.0.14-go1.19", + "1.0.14", + "1.0.15-go1.18", + "1.0.15-go1.19", + "1.0.15", + "1.0.16-go1.18", + "1.0.16-go1.19", + "1.0.16", + "1.0.17-go1.18", + "1.0.17-go1.19", + "1.0.17", + "1.0.18-go1.18", + "1.0.18-go1.19", + "1.0.18", + "1.0.19-go1.18", + "1.0.19-go1.19", + "1.0.19", + "1.0.20-go1.18", + "1.0.20-go1.19", + "1.0.20-pre.1", + "1.0.20-pre.2", + "1.0.20-pre.3", + "1.0.20-pre.4", + "1.0.20-pre.5", + "1.0.20", + "1.0.21-go1.18", + "1.0.21-go1.19", + "1.0.21", + "1.0.22-go1.18", + "1.0.22-go1.19", + "1.0.22-go119", + "1.0.22", + "1.0.23-go1.18", + "1.0.23-go1.19", + "1.0.23", + "1.0.24-go1.18", + "1.0.24-go1.19", + "1.0.24", + "1.0.25-go1.18", + "1.0.25-go1.19", + "1.0.25", + "1.0.26-debug438", + "1.0.26-go1.18", + "1.0.26-go1.19", + "1.0.26", + "1.0.27-go1.18", + "1.0.27-go1.19", + "1.0.27", + "1.0.28-pre", + "1.0.28-pre2", + "1.0.28-pre3", + "1.0.28-pre4", + "1.0.28-pre5", + "1.0.28", + "1.0.29", + "1.0.30", + "1.0.31-cap", + "1.0.31", + "1.0.32", + "1.0.33", + "1.0.34", + "1.0.35-dev1", + "1.0.35", + "1.0.36", + "1.0.37", + "1.0.38", + "1.0.39", + "1.0.40-alpha", + "1.0.40", + "1.0.41", + "1.0.42-alpha", + "1.0.42-alpha.2", + "1.0.42", + "1.0.43", + "1.0.44-alpha.1", + "1.0.44", + "1.0.45-alpha.1", + "1.0.45-alpha.2", + "1.0.45-alpha.3", + "1.0.45", + "1.0.46-alpha.1", + "1.0.46-alpha.2", + "1.0.46", + "1.0.47-alpha.1", + "1.0.47-alpha.2", + "1.0.47", + "1.0.48-alpha.1", + "1.0.48", + "1.0.49-alpha.1", + "1.0.49-alpha.2", + "1.0.49-alpha.3", + "1.0.49", + "1.0.50-alpha.1", + "1.0.50-alpha.2", + "1.0.50-alpha.3", + "1.0.50-alpha.4", + "1.0.50-alpha.5", + "1.0.50-alpha.6", + "1.0.50", + "1.0.51-alpha.1", + "1.0.51-debug.1", + "1.0.51", + "1.0.52-alpha.1", + "1.0.52-alpha.2", + "1.0.52-alpha.3", + "1.0.52", + "1.0.53-alpha.1" + ] + } + ] + } + ] + } + ] + } + ] + }, { "module": "github.com/segmentio/kafka-go", "packages": [ @@ -5516,6 +6595,549 @@ ] } ] + }, + { + "struct": "TCPConn", + "fields": [ + { + "field": "conn", + "offsets": [ + { + "offset": 0, + "versions": [ + "1.12.0", + "1.12.1", + "1.12.2", + "1.12.3", + "1.12.4", + "1.12.5", + "1.12.6", + "1.12.7", + "1.12.8", + "1.12.9", + "1.12.10", + "1.12.11", + "1.12.12", + "1.12.13", + "1.12.14", + "1.12.15", + "1.12.16", + "1.12.17", + "1.13.0", + "1.13.1", + "1.13.2", + "1.13.3", + "1.13.4", + "1.13.5", + "1.13.6", + "1.13.7", + "1.13.8", + "1.13.9", + "1.13.10", + "1.13.11", + "1.13.12", + "1.13.13", + "1.13.14", + "1.13.15", + "1.14.0", + "1.14.1", + "1.14.2", + "1.14.3", + "1.14.4", + "1.14.5", + "1.14.6", + "1.14.7", + "1.14.8", + "1.14.9", + "1.14.10", + "1.14.11", + "1.14.12", + "1.14.13", + "1.14.14", + "1.14.15", + "1.15.0", + "1.15.1", + "1.15.2", + "1.15.3", + "1.15.4", + "1.15.5", + "1.15.6", + "1.15.7", + "1.15.8", + "1.15.9", + "1.15.10", + "1.15.11", + "1.15.12", + "1.15.13", + "1.15.14", + "1.15.15", + "1.16.0", + "1.16.1", + "1.16.2", + "1.16.3", + "1.16.4", + "1.16.5", + "1.16.6", + "1.16.7", + "1.16.8", + "1.16.9", + "1.16.10", + "1.16.11", + "1.16.12", + "1.16.13", + "1.16.14", + "1.16.15", + "1.17.0", + "1.17.1", + "1.17.2", + "1.17.3", + "1.17.4", + "1.17.5", + "1.17.6", + "1.17.7", + "1.17.8", + "1.17.9", + "1.17.10", + "1.17.11", + "1.17.12", + "1.17.13", + "1.18.0", + "1.18.1", + "1.18.2", + "1.18.3", + "1.18.4", + "1.18.5", + "1.18.6", + "1.18.7", + "1.18.8", + "1.18.9", + "1.18.10", + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9", + "1.21.10", + "1.21.11", + "1.21.12", + "1.21.13", + "1.22.0", + "1.22.1", + "1.22.2", + "1.22.3", + "1.22.4", + "1.22.5", + "1.22.6", + "1.22.7", + "1.22.8", + "1.22.9", + "1.22.10", + "1.23.0", + "1.23.1", + "1.23.2", + "1.23.3", + "1.23.4" + ] + } + ] + } + ] + }, + { + "struct": "conn", + "fields": [ + { + "field": "fd", + "offsets": [ + { + "offset": 0, + "versions": [ + "1.12.0", + "1.12.1", + "1.12.2", + "1.12.3", + "1.12.4", + "1.12.5", + "1.12.6", + "1.12.7", + "1.12.8", + "1.12.9", + "1.12.10", + "1.12.11", + "1.12.12", + "1.12.13", + "1.12.14", + "1.12.15", + "1.12.16", + "1.12.17", + "1.13.0", + "1.13.1", + "1.13.2", + "1.13.3", + "1.13.4", + "1.13.5", + "1.13.6", + "1.13.7", + "1.13.8", + "1.13.9", + "1.13.10", + "1.13.11", + "1.13.12", + "1.13.13", + "1.13.14", + "1.13.15", + "1.14.0", + "1.14.1", + "1.14.2", + "1.14.3", + "1.14.4", + "1.14.5", + "1.14.6", + "1.14.7", + "1.14.8", + "1.14.9", + "1.14.10", + "1.14.11", + "1.14.12", + "1.14.13", + "1.14.14", + "1.14.15", + "1.15.0", + "1.15.1", + "1.15.2", + "1.15.3", + "1.15.4", + "1.15.5", + "1.15.6", + "1.15.7", + "1.15.8", + "1.15.9", + "1.15.10", + "1.15.11", + "1.15.12", + "1.15.13", + "1.15.14", + "1.15.15", + "1.16.0", + "1.16.1", + "1.16.2", + "1.16.3", + "1.16.4", + "1.16.5", + "1.16.6", + "1.16.7", + "1.16.8", + "1.16.9", + "1.16.10", + "1.16.11", + "1.16.12", + "1.16.13", + "1.16.14", + "1.16.15", + "1.17.0", + "1.17.1", + "1.17.2", + "1.17.3", + "1.17.4", + "1.17.5", + "1.17.6", + "1.17.7", + "1.17.8", + "1.17.9", + "1.17.10", + "1.17.11", + "1.17.12", + "1.17.13", + "1.18.0", + "1.18.1", + "1.18.2", + "1.18.3", + "1.18.4", + "1.18.5", + "1.18.6", + "1.18.7", + "1.18.8", + "1.18.9", + "1.18.10", + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9", + "1.21.10", + "1.21.11", + "1.21.12", + "1.21.13", + "1.22.0", + "1.22.1", + "1.22.2", + "1.22.3", + "1.22.4", + "1.22.5", + "1.22.6", + "1.22.7", + "1.22.8", + "1.22.9", + "1.22.10", + "1.23.0", + "1.23.1", + "1.23.2", + "1.23.3", + "1.23.4" + ] + } + ] + } + ] + }, + { + "struct": "netFD", + "fields": [ + { + "field": "raddr", + "offsets": [ + { + "offset": 112, + "versions": [ + "1.12.0", + "1.12.1", + "1.12.2", + "1.12.3", + "1.12.4", + "1.12.5", + "1.12.6", + "1.12.7", + "1.12.8", + "1.12.9", + "1.12.10", + "1.12.11", + "1.12.12", + "1.12.13", + "1.12.14", + "1.12.15", + "1.12.16", + "1.12.17", + "1.13.0", + "1.13.1", + "1.13.2", + "1.13.3", + "1.13.4", + "1.13.5", + "1.13.6", + "1.13.7", + "1.13.8", + "1.13.9", + "1.13.10", + "1.13.11", + "1.13.12", + "1.13.13", + "1.13.14", + "1.13.15", + "1.14.0", + "1.14.1", + "1.14.2", + "1.14.3", + "1.14.4", + "1.14.5", + "1.14.6", + "1.14.7", + "1.14.8", + "1.14.9", + "1.14.10", + "1.14.11", + "1.14.12", + "1.14.13", + "1.14.14", + "1.14.15", + "1.15.0", + "1.15.1", + "1.15.2", + "1.15.3", + "1.15.4", + "1.15.5", + "1.15.6", + "1.15.7", + "1.15.8", + "1.15.9", + "1.15.10", + "1.15.11", + "1.15.12", + "1.15.13", + "1.15.14", + "1.15.15", + "1.16.0", + "1.16.1", + "1.16.2", + "1.16.3", + "1.16.4", + "1.16.5", + "1.16.6", + "1.16.7", + "1.16.8", + "1.16.9", + "1.16.10", + "1.16.11", + "1.16.12", + "1.16.13", + "1.16.14", + "1.16.15", + "1.17.0", + "1.17.1", + "1.17.2", + "1.17.3", + "1.17.4", + "1.17.5", + "1.17.6", + "1.17.7", + "1.17.8", + "1.17.9", + "1.17.10", + "1.17.11", + "1.17.12", + "1.17.13", + "1.18.0", + "1.18.1", + "1.18.2", + "1.18.3", + "1.18.4", + "1.18.5", + "1.18.6", + "1.18.7", + "1.18.8", + "1.18.9", + "1.18.10", + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9", + "1.21.10", + "1.21.11", + "1.21.12", + "1.21.13", + "1.22.0", + "1.22.1", + "1.22.2", + "1.22.3", + "1.22.4", + "1.22.5", + "1.22.6", + "1.22.7", + "1.22.8", + "1.22.9", + "1.22.10", + "1.23.0", + "1.23.1", + "1.23.2", + "1.23.3", + "1.23.4" + ] + } + ] + } + ] } ] }, diff --git a/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf/probe.bpf.c b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf/probe.bpf.c new file mode 100644 index 000000000..4674c6686 --- /dev/null +++ b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf/probe.bpf.c @@ -0,0 +1,143 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "arguments.h" +#include "trace/span_context.h" +#include "go_context.h" +#include "go_types.h" +#include "uprobe.h" +#include "trace/start_span.h" +#include "go_net.h" + +char __license[] SEC("license") = "Dual MIT/GPL"; + +#define MAX_CONCURRENT 56 // todo: tune +#define MAX_OPERATION_NAME_SIZE 20 + +typedef struct tcp_addr { + u8 ip[16]; + u64 port; +} tcp_addr_t; + +struct rueidis_completed_command_t { + BASE_SPAN_PROPERTIES + char operation_name[MAX_OPERATION_NAME_SIZE]; + net_addr_t local_addr; +}; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, void*); + __type(value, struct rueidis_completed_command_t); + __uint(max_entries, MAX_CONCURRENT); +} redis_completed_events SEC(".maps"); + +volatile const u64 pipe_conn_pos; +volatile const u64 tcp_conn_conn_pos; +volatile const u64 conn_fd_pos; +volatile const u64 fd_raddr_pos; +volatile const u64 tcp_addr_ip_pos; +volatile const u64 tcp_addr_port_pos; +volatile const u64 completed_cs_pos; +volatile const u64 cs_s_pos; +volatile const u64 result_error_pos; + +const u64 max_opration_length = MAX_OPERATION_NAME_SIZE; + +// This instrumentation attaches uprobe to the following function: +// func (m *pipe) Do(ctx context.Context, cmd Completed) (resp RedisResult) +SEC("uprobe/pipe_Do") +int uprobe_pipe_Do(struct pt_regs *ctx) { + int cmd_cs_ptr_pos = 4; // passed in $rdi + struct go_iface go_context = {0}; + get_Go_context(ctx, 2, 0, true, &go_context); + + void *key = get_consistent_key(ctx, go_context.data); + void *redisReq_ptr = bpf_map_lookup_elem(&redis_completed_events, &key); + if (redisReq_ptr != NULL) { + bpf_printk("uprobe/pipe_Do already tracked with the current context"); + return 0; + } + + struct rueidis_completed_command_t redisReq = {}; + redisReq.start_time = bpf_ktime_get_ns(); + + start_span_params_t start_span_params = { + .ctx = ctx, + .go_context = &go_context, + .psc = &redisReq.psc, + .sc = &redisReq.sc, + .get_parent_span_context_fn = NULL, + .get_parent_span_context_arg = NULL, + }; + start_span(&start_span_params); + + + // read network peer data. located at pipe.conn.conn.fd.raddr + void *pipe_ptr = get_argument(ctx, 1); + // todo: check pipe not having conn scenario for older version + + void *tcp_conn_ptr = 0; + bpf_probe_read_user(&tcp_conn_ptr, sizeof(tcp_conn_ptr), get_go_interface_instance(pipe_ptr + pipe_conn_pos)); + + + void *fd_ptr = 0; + bpf_probe_read_user(&fd_ptr, sizeof(fd_ptr), (void *)(tcp_conn_ptr + tcp_conn_conn_pos + conn_fd_pos)); + + void *tcp_addr_ptr = 0; + bpf_probe_read_user(&tcp_addr_ptr, sizeof(tcp_addr_ptr), get_go_interface_instance(fd_ptr + fd_raddr_pos)); + + get_tcp_net_addr_from_tcp_addr(ctx, &redisReq.local_addr, (void *)(tcp_addr_ptr)); + // port still has issues. its type conversion with golang controller though. + + // read redis command's operation from cmd.cs[0] + void *cs_ptr = get_argument(ctx, cmd_cs_ptr_pos); + if (cs_ptr == 0) { + goto done; + } + + struct go_slice cs = {0}; + bpf_probe_read(&cs, sizeof(cs), cs_ptr); + + if (!get_go_string_from_user_ptr(cs.array, &redisReq.operation_name, max_opration_length)) { + bpf_printk("uprobe/pipe_Do command from Completed.cs.s"); + } + + // todo: get full query text + + done: + + bpf_map_update_elem(&redis_completed_events, &key, &redisReq, 0); + start_tracking_span(go_context.data, &redisReq.sc); + + return 0; +} + + +// This instrumentation attaches uretprobe to the following function: +// func (m *pipe) Do(ctx context.Context, cmd Completed) (resp RedisResult) +SEC("uprobe/pipe_Do") +int uprobe_pipe_Do_Returns(struct pt_regs *ctx) { + u64 end_time = bpf_ktime_get_ns(); + + struct go_iface go_context = {0}; + get_Go_context(ctx, 3, 0, true, &go_context); + + void *key = get_consistent_key(ctx, go_context.data); + struct rueidis_completed_command_t *redisReq = bpf_map_lookup_elem(&redis_completed_events, &key); + + if (redisReq == NULL) { + bpf_printk("event is NULL in ret probe"); + return 0; + } + + // todo: check if error happened + + done: + redisReq->end_time = bpf_ktime_get_ns(); + output_span_event(ctx, redisReq, sizeof(*redisReq), &redisReq->sc); + stop_tracking_span(&redisReq->sc, &redisReq->psc); + + bpf_map_delete_elem(&redis_completed_events, &key); + return 0; +} diff --git a/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf_arm64_bpfel.go b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf_arm64_bpfel.go new file mode 100644 index 000000000..eb585174b --- /dev/null +++ b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf_arm64_bpfel.go @@ -0,0 +1,212 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build arm64 + +package rueidis + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfRueidisCompletedCommandT struct { + StartTime uint64 + EndTime uint64 + Sc bpfSpanContext + Psc bpfSpanContext + OperationName [20]int8 + LocalAddr struct { + Ip [16]uint8 + Port uint32 + } +} + +type bpfSliceArrayBuff struct{ Buff [1024]uint8 } + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs + bpfVariableSpecs +} + +// bpfProgramSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobePipeDo *ebpf.ProgramSpec `ebpf:"uprobe_pipe_Do"` + UprobePipeDoReturns *ebpf.ProgramSpec `ebpf:"uprobe_pipe_Do_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + Events *ebpf.MapSpec `ebpf:"events"` + GoContextToSc *ebpf.MapSpec `ebpf:"go_context_to_sc"` + ProbeActiveSamplerMap *ebpf.MapSpec `ebpf:"probe_active_sampler_map"` + RedisCompletedEvents *ebpf.MapSpec `ebpf:"redis_completed_events"` + SamplersConfigMap *ebpf.MapSpec `ebpf:"samplers_config_map"` + SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` + TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` +} + +// bpfVariableSpecs contains global variables before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfVariableSpecs struct { + TCPAddrIP_offset *ebpf.VariableSpec `ebpf:"TCPAddr_IP_offset"` + TCPAddrPortOffset *ebpf.VariableSpec `ebpf:"TCPAddr_Port_offset"` + CompletedCsPos *ebpf.VariableSpec `ebpf:"completed_cs_pos"` + ConnFdPos *ebpf.VariableSpec `ebpf:"conn_fd_pos"` + CsS_pos *ebpf.VariableSpec `ebpf:"cs_s_pos"` + EndAddr *ebpf.VariableSpec `ebpf:"end_addr"` + FdRaddrPos *ebpf.VariableSpec `ebpf:"fd_raddr_pos"` + Hex *ebpf.VariableSpec `ebpf:"hex"` + IsRegistersAbi *ebpf.VariableSpec `ebpf:"is_registers_abi"` + MaxOprationLength *ebpf.VariableSpec `ebpf:"max_opration_length"` + PipeConnPos *ebpf.VariableSpec `ebpf:"pipe_conn_pos"` + ResultErrorPos *ebpf.VariableSpec `ebpf:"result_error_pos"` + StartAddr *ebpf.VariableSpec `ebpf:"start_addr"` + TcpAddrIpPos *ebpf.VariableSpec `ebpf:"tcp_addr_ip_pos"` + TcpAddrPortPos *ebpf.VariableSpec `ebpf:"tcp_addr_port_pos"` + TcpConnConnPos *ebpf.VariableSpec `ebpf:"tcp_conn_conn_pos"` + TotalCpus *ebpf.VariableSpec `ebpf:"total_cpus"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps + bpfVariables +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + AllocMap *ebpf.Map `ebpf:"alloc_map"` + Events *ebpf.Map `ebpf:"events"` + GoContextToSc *ebpf.Map `ebpf:"go_context_to_sc"` + ProbeActiveSamplerMap *ebpf.Map `ebpf:"probe_active_sampler_map"` + RedisCompletedEvents *ebpf.Map `ebpf:"redis_completed_events"` + SamplersConfigMap *ebpf.Map `ebpf:"samplers_config_map"` + SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.AllocMap, + m.Events, + m.GoContextToSc, + m.ProbeActiveSamplerMap, + m.RedisCompletedEvents, + m.SamplersConfigMap, + m.SliceArrayBuffMap, + m.TrackedSpansBySc, + ) +} + +// bpfVariables contains all global variables after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfVariables struct { + TCPAddrIP_offset *ebpf.Variable `ebpf:"TCPAddr_IP_offset"` + TCPAddrPortOffset *ebpf.Variable `ebpf:"TCPAddr_Port_offset"` + CompletedCsPos *ebpf.Variable `ebpf:"completed_cs_pos"` + ConnFdPos *ebpf.Variable `ebpf:"conn_fd_pos"` + CsS_pos *ebpf.Variable `ebpf:"cs_s_pos"` + EndAddr *ebpf.Variable `ebpf:"end_addr"` + FdRaddrPos *ebpf.Variable `ebpf:"fd_raddr_pos"` + Hex *ebpf.Variable `ebpf:"hex"` + IsRegistersAbi *ebpf.Variable `ebpf:"is_registers_abi"` + MaxOprationLength *ebpf.Variable `ebpf:"max_opration_length"` + PipeConnPos *ebpf.Variable `ebpf:"pipe_conn_pos"` + ResultErrorPos *ebpf.Variable `ebpf:"result_error_pos"` + StartAddr *ebpf.Variable `ebpf:"start_addr"` + TcpAddrIpPos *ebpf.Variable `ebpf:"tcp_addr_ip_pos"` + TcpAddrPortPos *ebpf.Variable `ebpf:"tcp_addr_port_pos"` + TcpConnConnPos *ebpf.Variable `ebpf:"tcp_conn_conn_pos"` + TotalCpus *ebpf.Variable `ebpf:"total_cpus"` +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobePipeDo *ebpf.Program `ebpf:"uprobe_pipe_Do"` + UprobePipeDoReturns *ebpf.Program `ebpf:"uprobe_pipe_Do_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobePipeDo, + p.UprobePipeDoReturns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_arm64_bpfel.o +var _BpfBytes []byte diff --git a/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf_x86_bpfel.go b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf_x86_bpfel.go new file mode 100644 index 000000000..f728f142e --- /dev/null +++ b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/bpf_x86_bpfel.go @@ -0,0 +1,212 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build 386 || amd64 + +package rueidis + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfRueidisCompletedCommandT struct { + StartTime uint64 + EndTime uint64 + Sc bpfSpanContext + Psc bpfSpanContext + OperationName [20]int8 + LocalAddr struct { + Ip [16]uint8 + Port uint32 + } +} + +type bpfSliceArrayBuff struct{ Buff [1024]uint8 } + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 + TraceFlags uint8 + Padding [7]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs + bpfVariableSpecs +} + +// bpfProgramSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobePipeDo *ebpf.ProgramSpec `ebpf:"uprobe_pipe_Do"` + UprobePipeDoReturns *ebpf.ProgramSpec `ebpf:"uprobe_pipe_Do_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + Events *ebpf.MapSpec `ebpf:"events"` + GoContextToSc *ebpf.MapSpec `ebpf:"go_context_to_sc"` + ProbeActiveSamplerMap *ebpf.MapSpec `ebpf:"probe_active_sampler_map"` + RedisCompletedEvents *ebpf.MapSpec `ebpf:"redis_completed_events"` + SamplersConfigMap *ebpf.MapSpec `ebpf:"samplers_config_map"` + SliceArrayBuffMap *ebpf.MapSpec `ebpf:"slice_array_buff_map"` + TrackedSpansBySc *ebpf.MapSpec `ebpf:"tracked_spans_by_sc"` +} + +// bpfVariableSpecs contains global variables before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfVariableSpecs struct { + TCPAddrIP_offset *ebpf.VariableSpec `ebpf:"TCPAddr_IP_offset"` + TCPAddrPortOffset *ebpf.VariableSpec `ebpf:"TCPAddr_Port_offset"` + CompletedCsPos *ebpf.VariableSpec `ebpf:"completed_cs_pos"` + ConnFdPos *ebpf.VariableSpec `ebpf:"conn_fd_pos"` + CsS_pos *ebpf.VariableSpec `ebpf:"cs_s_pos"` + EndAddr *ebpf.VariableSpec `ebpf:"end_addr"` + FdRaddrPos *ebpf.VariableSpec `ebpf:"fd_raddr_pos"` + Hex *ebpf.VariableSpec `ebpf:"hex"` + IsRegistersAbi *ebpf.VariableSpec `ebpf:"is_registers_abi"` + MaxOprationLength *ebpf.VariableSpec `ebpf:"max_opration_length"` + PipeConnPos *ebpf.VariableSpec `ebpf:"pipe_conn_pos"` + ResultErrorPos *ebpf.VariableSpec `ebpf:"result_error_pos"` + StartAddr *ebpf.VariableSpec `ebpf:"start_addr"` + TcpAddrIpPos *ebpf.VariableSpec `ebpf:"tcp_addr_ip_pos"` + TcpAddrPortPos *ebpf.VariableSpec `ebpf:"tcp_addr_port_pos"` + TcpConnConnPos *ebpf.VariableSpec `ebpf:"tcp_conn_conn_pos"` + TotalCpus *ebpf.VariableSpec `ebpf:"total_cpus"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps + bpfVariables +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + AllocMap *ebpf.Map `ebpf:"alloc_map"` + Events *ebpf.Map `ebpf:"events"` + GoContextToSc *ebpf.Map `ebpf:"go_context_to_sc"` + ProbeActiveSamplerMap *ebpf.Map `ebpf:"probe_active_sampler_map"` + RedisCompletedEvents *ebpf.Map `ebpf:"redis_completed_events"` + SamplersConfigMap *ebpf.Map `ebpf:"samplers_config_map"` + SliceArrayBuffMap *ebpf.Map `ebpf:"slice_array_buff_map"` + TrackedSpansBySc *ebpf.Map `ebpf:"tracked_spans_by_sc"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.AllocMap, + m.Events, + m.GoContextToSc, + m.ProbeActiveSamplerMap, + m.RedisCompletedEvents, + m.SamplersConfigMap, + m.SliceArrayBuffMap, + m.TrackedSpansBySc, + ) +} + +// bpfVariables contains all global variables after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfVariables struct { + TCPAddrIP_offset *ebpf.Variable `ebpf:"TCPAddr_IP_offset"` + TCPAddrPortOffset *ebpf.Variable `ebpf:"TCPAddr_Port_offset"` + CompletedCsPos *ebpf.Variable `ebpf:"completed_cs_pos"` + ConnFdPos *ebpf.Variable `ebpf:"conn_fd_pos"` + CsS_pos *ebpf.Variable `ebpf:"cs_s_pos"` + EndAddr *ebpf.Variable `ebpf:"end_addr"` + FdRaddrPos *ebpf.Variable `ebpf:"fd_raddr_pos"` + Hex *ebpf.Variable `ebpf:"hex"` + IsRegistersAbi *ebpf.Variable `ebpf:"is_registers_abi"` + MaxOprationLength *ebpf.Variable `ebpf:"max_opration_length"` + PipeConnPos *ebpf.Variable `ebpf:"pipe_conn_pos"` + ResultErrorPos *ebpf.Variable `ebpf:"result_error_pos"` + StartAddr *ebpf.Variable `ebpf:"start_addr"` + TcpAddrIpPos *ebpf.Variable `ebpf:"tcp_addr_ip_pos"` + TcpAddrPortPos *ebpf.Variable `ebpf:"tcp_addr_port_pos"` + TcpConnConnPos *ebpf.Variable `ebpf:"tcp_conn_conn_pos"` + TotalCpus *ebpf.Variable `ebpf:"total_cpus"` +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobePipeDo *ebpf.Program `ebpf:"uprobe_pipe_Do"` + UprobePipeDoReturns *ebpf.Program `ebpf:"uprobe_pipe_Do_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobePipeDo, + p.UprobePipeDoReturns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_x86_bpfel.o +var _BpfBytes []byte diff --git a/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/probe.go b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/probe.go new file mode 100644 index 000000000..dc6f7c999 --- /dev/null +++ b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/probe.go @@ -0,0 +1,178 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package rueidis + +import ( + "fmt" + "log/slog" + "net" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/otel/attribute" + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" + "go.opentelemetry.io/otel/trace" + "golang.org/x/sys/unix" + + "go.opentelemetry.io/auto/internal/pkg/instrumentation/context" + "go.opentelemetry.io/auto/internal/pkg/instrumentation/probe" + "go.opentelemetry.io/auto/internal/pkg/instrumentation/utils" + "go.opentelemetry.io/auto/internal/pkg/structfield" +) + +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 bpf ./bpf/probe.bpf.c + +const ( + pkg = "github.com/redis/rueidis" +) + +var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff} + +func New(logger *slog.Logger, version string) probe.Probe { + id := probe.ID{ + SpanKind: trace.SpanKindClient, + InstrumentedPkg: pkg, + } + + uprobes := []*probe.Uprobe{ + { + Sym: "github.com/redis/rueidis.(*pipe).Do", + EntryProbe: "uprobe_pipe_Do", + ReturnProbe: "uprobe_pipe_Do_Returns", + PackageConstrainsts: []probe.PackageConstrainst{ + { + Package: "github.com/redis/rueidis", + FailureMode: probe.FailureModeIgnore, + }, + }, + }, + } + + // todo: does redis support distributed tracing? if yes, add propagation + + return &probe.SpanProducer[bpfObjects, event]{ + Base: probe.Base[bpfObjects, event]{ + ID: id, + Logger: logger, + Consts: []probe.Const{ + probe.RegistersABIConst{}, + probe.AllocationConst{}, + // to extract peer address data + probe.StructFieldConst{ + Key: "pipe_conn_pos", + Val: structfield.NewID(pkg, pkg, "pipe", "conn"), + }, + probe.StructFieldConst{ + Key: "tcp_conn_conn_pos", + Val: structfield.NewID("std", "net", "TCPConn", "conn"), + }, + probe.StructFieldConst{ + Key: "conn_fd_pos", + Val: structfield.NewID("std", "net", "conn", "fd"), + }, + probe.StructFieldConst{ + Key: "fd_raddr_pos", + Val: structfield.NewID("std", "net", "netFD", "raddr"), + }, + probe.StructFieldConst{ + Key: "tcp_addr_ip_pos", + Val: structfield.NewID("std", "net", "TCPAddr", "IP"), + }, + probe.StructFieldConst{ + Key: "tcp_addr_port_pos", + Val: structfield.NewID("std", "net", "TCPAddr", "Port"), + }, + // to extract command data + probe.StructFieldConst{ + Key: "completed_cs_pos", + Val: structfield.NewID(pkg, fmt.Sprintf("%s/%s", pkg, "internal/cmds"), "Completed", "cs"), + }, + probe.StructFieldConst{ + Key: "cs_s_pos", + Val: structfield.NewID(pkg, fmt.Sprintf("%s/%s", pkg, "internal/cmds"), "CommandSlice", "s"), + }, + // to extract response data + probe.StructFieldConst{ + Key: "result_error_pos", + Val: structfield.NewID(pkg, pkg, "RedisResult", "err"), + }, + }, + Uprobes: uprobes, + SpecFn: loadBpf, + }, + Version: version, + SchemaURL: semconv.SchemaURL, + ProcessFn: processFn, + } +} + +// event represents a kafka message received by the consumer. +type event struct { + context.BaseSpanProperties + + OperationName [20]byte + LocalAddr NetAddr +} + +type NetAddr struct { + IP [16]uint8 + Port int32 +} + +func processFn(e *event) ptrace.SpanSlice { + spans := ptrace.NewSpanSlice() + span := spans.AppendEmpty() + span.SetKind(ptrace.SpanKindClient) + span.SetStartTimestamp(utils.BootOffsetToTimestamp(e.StartTime)) + span.SetEndTimestamp(utils.BootOffsetToTimestamp(e.EndTime)) + span.SetTraceID(pcommon.TraceID(e.SpanContext.TraceID)) + span.SetSpanID(pcommon.SpanID(e.SpanContext.SpanID)) + span.SetFlags(uint32(trace.FlagsSampled)) + + operation := unix.ByteSliceToString(e.OperationName[:]) + span.SetName(fmt.Sprintf("%s %s", "cache", operation)) + + attrs := []attribute.KeyValue{} + + ip := parseU8SliceToIP(e.LocalAddr.IP) + + attrs = append(attrs, semconv.ServerAddress(ip.String())) + attrs = append(attrs, semconv.DBOperationName(operation)) + attrs = append(attrs, semconv.DBSystemRedis) + + // document: https://opentelemetry.io/docs/specs/semconv/database/redis/ + // span.Attributes().PutStr("db.namespace", "redis") // todo: hard to get as its set at the beginning of connection + // span.Attributes().PutStr("db.collection.name", "redis") // todo: maybe for zget, hget, mget and stuff? + // span.Attributes().PutStr("db.response.status_code", "redis") // todo + // span.Attributes().PutStr("error.type", "redis") // todo: later + // span.Attributes().PutStr("db.query.text", "redis") // todo + + utils.Attributes(span.Attributes(), attrs...) + + if e.ParentSpanContext.SpanID.IsValid() { + span.SetParentSpanID(pcommon.SpanID(e.ParentSpanContext.SpanID)) + } + + return spans +} + +func parseU8SliceToIP(raw [16]uint8) net.IP { + ip := make(net.IP, len(raw)) + copy(ip, raw[:]) + + if isZeros(raw[4:16]) { + copy(ip[12:16], raw[0:4]) + copy(ip[0:12], v4InV6Prefix) + } + return ip +} + +func isZeros(p net.IP) bool { + for i := 0; i < len(p); i++ { + if p[i] != 0 { + return false + } + } + return true +} diff --git a/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/probe_test.go b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/probe_test.go new file mode 100644 index 000000000..145f7c1bc --- /dev/null +++ b/internal/pkg/instrumentation/bpf/github.com/redis/rueidis/probe_test.go @@ -0,0 +1,79 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package rueidis + +import ( + "testing" + "time" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/auto/internal/pkg/instrumentation/context" + "go.opentelemetry.io/auto/internal/pkg/instrumentation/utils" + + "github.com/stretchr/testify/assert" + + semconv "go.opentelemetry.io/otel/semconv/v1.26.0" +) + +func TestProbeConvertEvent(t *testing.T) { + start := time.Unix(0, time.Now().UnixNano()) // No wall clock. + end := start.Add(1 * time.Second) + + startOffset := utils.TimeToBootOffset(start) + endOffset := utils.TimeToBootOffset(end) + + traceID := trace.TraceID{1} + spanID := trace.SpanID{1} + + testCases := []struct { + name string + event *event + expected ptrace.SpanSlice + }{ + { + name: "basic get test", + event: &event{ + BaseSpanProperties: context.BaseSpanProperties{ + StartTime: startOffset, + EndTime: endOffset, + SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID}, + }, + OperationName: [20]byte{0x47, 0x45, 0x54}, + LocalAddr: NetAddr{ + IP: [16]uint8{172, 20, 0, 3}, + Port: 6379, + }, + }, + expected: func() ptrace.SpanSlice { + spans := ptrace.NewSpanSlice() + span := spans.AppendEmpty() + span.SetName("cache GET") + span.SetKind(ptrace.SpanKindClient) + span.SetStartTimestamp(utils.BootOffsetToTimestamp(startOffset)) + span.SetEndTimestamp(utils.BootOffsetToTimestamp(endOffset)) + span.SetTraceID(pcommon.TraceID(traceID)) + span.SetSpanID(pcommon.SpanID(spanID)) + span.SetFlags(uint32(trace.FlagsSampled)) + utils.Attributes( + span.Attributes(), + semconv.ServerAddress("172.20.0.3"), + semconv.DBOperationName("GET"), + semconv.DBSystemRedis, + ) + + return spans + }(), + }, + } + + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + out := processFn(tt.event) + assert.Equal(t, tt.expected, out) + }) + } +} diff --git a/internal/pkg/instrumentation/manager.go b/internal/pkg/instrumentation/manager.go index 8fcf9e3f2..1d6afa3de 100644 --- a/internal/pkg/instrumentation/manager.go +++ b/internal/pkg/instrumentation/manager.go @@ -16,6 +16,7 @@ import ( "go.opentelemetry.io/otel/trace" dbSql "go.opentelemetry.io/auto/internal/pkg/instrumentation/bpf/database/sql" + rueidisProbe "go.opentelemetry.io/auto/internal/pkg/instrumentation/bpf/github.com/redis/rueidis" kafkaConsumer "go.opentelemetry.io/auto/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/consumer" kafkaProducer "go.opentelemetry.io/auto/internal/pkg/instrumentation/bpf/github.com/segmentio/kafka-go/producer" autosdk "go.opentelemetry.io/auto/internal/pkg/instrumentation/bpf/go.opentelemetry.io/auto/sdk" @@ -420,6 +421,7 @@ func (m *Manager) availableProbes() []probe.Probe { kafkaProducer.New(m.logger, m.version), kafkaConsumer.New(m.logger, m.version), autosdk.New(m.logger), + rueidisProbe.New(m.logger, m.version), } if m.globalImpl { diff --git a/internal/tools/inspect/cmd/offsetgen/main.go b/internal/tools/inspect/cmd/offsetgen/main.go index 17f841f8a..b879e23c5 100644 --- a/internal/tools/inspect/cmd/offsetgen/main.go +++ b/internal/tools/inspect/cmd/offsetgen/main.go @@ -75,6 +75,11 @@ func manifests() ([]inspect.Manifest, error) { return nil, fmt.Errorf("failed to get \"github.com/segmentio/kafka-go\" versions: %w", err) } + rueidisVers, err := PkgVersions("github.com/redis/rueidis") + if err != nil { + return nil, fmt.Errorf("failed to get \"github.com/redis/rueidis\" versions: %w", err) + } + ren := func(src string) inspect.Renderer { return inspect.NewRenderer(logger, src, inspect.DefaultFS) } @@ -125,6 +130,9 @@ func manifests() ([]inspect.Manifest, error) { structfield.NewID("std", "bufio", "Writer", "n"), structfield.NewID("std", "net", "TCPAddr", "IP"), structfield.NewID("std", "net", "TCPAddr", "Port"), + structfield.NewID("std", "net", "netFD", "raddr"), + structfield.NewID("std", "net", "conn", "fd"), + structfield.NewID("std", "net", "TCPConn", "conn"), }, }, { @@ -192,6 +200,18 @@ func manifests() ([]inspect.Manifest, error) { structfield.NewID("github.com/segmentio/kafka-go", "github.com/segmentio/kafka-go", "Conn", "clientID"), }, }, + { + Application: inspect.Application{ + Renderer: ren("templates/github.com/redis/rueidis/*.tmpl"), + Versions: rueidisVers, + }, + StructFields: []structfield.ID{ + structfield.NewID("github.com/redis/rueidis", "github.com/redis/rueidis/internal/cmds", "Completed", "cs"), + structfield.NewID("github.com/redis/rueidis", "github.com/redis/rueidis/internal/cmds", "CommandSlice", "s"), + structfield.NewID("github.com/redis/rueidis", "github.com/redis/rueidis", "RedisResult", "err"), + structfield.NewID("github.com/redis/rueidis", "github.com/redis/rueidis", "pipe", "conn"), + }, + }, }, nil } diff --git a/internal/tools/inspect/render.go b/internal/tools/inspect/render.go index 8280a9758..ef316272a 100644 --- a/internal/tools/inspect/render.go +++ b/internal/tools/inspect/render.go @@ -19,6 +19,7 @@ import ( //go:embed templates/runtime/*.tmpl //go:embed templates/go.opentelemetry.io/otel/traceglobal/*.tmpl //go:embed templates/github.com/segmentio/kafka-go/*.tmpl +//go:embed templates/github.com/redis/rueidis/*.tmpl var DefaultFS embed.FS // Renderer renders templates from an fs.FS. diff --git a/internal/tools/inspect/templates/github.com/redis/rueidis/go.mod.tmpl b/internal/tools/inspect/templates/github.com/redis/rueidis/go.mod.tmpl new file mode 100644 index 000000000..f88c45b6a --- /dev/null +++ b/internal/tools/inspect/templates/github.com/redis/rueidis/go.mod.tmpl @@ -0,0 +1,7 @@ +module grpcapp + +go 1.12 + +require github.com/redis/rueidis {{ .Version }} + +require golang.org/x/sys v0.17.0 // indirect diff --git a/internal/tools/inspect/templates/github.com/redis/rueidis/main.go.tmpl b/internal/tools/inspect/templates/github.com/redis/rueidis/main.go.tmpl new file mode 100644 index 000000000..cacb0fcff --- /dev/null +++ b/internal/tools/inspect/templates/github.com/redis/rueidis/main.go.tmpl @@ -0,0 +1,7 @@ +package main + +import ( + _ "github.com/redis/rueidis" +) + +func main() {}