Skip to content

Commit feda558

Browse files
committed
Add OpenTelemetry example
1 parent 24e9024 commit feda558

File tree

8 files changed

+221
-4
lines changed

8 files changed

+221
-4
lines changed

examples/examples_test.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ EXAMPLES=(
6767
"features/metadata_interceptor"
6868
"features/multiplex"
6969
"features/name_resolving"
70+
"features/opentelemetry"
7071
"features/orca"
7172
"features/retry"
7273
"features/unix_abstract"
@@ -122,6 +123,7 @@ declare -A EXPECTED_SERVER_OUTPUT=(
122123
["features/metadata_interceptor"]="key1 from metadata: "
123124
["features/multiplex"]=":50051"
124125
["features/name_resolving"]="serving on localhost:50051"
126+
["features/opentelemetry"]="serving on :50051"
125127
["features/orca"]="Server listening"
126128
["features/retry"]="request succeeded count: 4"
127129
["features/unix_abstract"]="serving on @abstract-unix-socket"
@@ -146,6 +148,7 @@ declare -A EXPECTED_CLIENT_OUTPUT=(
146148
["features/metadata_interceptor"]="BidiStreaming Echo: hello world"
147149
["features/multiplex"]="Greeting: Hello multiplex"
148150
["features/name_resolving"]="calling helloworld.Greeter/SayHello to \"example:///resolver.example.grpc.io\""
151+
["features/opentelemetry"]="this is examples/opentelemetry (from :50051)" # does this need to exit to work?
149152
["features/orca"]="Per-call load report received: map\[db_queries:10\]"
150153
["features/retry"]="UnaryEcho reply: message:\"Try and Success\""
151154
["features/unix_abstract"]="calling echo.Echo/UnaryEcho to unix-abstract:abstract-unix-socket"

examples/features/customloadbalancer/client/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func main() {
5353
mr.InitialState(resolver.State{
5454
Endpoints: []resolver.Endpoint{
5555
{Addresses: []resolver.Address{{Addr: addr1}}},
56-
{Addresses: []resolver.Address{{Addr: addr2}}},
56+
{Addresses: []resolver.Address{{Addr: addr2}}}, // Do I need the addresses for this one?
5757
},
5858
ServiceConfig: sc,
5959
})
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# OpenTelemetry
2+
3+
This example shows how to configure OpenTelemetry on a client and server, and shows
4+
what type of telemetry data it can produce for certain RPC's.
5+
6+
## Try it
7+
8+
```
9+
go run server/main.go
10+
```
11+
12+
```
13+
go run client/main.go
14+
```
15+
16+
```
17+
curl localhost:9464/metrics
18+
curl localhost:9465/metrics
19+
```
20+
21+
## Explanation
22+
23+
The client continuously makes RPC's to a server. The client and server both
24+
expose a prometheus exporter to listen and provide metrics. This defaults to
25+
:9464 for the server and :9465 for the client.
26+
27+
OpenTelemetry is configured on both the client and the server, and exports to
28+
the Prometheus exporter. The exporter exposes metrics on the Prometheus ports
29+
described above.
30+
31+
Curling to the exposed Prometheus ports outputs the metrics recorded on the
32+
client and server.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
*
3+
* Copyright 2024 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package main
20+
21+
import (
22+
"context"
23+
"flag"
24+
"fmt"
25+
"log"
26+
"net/http"
27+
"time"
28+
29+
"google.golang.org/grpc"
30+
"google.golang.org/grpc/credentials/insecure"
31+
"google.golang.org/grpc/examples/features/proto/echo"
32+
"google.golang.org/grpc/stats/opentelemetry"
33+
34+
"github.com/prometheus/client_golang/prometheus/promhttp"
35+
"go.opentelemetry.io/otel/exporters/prometheus"
36+
"go.opentelemetry.io/otel/sdk/metric"
37+
)
38+
39+
var (
40+
addr = flag.String("addr", ":50051", "the server address to connect to")
41+
promAddr = flag.String("promAddr", ":9465", "the Prometheus exporter endpoint")
42+
)
43+
44+
func main() {
45+
exporter, err := prometheus.New()
46+
if err != nil {
47+
log.Fatalf("Failed to start prometheus exporter: %v", err)
48+
}
49+
provider := metric.NewMeterProvider(
50+
metric.WithReader(exporter),
51+
)
52+
// why 64 for interop 65 for example?
53+
go http.ListenAndServe(*promAddr, promhttp.Handler())
54+
55+
/*ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
56+
defer cancel()*/
57+
// play around to see if examples pass with this - unbounded
58+
ctx := context.Background()
59+
60+
do := opentelemetry.DialOption(opentelemetry.Options{MetricsOptions: opentelemetry.MetricsOptions{MeterProvider: provider}})
61+
62+
cc, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()), do)
63+
if err != nil {
64+
log.Fatalf("Failed to start NewClient: %v", err)
65+
}
66+
defer cc.Close()
67+
c := echo.NewEchoClient(cc)
68+
69+
// Make a RPC every second. This should trigger telemetry to be emitted from
70+
// the client and the server.
71+
for {
72+
r, err := c.UnaryEcho(ctx, &echo.EchoRequest{Message: "this is examples/opentelemetry"}) // do I need to rename, any call options? echopb etc. Requires 1.21, but not unstable exporter not in g3
73+
if err != nil {
74+
log.Fatalf("UnaryEcho failed: %v", err)
75+
}
76+
fmt.Println(r) // Does this need to exit to pass examples test? I think I just run bash script to run examples test. Does example test need determinstic output from this? Does the read me need to be deterministic output?
77+
time.Sleep(time.Second)
78+
}
79+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
*
3+
* Copyright 2024 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package main
20+
21+
import (
22+
"context"
23+
"flag"
24+
"fmt"
25+
"log"
26+
"net"
27+
"net/http"
28+
29+
"google.golang.org/grpc"
30+
pb "google.golang.org/grpc/examples/features/proto/echo"
31+
"google.golang.org/grpc/stats/opentelemetry"
32+
33+
"github.com/prometheus/client_golang/prometheus/promhttp"
34+
"go.opentelemetry.io/otel/exporters/prometheus"
35+
"go.opentelemetry.io/otel/sdk/metric"
36+
)
37+
38+
var (
39+
addr = flag.String("addr", ":50051", "the server address to connect to")
40+
promAddr = flag.String("promAddr", ":9464", "the Prometheus exporter endpoint")
41+
)
42+
43+
type echoServer struct {
44+
pb.UnimplementedEchoServer
45+
addr string
46+
}
47+
48+
func (s *echoServer) UnaryEcho(ctx context.Context, req *pb.EchoRequest) (*pb.EchoResponse, error) {
49+
return &pb.EchoResponse{Message: fmt.Sprintf("%s (from %s)", req.Message, s.addr)}, nil
50+
}
51+
52+
func main() {
53+
exporter, err := prometheus.New()
54+
if err != nil {
55+
log.Fatalf("Failed to start prometheus exporter: %v", err)
56+
}
57+
provider := metric.NewMeterProvider(
58+
metric.WithReader(exporter),
59+
)
60+
go http.ListenAndServe(*promAddr, promhttp.Handler())
61+
62+
so := opentelemetry.ServerOption(opentelemetry.Options{MetricsOptions: opentelemetry.MetricsOptions{MeterProvider: provider}})
63+
64+
lis, err := net.Listen("tcp", *addr)
65+
if err != nil {
66+
log.Fatalf("failed to listen: %v", err)
67+
}
68+
s := grpc.NewServer(so)
69+
pb.RegisterEchoServer(s, &echoServer{
70+
addr: *addr,
71+
})
72+
73+
log.Printf("serving on %s\n", *addr)
74+
75+
if err := s.Serve(lis); err != nil {
76+
log.Fatalf("failed to serve: %v", err)
77+
}
78+
}

examples/go.mod

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ toolchain go1.22.1
66

77
require (
88
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b
9+
github.com/prometheus/client_golang v1.19.1
10+
go.opentelemetry.io/otel/exporters/prometheus v0.49.0
11+
go.opentelemetry.io/otel/sdk/metric v1.27.0
912
golang.org/x/oauth2 v0.20.0
1013
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528155852-a33235495d66
1114
google.golang.org/grpc v1.64.0
1215
google.golang.org/grpc/gcp/observability v1.0.1
16+
google.golang.org/grpc/stats/opentelemetry v0.0.0-20240529235625-24e902437554
1317
google.golang.org/protobuf v1.34.1
1418
)
1519

@@ -37,6 +41,7 @@ require (
3741
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.3 // indirect
3842
github.com/aws/aws-sdk-go-v2/service/sts v1.28.10 // indirect
3943
github.com/aws/smithy-go v1.20.2 // indirect
44+
github.com/beorn7/perks v1.0.1 // indirect
4045
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
4146
github.com/cespare/xxhash/v2 v2.3.0 // indirect
4247
github.com/envoyproxy/go-control-plane v0.12.0 // indirect
@@ -50,11 +55,15 @@ require (
5055
github.com/google/uuid v1.6.0 // indirect
5156
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
5257
github.com/googleapis/gax-go/v2 v2.12.4 // indirect
58+
github.com/prometheus/client_model v0.6.1 // indirect
59+
github.com/prometheus/common v0.53.0 // indirect
60+
github.com/prometheus/procfs v0.15.0 // indirect
5361
go.opencensus.io v0.24.0 // indirect
5462
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect
5563
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect
5664
go.opentelemetry.io/otel v1.27.0 // indirect
5765
go.opentelemetry.io/otel/metric v1.27.0 // indirect
66+
go.opentelemetry.io/otel/sdk v1.27.0 // indirect
5867
go.opentelemetry.io/otel/trace v1.27.0 // indirect
5968
golang.org/x/crypto v0.23.0 // indirect
6069
golang.org/x/net v0.25.0 // indirect
@@ -69,3 +78,5 @@ require (
6978
)
7079

7180
replace google.golang.org/grpc => ../
81+
82+
replace google.golang.org/grpc/stats/opentelemetry => ../stats/opentelemetry

examples/go.sum

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.10 h1:69tpbPED7jKPyzMcrwSvhWcJ9bP
811811
github.com/aws/aws-sdk-go-v2/service/sts v1.28.10/go.mod h1:0Aqn1MnEuitqfsCNyKsdKLhDUOr4txD/g19EfiUqgws=
812812
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
813813
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
814+
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
815+
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
814816
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
815817
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
816818
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -1041,10 +1043,18 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ
10411043
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
10421044
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10431045
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1046+
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
1047+
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
10441048
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
10451049
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
10461050
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
10471051
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
1052+
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
1053+
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
1054+
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
1055+
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
1056+
github.com/prometheus/procfs v0.15.0 h1:A82kmvXJq2jTu5YUhSGNlYoxh85zLnKgPz4bMZgI5Ek=
1057+
github.com/prometheus/procfs v0.15.0/go.mod h1:Y0RJ/Y5g5wJpkTisOtqwDSo4HwhGmLB4VQSw2sQJLHk=
10481058
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
10491059
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
10501060
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@@ -1095,10 +1105,14 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4
10951105
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0=
10961106
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
10971107
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
1108+
go.opentelemetry.io/otel/exporters/prometheus v0.49.0 h1:Er5I1g/YhfYv9Affk9nJLfH/+qCCVVg1f2R9AbJfqDQ=
1109+
go.opentelemetry.io/otel/exporters/prometheus v0.49.0/go.mod h1:KfQ1wpjf3zsHjzP149P4LyAwWRupc6c7t1ZJ9eXpKQM=
10981110
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
10991111
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
1100-
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
1101-
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
1112+
go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
1113+
go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
1114+
go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI=
1115+
go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw=
11021116
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
11031117
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
11041118
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=

examples/helloworld/greeter_server/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
)
3232

3333
var (
34-
port = flag.Int("port", 50051, "The server port")
34+
port = flag.Int("port", 50051, "The server port") // The port only is the variable thing...
3535
)
3636

3737
// server is used to implement helloworld.GreeterServer.

0 commit comments

Comments
 (0)