From bf47a62f9135f77c875bcac2ae07c750009e8dae Mon Sep 17 00:00:00 2001 From: Matthias Theuermann <73223147+mati007thm@users.noreply.github.com> Date: Thu, 11 Jan 2024 20:01:56 +0100 Subject: [PATCH] fix: golang metrics instrumentation (#5) --- dapr-distributed-calendar/go/go.mod | 26 +++++- dapr-distributed-calendar/go/go.sum | 51 +++++++++++ dapr-distributed-calendar/go/go_events.go | 84 +++++++++++++++++-- .../kubernetes/go-events.yaml | 8 +- 4 files changed, 158 insertions(+), 11 deletions(-) diff --git a/dapr-distributed-calendar/go/go.mod b/dapr-distributed-calendar/go/go.mod index d840411..fdfabe4 100644 --- a/dapr-distributed-calendar/go/go.mod +++ b/dapr-distributed-calendar/go/go.mod @@ -2,4 +2,28 @@ module go_events go 1.20 -require github.com/gorilla/mux v1.8.1 +require ( + github.com/gorilla/mux v1.8.1 + go.opentelemetry.io/otel v1.21.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 + go.opentelemetry.io/otel/metric v1.21.0 + go.opentelemetry.io/otel/sdk v1.21.0 + go.opentelemetry.io/otel/sdk/metric v1.21.0 +) + +require ( + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/grpc v1.59.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect +) diff --git a/dapr-distributed-calendar/go/go.sum b/dapr-distributed-calendar/go/go.sum index 7128337..ce0dc30 100644 --- a/dapr-distributed-calendar/go/go.sum +++ b/dapr-distributed-calendar/go/go.sum @@ -1,2 +1,53 @@ +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= +go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/dapr-distributed-calendar/go/go_events.go b/dapr-distributed-calendar/go/go_events.go index 3907886..3675d63 100644 --- a/dapr-distributed-calendar/go/go_events.go +++ b/dapr-distributed-calendar/go/go_events.go @@ -2,14 +2,22 @@ package main import ( "bytes" + "context" "encoding/json" "fmt" "io" "log" "net/http" "os" + "time" "github.com/gorilla/mux" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/metric" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" ) var daprPort = os.Getenv("DAPR_HTTP_PORT") // Dapr's default is 3500 if not configured @@ -25,8 +33,46 @@ type Event struct { ID string } +func newResource() (*resource.Resource, error) { + return resource.Merge(resource.Default(), + resource.NewWithAttributes(semconv.SchemaURL, + semconv.ServiceName("go-events"), + semconv.ServiceVersion("0.1.0"), + )) +} + +func newMeterProvider(res *resource.Resource) (*sdkmetric.MeterProvider, error) { + metricExporter, err := otlpmetricgrpc.New(context.Background()) + if err != nil { + return nil, err + } + + meterProvider := sdkmetric.NewMeterProvider( + sdkmetric.WithResource(res), + sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExporter, + // Default is 1m. Set to 3s for demonstrative purposes. + sdkmetric.WithInterval(3*time.Second))), + ) + otel.SetMeterProvider(meterProvider) + return meterProvider, nil +} + +var meter = otel.Meter("go-events") +var eventsCounter metric.Int64UpDownCounter + +func init() { + var err error + eventsCounter, err = meter.Int64UpDownCounter( + "events.counter", + metric.WithDescription("Number of events."), + metric.WithUnit("{events}"), + ) + if err != nil { + panic(err) + } +} + func addEvent(w http.ResponseWriter, r *http.Request) { - log.Printf(stateURL) var event Event err := json.NewDecoder(r.Body).Decode(&event) @@ -44,13 +90,14 @@ func addEvent(w http.ResponseWriter, r *http.Request) { "value": event.Name + " " + event.Date, } state, _ := json.Marshal(data) - log.Printf(string(state)) + log.Print(string(state)) resp, err := http.Post(stateURL, "application/json", bytes.NewBuffer(state)) if err != nil { log.Fatalln("Error posting to state", err) return } + eventsCounter.Add(context.Background(), 1) log.Printf("Response after posting to state: %s", resp.Status) http.Error(w, "All Okay", http.StatusOK) } @@ -62,12 +109,19 @@ func deleteEvent(w http.ResponseWriter, r *http.Request) { var eventID Identity err := json.NewDecoder(r.Body).Decode(&eventID) - log.Printf("Error decoding id") + if err != nil { + log.Print("Error decoding id") + return + } deleteURL := stateURL + "/" + eventID.ID log.Printf("Delete URL: %s", deleteURL) req, err := http.NewRequest(http.MethodDelete, deleteURL, nil) + if err != nil { + log.Fatalln("Error creating delete request", err) + return + } client := &http.Client{} resp, err := client.Do(req) if err != nil { @@ -78,8 +132,8 @@ func deleteEvent(w http.ResponseWriter, r *http.Request) { defer resp.Body.Close() bodyBytes, _ := io.ReadAll(resp.Body) - - log.Printf(string(bodyBytes)) + eventsCounter.Add(context.Background(), -1) + log.Print(string(bodyBytes)) } func getEvent(w http.ResponseWriter, r *http.Request) { @@ -114,10 +168,28 @@ func getEvent(w http.ResponseWriter, r *http.Request) { return } - log.Printf(string(bodyBytes)) + log.Print(string(bodyBytes)) } func main() { + res, err := newResource() + if err != nil { + panic(err) + } + + meterProvider, err := newMeterProvider(res) + if err != nil { + panic(err) + } + + defer func() { + if err := meterProvider.Shutdown(context.Background()); err != nil { + log.Println(err) + } + }() + + otel.SetMeterProvider(meterProvider) + router := mux.NewRouter() router.HandleFunc("/addEvent", addEvent).Methods("POST") diff --git a/dapr-distributed-calendar/kubernetes/go-events.yaml b/dapr-distributed-calendar/kubernetes/go-events.yaml index 266bdd0..e9efc41 100644 --- a/dapr-distributed-calendar/kubernetes/go-events.yaml +++ b/dapr-distributed-calendar/kubernetes/go-events.yaml @@ -16,7 +16,7 @@ spec: app: go-events annotations: # instrumentation.opentelemetry.io/inject-go: "go-instrumentation" - # instrumentation.opentelemetry.io/otel-go-auto-target-exe: '/root/app' + # instrumentation.opentelemetry.io/otel-go-auto-target-exe: '/bin/app' dapr.io/enabled: "true" dapr.io/app-id: "go-events" dapr.io/app-port: "6000" @@ -28,14 +28,14 @@ spec: spec: containers: - name: go-events - image: mati007thm/dapr-distributed-calendar_go-events:latest + image: mati007thm/dapr-distributed-calendar_go-events:manual env: - # - name: OTEL_SERVICE_NAME - # value: "go-events" - name: APP_PORT value: "6000" - name: DAPR_HTTP_PORT value: "3500" + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://otel-dapr-collector:4317" ports: - containerPort: 6000 imagePullPolicy: Always