From adee42c080856aa7783aa4a6d7399b3cb2f9d322 Mon Sep 17 00:00:00 2001 From: Michael Pleshakov Date: Tue, 14 Nov 2023 10:28:31 -0500 Subject: [PATCH 1/2] Prototype sending product telemetry Problem: - Understand how to send product telemetry using OpenTelemerty - Note: OpenTelemetry is required by the backend (F5 Data Fabric) Solution: - Use OpenTelemetry traces to send some telemetry data Note: an offline demo/presentation will follow this prototype Demo instructions: - Install OTel collector using /otel-collector/README.md instructions - Install NGF, 1 replica. - After NGF starts, it will send telemetry data once. - To show that NGF sends the data: - In NGF log, look for generated traces - In the OTel collector log, look for received traces. --- go.mod | 16 +++- go.sum | 37 ++++++++- internal/mode/static/manager.go | 8 ++ internal/mode/static/telemerty.go | 129 ++++++++++++++++++++++++++++++ otel-collector/README.md | 19 +++++ otel-collector/values.yaml | 27 +++++++ 6 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 internal/mode/static/telemerty.go create mode 100644 otel-collector/README.md create mode 100644 otel-collector/values.yaml diff --git a/go.mod b/go.mod index cf462530be..3d5afa283a 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,11 @@ require ( github.com/onsi/gomega v1.30.0 github.com/prometheus/client_golang v1.17.0 github.com/spf13/cobra v1.8.0 + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 + go.opentelemetry.io/otel/sdk v1.19.0 go.uber.org/zap v1.26.0 k8s.io/api v0.28.3 k8s.io/apimachinery v0.28.3 @@ -26,6 +31,7 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect @@ -33,6 +39,7 @@ require ( github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -46,6 +53,7 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/uuid v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -66,11 +74,14 @@ require ( github.com/prometheus/procfs v0.11.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.4 // indirect + go.opentelemetry.io/otel/metric v1.19.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/mod v0.13.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect + golang.org/x/oauth2 v0.10.0 // indirect golang.org/x/sys v0.14.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect @@ -78,6 +89,9 @@ require ( golang.org/x/tools v0.14.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/grpc v1.58.2 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 16041dac8b..35e9b6ab8b 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +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/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= @@ -24,9 +26,12 @@ github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBD github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4/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/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -41,6 +46,8 @@ github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -62,6 +69,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -150,6 +159,22 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +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= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= @@ -180,8 +205,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -226,6 +251,14 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= 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= diff --git a/internal/mode/static/manager.go b/internal/mode/static/manager.go index 3eca635143..39bd38af71 100644 --- a/internal/mode/static/manager.go +++ b/internal/mode/static/manager.go @@ -222,6 +222,14 @@ func StartManager(cfg config.Config) error { } } + err = mgr.Add(&telemetryReporter{ + k8sClient: mgr.GetClient(), + logger: cfg.Logger.WithName("telemetryReporter"), + }) + if err != nil { + return err + } + cfg.Logger.Info("Starting manager") return mgr.Start(ctx) } diff --git a/internal/mode/static/telemerty.go b/internal/mode/static/telemerty.go new file mode 100644 index 0000000000..9e659702a2 --- /dev/null +++ b/internal/mode/static/telemerty.go @@ -0,0 +1,129 @@ +package static + +import ( + "context" + + "github.com/go-logr/logr" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.17.0" + v1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type errorHandler struct { + logger logr.Logger +} + +func (h errorHandler) Handle(err error) { + h.logger.Error(err, "error in telemetry") +} + +type telemetryReporter struct { + k8sClient client.Client + logger logr.Logger +} + +func (r *telemetryReporter) Start(ctx context.Context) error { + // runs once in a POC. + + // telemetry endpoint configuration + var ( + // /otel-collector/README.md deploys a collector with the endpoint below + // no TLS or auth headers are needed for that collector + endpoint = "my-opentelemetry-collector.default.svc.cluster.local:4317" + secure = false // use TLS or not. + headers = map[string]string{} // allows t add headers to a GRPC connection. (e.g. authentication) + ) + + // gather telemetry data + var ns v1.Namespace + err := r.k8sClient.Get(ctx, client.ObjectKey{Name: "kube-system"}, &ns) + if err != nil { + return err + } + + // cluster ID (UUID of kube-system namespace) + clusterID := string(ns.UID) + // NGF version + ngfVersion := "product-tel-prototype-0.0.1" + + // configure OTel + otel.SetLogger(r.logger) + otel.SetErrorHandler(errorHandler{ + logger: r.logger, + }) + + // create resource + res, err := resource.Merge( + resource.Default(), + resource.NewWithAttributes( + "", + semconv.ServiceName("NGF"), + semconv.ServiceVersion("1.0.0"), + ), + ) + if err != nil { + return err + } + + stdoutExporter, err := newStdoutExporter() + if err != nil { + return err + } + + otelExporter, err := newOTLPExporter(ctx, endpoint, secure, headers) + if err != nil { + return err + } + + provider := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(stdoutExporter), // prints to stdout + sdktrace.WithBatcher(otelExporter), // sends to a collector + sdktrace.WithResource(res), + ) + + tracer := provider.Tracer("product-telemetry") + + // create span + _, span := tracer.Start(ctx, "report") + + span.SetAttributes( + attribute.String("clusterId", clusterID), + attribute.String("ngfVersion", ngfVersion), + ) + + // send + span.End() // exits immediately and sends asynchronously + + return nil +} + +func newStdoutExporter() (*stdouttrace.Exporter, error) { + return stdouttrace.New(stdouttrace.WithPrettyPrint()) +} + +func newOTLPExporter( + ctx context.Context, + endpoint string, + secure bool, + headers map[string]string, +) (*otlptrace.Exporter, error) { + options := []otlptracegrpc.Option{ + otlptracegrpc.WithEndpoint(endpoint), + otlptracegrpc.WithHeaders(headers), + } + + if !secure { + options = append(options, otlptracegrpc.WithInsecure()) + } + + traceClient := otlptracegrpc.NewClient(options...) + + return otlptrace.New(ctx, traceClient) +} diff --git a/otel-collector/README.md b/otel-collector/README.md new file mode 100644 index 0000000000..525c2b2546 --- /dev/null +++ b/otel-collector/README.md @@ -0,0 +1,19 @@ +# How to Install + +Add repo: + +```text +helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts +``` + +Install: + +```text +helm install my-opentelemetry-collector open-telemetry/opentelemetry-collector -f values.yaml +``` + +Uninstall: + +```text +helm uninstall my-opentelemetry-collector +``` diff --git a/otel-collector/values.yaml b/otel-collector/values.yaml new file mode 100644 index 0000000000..edd45ed200 --- /dev/null +++ b/otel-collector/values.yaml @@ -0,0 +1,27 @@ +mode: deployment +replicaCount: 1 +config: + exporters: + debug: + verbosity: detailed + receivers: + jaeger: + prometheus: + zipkin: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + service: + telemetry: + extensions: + - health_check + pipelines: + logs: + metrics: + traces: + exporters: + - debug + processors: + receivers: + - otlp From 08e863e022afacdb321fd84559b3b342a207a539 Mon Sep 17 00:00:00 2001 From: Michael Pleshakov Date: Mon, 27 Nov 2023 16:31:05 -0500 Subject: [PATCH 2/2] Add explanatory comments --- internal/mode/static/telemerty.go | 40 ++++++++++++++++++++++---- internal/mode/static/telemetry_test.go | 21 ++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 internal/mode/static/telemetry_test.go diff --git a/internal/mode/static/telemerty.go b/internal/mode/static/telemerty.go index 9e659702a2..917fef4431 100644 --- a/internal/mode/static/telemerty.go +++ b/internal/mode/static/telemerty.go @@ -53,13 +53,16 @@ func (r *telemetryReporter) Start(ctx context.Context) error { // NGF version ngfVersion := "product-tel-prototype-0.0.1" - // configure OTel + // Step 1 + // configure OTel global options otel.SetLogger(r.logger) otel.SetErrorHandler(errorHandler{ logger: r.logger, }) - // create resource + // Step 2 + // create a resource. + // the resource represents the entity producing telemetry data. res, err := resource.Merge( resource.Default(), resource.NewWithAttributes( @@ -72,24 +75,40 @@ func (r *telemetryReporter) Start(ctx context.Context) error { return err } + // Step 3 + // Create exporters + + // stdout exporter will not be needed in production. stdoutExporter, err := newStdoutExporter() if err != nil { return err } + // this creates an exporter with a GRPC connection to the collector + // however, it will not establish a network connection until we start sending data. + // see the comment inside newOTLPExporter() otelExporter, err := newOTLPExporter(ctx, endpoint, secure, headers) if err != nil { return err } + // Step 4 + // Create provider + // Batchers batch exporting multiple spans together for performance. + // We don't need that, since we only need to send one span. provider := sdktrace.NewTracerProvider( - sdktrace.WithBatcher(stdoutExporter), // prints to stdout - sdktrace.WithBatcher(otelExporter), // sends to a collector + //sdktrace.WithBatcher(stdoutExporter), + //sdktrace.WithBatcher(otelExporter), + sdktrace.WithSyncer(stdoutExporter), // prints to stdout + sdktrace.WithSyncer(otelExporter), // sends to a collector sdktrace.WithResource(res), ) + // Step 5 + // Create tracer tracer := provider.Tracer("product-telemetry") + // Step 6 // create span _, span := tracer.Start(ctx, "report") @@ -98,8 +117,12 @@ func (r *telemetryReporter) Start(ctx context.Context) error { attribute.String("ngfVersion", ngfVersion), ) - // send - span.End() // exits immediately and sends asynchronously + // Step 7 + // End span (send a trace). + // if sdktrace.WithSyncer is used, this will block until the data is sent. + // if sdktrace.WithBatcher is used, this will not block. However, the data will not be sent immediately. + // Any errors will be passed to the errorHandler configured above. + span.End() return nil } @@ -117,6 +140,11 @@ func newOTLPExporter( options := []otlptracegrpc.Option{ otlptracegrpc.WithEndpoint(endpoint), otlptracegrpc.WithHeaders(headers), + // Uncomment the block bellow to make sure a connection to the endpoint is established before otlptrace.New() returns. + // Not recommended. See https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md#dialing-in-grpc + //otlptracegrpc.WithDialOption( + // grpc.WithBlock(), + //), } if !secure { diff --git a/internal/mode/static/telemetry_test.go b/internal/mode/static/telemetry_test.go new file mode 100644 index 0000000000..9fb632fbc1 --- /dev/null +++ b/internal/mode/static/telemetry_test.go @@ -0,0 +1,21 @@ +package static + +import ( + "context" + "testing" + + ctlrZap "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +func TestTelemetry(t *testing.T) { + logger := ctlrZap.New() + + logger.Info("Starting exporter") + + reporter := &TelemetryReporter{ + Logger: logger, + } + + ctx := context.Background() + reporter.Start(ctx) +}