Skip to content

Commit c96e018

Browse files
authored
chore: An example of instrumenting a gRPC client and server with Instana using instagrpc (#975)
* chore: an example of instrumenting a gRPC client and server with Instana using instagrpc
1 parent cd6dcb8 commit c96e018

File tree

8 files changed

+679
-0
lines changed

8 files changed

+679
-0
lines changed

example/grpc/README.md

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# An Example For gRPC Instrumentation
2+
============================
3+
4+
An example of instrumenting a gRPC client and server with Instana using [`github.com/instana/go-sensor/tree/main/instrumentation/instagrpc`](https://pkg.go.dev/github.com/instana/go-sensor/instrumentation/instagrpc).
5+
6+
7+
## Usage
8+
9+
Install the packages
10+
11+
```bash
12+
go mod tidy
13+
```
14+
15+
Start the gRPC Server:
16+
17+
```bash
18+
go run server/main.go
19+
```
20+
21+
Run the gRPC client
22+
23+
```bash
24+
go run client/main.go
25+
```
26+
27+
## Output
28+
29+
The client makes a unary, stream and an unknown call to the gRPC server. You will be able to see those 3 call traces in the Instana dashboard.

example/grpc/client/main.go

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// (c) Copyright IBM Corp. 2024
2+
3+
//go:build go1.22
4+
// +build go1.22
5+
6+
package main
7+
8+
import (
9+
"context"
10+
"io"
11+
"log"
12+
"time"
13+
14+
instana "github.com/instana/go-sensor"
15+
pb "github.com/instana/go-sensor/example/grpc/hellopb"
16+
"github.com/instana/go-sensor/instrumentation/instagrpc"
17+
"github.com/opentracing/opentracing-go/ext"
18+
"google.golang.org/grpc"
19+
)
20+
21+
func main() {
22+
23+
sensor := instana.NewSensor("grpc-client")
24+
25+
// Connect to the server.
26+
conn, err := grpc.Dial("localhost:50051",
27+
grpc.WithInsecure(),
28+
grpc.WithUnaryInterceptor(instagrpc.UnaryClientInterceptor(sensor)),
29+
grpc.WithStreamInterceptor(instagrpc.StreamClientInterceptor(sensor)))
30+
if err != nil {
31+
log.Fatalf("Failed to connect: %v", err)
32+
}
33+
defer conn.Close()
34+
35+
client := pb.NewGreeterClient(conn)
36+
37+
// Unary call
38+
doUnaryCall(sensor, client)
39+
40+
// Server-side streaming call
41+
doStreamingCall(sensor, client)
42+
43+
// Make a call to an unknown service/method.
44+
doUnknownServiceCall(sensor, conn)
45+
46+
time.Sleep(10 * time.Minute)
47+
}
48+
49+
func doUnknownServiceCall(sensor instana.TracerLogger, client *grpc.ClientConn) {
50+
51+
sp := sensor.Tracer().
52+
StartSpan("grpc-unknown-service-call").
53+
SetTag(string(ext.SpanKind), "entry")
54+
55+
sp.Finish()
56+
57+
ctx := instana.ContextWithSpan(context.Background(), sp)
58+
59+
// Invoke a non-existent method (this will trigger the UnknownServiceHandler).
60+
err := client.Invoke(ctx, "/UnknownService/UnknownMethod", nil, nil)
61+
if err != nil {
62+
log.Printf("Error from server: %v", err)
63+
} else {
64+
log.Println("Call succeeded (unexpected).")
65+
}
66+
}
67+
68+
func doUnaryCall(sensor instana.TracerLogger, client pb.GreeterClient) {
69+
70+
sp := sensor.Tracer().
71+
StartSpan("grpc-unary-client-call").
72+
SetTag(string(ext.SpanKind), "entry")
73+
74+
sp.Finish()
75+
76+
ctx := instana.ContextWithSpan(context.Background(), sp)
77+
78+
log.Println("Starting Unary Call...")
79+
ctx, cancel := context.WithTimeout(ctx, time.Second)
80+
defer cancel()
81+
82+
resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "World"})
83+
if err != nil {
84+
log.Fatalf("Unary call failed: %v", err)
85+
}
86+
log.Printf("Unary Response: %s", resp.GetMessage())
87+
}
88+
89+
func doStreamingCall(sensor instana.TracerLogger, client pb.GreeterClient) {
90+
91+
sp := sensor.Tracer().
92+
StartSpan("grpc-stream-client-call").
93+
SetTag(string(ext.SpanKind), "entry")
94+
95+
sp.Finish()
96+
97+
ctx := instana.ContextWithSpan(context.Background(), sp)
98+
99+
log.Println("Starting Streaming Call...")
100+
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
101+
defer cancel()
102+
103+
stream, err := client.SayHelloStream(ctx, &pb.HelloRequest{Name: "World"})
104+
if err != nil {
105+
log.Fatalf("Streaming call failed: %v", err)
106+
}
107+
108+
for {
109+
resp, err := stream.Recv()
110+
if err == io.EOF {
111+
log.Println("Streaming completed.")
112+
break
113+
}
114+
if err != nil {
115+
log.Fatalf("Error receiving stream: %v", err)
116+
}
117+
log.Printf("Streaming Response: %s", resp.GetMessage())
118+
}
119+
}

example/grpc/go.mod

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module github.com/instana/go-sensor/example/grpc
2+
3+
go 1.22.7
4+
5+
require (
6+
github.com/instana/go-sensor v1.65.0
7+
github.com/instana/go-sensor/instrumentation/instagrpc v1.29.0
8+
github.com/opentracing/opentracing-go v1.2.0
9+
google.golang.org/grpc v1.68.0
10+
google.golang.org/protobuf v1.35.2
11+
)
12+
13+
require (
14+
github.com/google/uuid v1.6.0 // indirect
15+
github.com/looplab/fsm v1.0.1 // indirect
16+
golang.org/x/net v0.29.0 // indirect
17+
golang.org/x/sys v0.25.0 // indirect
18+
golang.org/x/text v0.18.0 // indirect
19+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
20+
)

example/grpc/go.sum

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
5+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
6+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
7+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
8+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
9+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
10+
github.com/instana/go-sensor v1.65.0 h1:tvghnyNsSE2Bj1nsARLwLFc7GIR9+NXN7QAjMRw6EHg=
11+
github.com/instana/go-sensor v1.65.0/go.mod h1:Ngi6H3q4iZ6yn4EH9zQYUflI/eDTULrM3B+RW9HN4zI=
12+
github.com/instana/go-sensor/instrumentation/instagrpc v1.29.0 h1:YwdOePmbhNS2tGp1zfsdfl6ZxjKw5D79m3i7YyUVkbI=
13+
github.com/instana/go-sensor/instrumentation/instagrpc v1.29.0/go.mod h1:7nSl2l6iVw75UnW5oIe3q0CFEUGJ+z+4sjmir3GnWAg=
14+
github.com/looplab/fsm v1.0.1 h1:OEW0ORrIx095N/6lgoGkFkotqH6s7vaFPsgjLAaF5QU=
15+
github.com/looplab/fsm v1.0.1/go.mod h1:PmD3fFvQEIsjMEfvZdrCDZ6y8VwKTwWNjlpEr6IKPO4=
16+
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
17+
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
18+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
19+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
20+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
21+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
22+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
23+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
24+
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
25+
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
26+
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
27+
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
28+
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
29+
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
30+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
31+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
32+
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
33+
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
34+
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
35+
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
36+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
37+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)