From 71d578ca7f0af2eea82f41d601362431d4bd73f1 Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Sat, 31 Dec 2022 00:13:21 +0700 Subject: [PATCH 1/7] feat: simplify otel-collector example --- example/otel-collector/Dockerfile | 13 ++ example/otel-collector/Makefile | 28 --- example/otel-collector/README.md | 202 ++---------------- example/otel-collector/docker-compose.yaml | 42 ++++ example/otel-collector/go.mod | 4 + example/otel-collector/go.sum | 8 + example/otel-collector/k8s/jaeger.yaml | 19 -- example/otel-collector/k8s/namespace.yaml | 18 -- .../otel-collector/k8s/otel-collector.yaml | 153 ------------- .../k8s/prometheus-monitor.yaml | 43 ---- .../k8s/prometheus-service.yaml | 32 --- example/otel-collector/main.go | 40 +++- .../otel-collector/otel-collector-config.yaml | 31 +++ example/otel-collector/prometheus-config.yaml | 6 + 14 files changed, 162 insertions(+), 477 deletions(-) create mode 100644 example/otel-collector/Dockerfile delete mode 100644 example/otel-collector/Makefile create mode 100644 example/otel-collector/docker-compose.yaml delete mode 100644 example/otel-collector/k8s/jaeger.yaml delete mode 100644 example/otel-collector/k8s/namespace.yaml delete mode 100644 example/otel-collector/k8s/otel-collector.yaml delete mode 100644 example/otel-collector/k8s/prometheus-monitor.yaml delete mode 100644 example/otel-collector/k8s/prometheus-service.yaml create mode 100644 example/otel-collector/otel-collector-config.yaml create mode 100644 example/otel-collector/prometheus-config.yaml diff --git a/example/otel-collector/Dockerfile b/example/otel-collector/Dockerfile new file mode 100644 index 00000000000..8a7e848e02b --- /dev/null +++ b/example/otel-collector/Dockerfile @@ -0,0 +1,13 @@ +FROM golang:1.18-alpine AS base + +COPY . /src + +WORKDIR /src/example/otel-collector + +RUN go build -o main . + +FROM alpine:latest + +COPY --from=base /src/example/otel-collector/main /app/main + +CMD ["/app/main"] \ No newline at end of file diff --git a/example/otel-collector/Makefile b/example/otel-collector/Makefile deleted file mode 100644 index a5707834b39..00000000000 --- a/example/otel-collector/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -JAEGER_OPERATOR_VERSION = v1.36.0 - -namespace-k8s: - kubectl apply -f k8s/namespace.yaml - -jaeger-operator-k8s: - # Create the jaeger operator and necessary artifacts in ns observability - kubectl create -n observability -f https://github.com/jaegertracing/jaeger-operator/releases/download/$(JAEGER_OPERATOR_VERSION)/jaeger-operator.yaml - -jaeger-k8s: - kubectl apply -f k8s/jaeger.yaml - -prometheus-k8s: - kubectl apply -f k8s/prometheus-service.yaml # Prometheus instance - kubectl apply -f k8s/prometheus-monitor.yaml # Service monitor - -otel-collector-k8s: - kubectl apply -f k8s/otel-collector.yaml - -clean-k8s: - - kubectl delete -f k8s/otel-collector.yaml - - - kubectl delete -f k8s/prometheus-monitor.yaml - - kubectl delete -f k8s/prometheus-service.yaml - - - kubectl delete -f k8s/jaeger.yaml - - - kubectl delete -n observability -f https://github.com/jaegertracing/jaeger-operator/releases/download/$(JAEGER_OPERATOR_VERSION)/jaeger-operator.yaml diff --git a/example/otel-collector/README.md b/example/otel-collector/README.md index 6e13a59144a..426b6f81b44 100644 --- a/example/otel-collector/README.md +++ b/example/otel-collector/README.md @@ -1,4 +1,4 @@ -# OpenTelemetry Collector Traces Example +# OpenTelemetry Collector Traces, Metrics Example This example illustrates how to export trace and metric data from the OpenTelemetry-Go SDK to the OpenTelemetry Collector. From there, we bring the @@ -13,116 +13,32 @@ App + SDK ---> OpenTelemetry Collector ---| # Prerequisites -You will need access to a Kubernetes cluster for this demo. We use a local -instance of [microk8s](https://microk8s.io/), but please feel free to pick -your favorite. If you do decide to use microk8s, please ensure that dns -and storage addons are enabled +You need docker and docker-compose to run this example. If you don't have docker +installed, you can follow the instructions [here](https://docs.docker.com/get-docker/). -```bash -microk8s enable dns storage -``` - -For simplicity, the demo application is not part of the k8s cluster, and will -access the OpenTelemetry Collector through a NodePort on the cluster. Note that -the NodePort opened by this demo is not secured. - -Ideally you'd want to either have your application running as part of the -kubernetes cluster, or use a secured connection (NodePort/LoadBalancer with TLS -or an ingress extension). - -If not using microk8s, ensure that cert-manager is installed by following [the -instructions here](https://cert-manager.io/docs/installation/). - -# Deploying to Kubernetes - -All the necessary Kubernetes deployment files are available in this demo, in the -[k8s](./k8s) folder. For your convenience, we assembled a [makefile](./Makefile) -with deployment commands (see below). For those with subtly different systems, -you are, of course, welcome to poke inside the Makefile and run the commands -manually. If you use microk8s and alias `microk8s kubectl` to `kubectl`, the -Makefile will not recognize the alias, and so the commands will have to be run -manually. - -## Setting up the Prometheus operator - -If you're using microk8s like us, simply do - -```bash -microk8s enable prometheus -``` - -and you're good to go. Move on to [Using the makefile](#using-the-makefile). - -Otherwise, obtain a copy of the Prometheus Operator stack from -[prometheus-operator](https://github.com/prometheus-operator/kube-prometheus): - -```bash -git clone https://github.com/prometheus-operator/kube-prometheus.git -cd kube-prometheus -kubectl create -f manifests/setup - -# wait for namespaces and CRDs to become available, then -kubectl create -f manifests/ -``` - -And to tear down the stack when you're finished: - -```bash -kubectl delete --ignore-not-found=true -f manifests/ -f manifests/setup -``` - -## Using the makefile - -Next, we can deploy our Jaeger instance, Prometheus monitor, and Collector -using the [makefile](./Makefile). - -```bash -# Create the namespace -make namespace-k8s - -# Deploy Jaeger operator -make jaeger-operator-k8s - -# After the operator is deployed, create the Jaeger instance -make jaeger-k8s - -# Then the Prometheus instance. Ensure you have enabled a Prometheus operator -# before executing (see above). -make prometheus-k8s - -# Finally, deploy the OpenTelemetry Collector -make otel-collector-k8s -``` - -If you want to clean up after this, you can use the `make clean-k8s` to delete -all the resources created above. Note that this will not remove the namespace. -Because Kubernetes sometimes gets stuck when removing namespaces, please remove -this namespace manually after all the resources inside have been deleted, -for example with +# Running the example ```bash -kubectl delete namespaces observability +docker-compose up -d ``` # Configuring the OpenTelemetry Collector Although the above steps should deploy and configure everything, let's spend -some time on the [configuration](./k8s/otel-collector.yaml) of the Collector. +some time on the [configuration](./otel-collector-config.yaml) of the Collector. One important part here is that, in order to enable our application to send data to the OpenTelemetry Collector, we need to first configure the `otlp` receiver: ```yml ... - otel-collector-config: | - receivers: - # Make sure to add the otlp receiver. - # This will open up the receiver on port 4317. - otlp: - protocols: - grpc: - endpoint: "0.0.0.0:4317" - processors: +receivers: + # Make sure to add the otlp receiver. + # This will open up the receiver on port 4317 + otlp: + protocols: + grpc: + endpoint: "0.0.0.0:4317" ... ``` @@ -134,98 +50,26 @@ need to create the Jaeger and Prometheus exporters: ```yml ... - exporters: - jaeger: - endpoint: "jaeger-collector.observability.svc.cluster.local:14250" - - prometheus: - endpoint: 0.0.0.0:8889 - namespace: "testapp" +exporters: + jaeger: + endpoint: "jaeger:14250" + tls: + insecure: true + prometheus: + endpoint: 0.0.0.0:8889 ... ``` -## OpenTelemetry Collector service - -One more aspect in the OpenTelemetry Collector [configuration](./k8s/otel-collector.yaml) worth looking at is the NodePort service used for accessing it: - -```yaml -apiVersion: v1 -kind: Service -metadata: - ... -spec: - ports: - - name: otlp # Default endpoint for otlp receiver. - port: 4317 - protocol: TCP - targetPort: 4317 - nodePort: 30080 - - name: metrics # Endpoint for metrics from our app. - port: 8889 - protocol: TCP - targetPort: 8889 - selector: - component: otel-collector - type: - NodePort -``` - -This service will bind the `4317` port used to access the otlp receiver to port `30080` on your cluster's node. By doing so, it makes it possible for us to access the Collector by using the static address `:30080`. In case you are running a local cluster, this will be `localhost:30080`. Note that you can also change this to a LoadBalancer or have an ingress extension for accessing the service. - -# Running the code - -You can find the complete code for this example in the [main.go](./main.go) -file. To run it, ensure you have a somewhat recent version of Go (preferably >= -1.13) and do - -```bash -go run main.go -``` - -The example simulates an application, hard at work, computing for ten seconds -then finishing. - # Viewing instrumentation data Now the exciting part! Let's check out the telemetry data generated by our sample application ## Jaeger UI - -First, we need to enable an ingress provider. If you've been using microk8s, -do - -```bash -microk8s enable ingress -``` - -Then find out where the Jaeger console is living: - -```bash -kubectl get ingress --all-namespaces -``` - -For us, we get the output - -``` -NAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGE -observability jaeger-query * 127.0.0.1 80 5h40m -``` - -indicating that the Jaeger UI is available at -[http://localhost:80](http://localhost:80). Navigate there in your favorite +Jaeger UI is available at +[http://localhost:16686](http://localhost:16686). Navigate there in your favorite web-browser to view the generated traces. ## Prometheus - -Unfortunately, the Prometheus operator doesn't provide a convenient -out-of-the-box ingress route for us to use, so we'll use port-forwarding -instead. Note: this is a quick-and-dirty solution for the sake of example. -You *will* be attacked by shady people if you do this in production! - -```bash -kubectl --namespace monitoring port-forward svc/prometheus-k8s 9090 -``` - -Then navigate to [http://localhost:9090](http://localhost:9090) to view +Navigate to [http://localhost:9090](http://localhost:9090) to view the Prometheus dashboard. diff --git a/example/otel-collector/docker-compose.yaml b/example/otel-collector/docker-compose.yaml new file mode 100644 index 00000000000..db75fd9c8eb --- /dev/null +++ b/example/otel-collector/docker-compose.yaml @@ -0,0 +1,42 @@ +version: "3.7" +networks: + otel-collector-example: + name: otel-collector-example + +services: + go-app: + build: + context: ../.. + dockerfile: $PWD/Dockerfile + networks: + - otel-collector-example + otel-collector: + image: otel/opentelemetry-collector:latest + networks: + - otel-collector-example + volumes: + - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml + command: ["--config=/etc/otel-collector-config.yaml"] + expose: + - 4317 # Default endpoint for otlp receiver + - 8889 # Default endpoint for querying metrics + jaeger: + image: jaegertracing/all-in-one:latest + networks: + - otel-collector-example + expose: + - 14250 # Default endpoint for jaeger receiver + - 16686 # Default endpoint for jaeger query + ports: + - 16686:16686 + prometheus: + image: quay.io/prometheus/prometheus:latest + networks: + - otel-collector-example + volumes: + - ./prometheus-config.yaml:/etc/prometheus/prometheus.yml + expose: + - 9090 # Default endpoint for prometheus + ports: + - 9090:9090 + command: ["--config.file=/etc/prometheus/prometheus.yml"] diff --git a/example/otel-collector/go.mod b/example/otel-collector/go.mod index 51e93789716..99937659981 100644 --- a/example/otel-collector/go.mod +++ b/example/otel-collector/go.mod @@ -9,8 +9,11 @@ replace ( require ( go.opentelemetry.io/otel v1.11.2 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2 + go.opentelemetry.io/otel/metric v0.34.0 go.opentelemetry.io/otel/sdk v1.11.2 + go.opentelemetry.io/otel/sdk/metric v0.34.0 go.opentelemetry.io/otel/trace v1.11.2 google.golang.org/grpc v1.51.0 ) @@ -22,6 +25,7 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect diff --git a/example/otel-collector/go.sum b/example/otel-collector/go.sum index 95ced88c1aa..98813ccef9c 100644 --- a/example/otel-collector/go.sum +++ b/example/otel-collector/go.sum @@ -155,6 +155,14 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 h1:kpskzLZ60cJ48SJ4uxWa6waBL+4kSV6nVK8rP+QM8Wg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0/go.mod h1:4+x3i62TEegDHuzNva0bMcAN8oUi5w4liGb1d/VgPYo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 h1:e7kFb4pJLbhJgAwUdoVTHzB9pGujs5O8/7gFyZL88fg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0/go.mod h1:3x00m9exjIbhK+zTO4MsCSlfbVmgvLP0wjDgDKa/8bw= +go.opentelemetry.io/otel/metric v0.34.0 h1:MCPoQxcg/26EuuJwpYN1mZTeCYAUGx8ABxfW07YkjP8= +go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8= +go.opentelemetry.io/otel/sdk/metric v0.34.0 h1:7ElxfQpXCFZlRTvVRTkcUvK8Gt5DC8QzmzsLsO2gdzo= +go.opentelemetry.io/otel/sdk/metric v0.34.0/go.mod h1:l4r16BIqiqPy5rd14kkxllPy/fOI4tWo1jkpD9Z3ffQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= diff --git a/example/otel-collector/k8s/jaeger.yaml b/example/otel-collector/k8s/jaeger.yaml deleted file mode 100644 index 56558aee24c..00000000000 --- a/example/otel-collector/k8s/jaeger.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright The OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -apiVersion: jaegertracing.io/v1 -kind: Jaeger -metadata: - name: jaeger - namespace: observability \ No newline at end of file diff --git a/example/otel-collector/k8s/namespace.yaml b/example/otel-collector/k8s/namespace.yaml deleted file mode 100644 index c31ad1c9dcc..00000000000 --- a/example/otel-collector/k8s/namespace.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright The OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -apiVersion: v1 -kind: Namespace -metadata: - name: observability diff --git a/example/otel-collector/k8s/otel-collector.yaml b/example/otel-collector/k8s/otel-collector.yaml deleted file mode 100644 index c6497a0d282..00000000000 --- a/example/otel-collector/k8s/otel-collector.yaml +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright The OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -apiVersion: v1 -kind: ConfigMap -metadata: - name: otel-collector-conf - namespace: observability - labels: - app: opentelemetry - component: otel-collector-conf -data: - otel-collector-config: | - receivers: - # Make sure to add the otlp receiver. - # This will open up the receiver on port 4317 - otlp: - protocols: - grpc: - endpoint: "0.0.0.0:4317" - processors: - extensions: - health_check: {} - exporters: - jaeger: - endpoint: "jaeger-collector.observability.svc.cluster.local:14250" - insecure: true - prometheus: - endpoint: 0.0.0.0:8889 - namespace: "testapp" - logging: - - service: - extensions: [health_check] - pipelines: - traces: - receivers: [otlp] - processors: [] - exporters: [jaeger] - - metrics: - receivers: [otlp] - processors: [] - exporters: [prometheus, logging] ---- -apiVersion: v1 -kind: Service -metadata: - name: otel-collector - namespace: observability - labels: - app: opentelemetry - component: otel-collector -spec: - ports: - - name: otlp # Default endpoint for otlp receiver. - port: 4317 - protocol: TCP - targetPort: 4317 - nodePort: 30080 - - name: metrics # Default endpoint for metrics. - port: 8889 - protocol: TCP - targetPort: 8889 - selector: - component: otel-collector - type: NodePort ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: otel-collector - namespace: observability - labels: - app: opentelemetry - component: otel-collector -spec: - selector: - matchLabels: - app: opentelemetry - component: otel-collector - minReadySeconds: 5 - progressDeadlineSeconds: 120 - replicas: 1 #TODO - adjust this to your own requirements - template: - metadata: - annotations: - prometheus.io/path: "/metrics" - prometheus.io/port: "8889" - prometheus.io/scrape: "true" - labels: - app: opentelemetry - component: otel-collector - spec: - containers: - - command: - - "/otelcol" - - "--config=/conf/otel-collector-config.yaml" - # Memory Ballast size should be max 1/3 to 1/2 of memory. - - "--mem-ballast-size-mib=683" - env: - - name: GOGC - value: "80" - image: otel/opentelemetry-collector:0.6.0 - name: otel-collector - resources: - limits: - cpu: 1 - memory: 2Gi - requests: - cpu: 200m - memory: 400Mi - ports: - - containerPort: 4317 # Default endpoint for otlp receiver. - - containerPort: 8889 # Default endpoint for querying metrics. - volumeMounts: - - name: otel-collector-config-vol - mountPath: /conf - # - name: otel-collector-secrets - # mountPath: /secrets - livenessProbe: - httpGet: - path: / - port: 13133 # Health Check extension default port. - readinessProbe: - httpGet: - path: / - port: 13133 # Health Check extension default port. - volumes: - - configMap: - name: otel-collector-conf - items: - - key: otel-collector-config - path: otel-collector-config.yaml - name: otel-collector-config-vol -# - secret: -# name: otel-collector-secrets -# items: -# - key: cert.pem -# path: cert.pem -# - key: key.pem -# path: key.pem diff --git a/example/otel-collector/k8s/prometheus-monitor.yaml b/example/otel-collector/k8s/prometheus-monitor.yaml deleted file mode 100644 index 88d639a090c..00000000000 --- a/example/otel-collector/k8s/prometheus-monitor.yaml +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright The OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -apiVersion: monitoring.coreos.com/v1 -kind: Prometheus -metadata: - labels: - app: prometheus - prometheus: service-prometheus - name: service-prometheus - namespace: monitoring -spec: - alerting: - alertmanagers: - - name: alertmanager-main - namespace: monitoring - port: web - baseImage: quay.io/prometheus/prometheus - logLevel: info - paused: false - replicas: 2 - retention: 2d - routePrefix: / - ruleSelector: - matchLabels: - prometheus: service-prometheus - role: alert-rules - serviceAccountName: prometheus-k8s - serviceMonitorSelector: - matchExpressions: - - key: serviceapp - operator: Exists diff --git a/example/otel-collector/k8s/prometheus-service.yaml b/example/otel-collector/k8s/prometheus-service.yaml deleted file mode 100644 index 87634773e84..00000000000 --- a/example/otel-collector/k8s/prometheus-service.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright The OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - labels: - serviceapp: otel-collector - name: otel-collector - namespace: observability -spec: - endpoints: - - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - interval: 30s - port: metrics - namespaceSelector: - matchNames: - - observability - selector: - matchLabels: - app: opentelemetry diff --git a/example/otel-collector/main.go b/example/otel-collector/main.go index 7f426e6bf3e..1465f8a125b 100644 --- a/example/otel-collector/main.go +++ b/example/otel-collector/main.go @@ -30,8 +30,11 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + metricglobal "go.opentelemetry.io/otel/metric/global" "go.opentelemetry.io/otel/propagation" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.12.0" @@ -58,9 +61,9 @@ func initProvider() (func(context.Context) error, error) { // `localhost:30080` endpoint. Otherwise, replace `localhost` with the // endpoint of your cluster. If you run the app inside k8s, then you can // probably connect directly to the service through dns. - ctx, cancel := context.WithTimeout(ctx, time.Second) + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() - conn, err := grpc.DialContext(ctx, "localhost:30080", + conn, err := grpc.DialContext(ctx, "otel-collector:4317", // Note the use of insecure transport here. TLS is recommended in production. grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock(), @@ -88,8 +91,34 @@ func initProvider() (func(context.Context) error, error) { // set global propagator to tracecontext (the default is no-op). otel.SetTextMapPropagator(propagation.TraceContext{}) + // Set up a metric exporter + metricExporter, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithGRPCConn(conn)) + if err != nil { + return nil, fmt.Errorf("failed to create metric exporter: %w", err) + } + + metricProvider := sdkmetric.NewMeterProvider( + sdkmetric.WithReader( + sdkmetric.NewPeriodicReader( + metricExporter, + sdkmetric.WithInterval(5*time.Second), + ), + ), + ) + + metricglobal.SetMeterProvider(metricProvider) + + shutdownFunction := func(ctx context.Context) error { + if err := tracerProvider.Shutdown(ctx); err != nil { + return fmt.Errorf("failed to shutdown TracerProvider: %w", err) + } + if err := metricProvider.Shutdown(ctx); err != nil { + return fmt.Errorf("failed to shutdown MeterProvider: %w", err) + } + return nil + } // Shutdown will flush any remaining spans and shut down the exporter. - return tracerProvider.Shutdown, nil + return shutdownFunction, nil } func main() { @@ -104,7 +133,7 @@ func main() { } defer func() { if err := shutdown(ctx); err != nil { - log.Fatal("failed to shutdown TracerProvider: %w", err) + log.Fatal("failed to shutdown: %w", err) } }() @@ -117,18 +146,19 @@ func main() { attribute.String("attrB", "raspberry"), attribute.String("attrC", "vanilla"), } - // work begins ctx, span := tracer.Start( ctx, "CollectorExporter-Example", trace.WithAttributes(commonAttrs...)) defer span.End() + meter, _ := metricglobal.Meter("test-meter").SyncInt64().Counter("test-counter") for i := 0; i < 10; i++ { _, iSpan := tracer.Start(ctx, fmt.Sprintf("Sample-%d", i)) log.Printf("Doing really hard work (%d / 10)\n", i+1) <-time.After(time.Second) + meter.Add(ctx, 1) iSpan.End() } diff --git a/example/otel-collector/otel-collector-config.yaml b/example/otel-collector/otel-collector-config.yaml new file mode 100644 index 00000000000..368cfe20111 --- /dev/null +++ b/example/otel-collector/otel-collector-config.yaml @@ -0,0 +1,31 @@ +receivers: + # Make sure to add the otlp receiver. + # This will open up the receiver on port 4317 + otlp: + protocols: + grpc: + endpoint: "0.0.0.0:4317" +processors: +extensions: + health_check: {} +exporters: + jaeger: + endpoint: "jaeger:14250" + tls: + insecure: true + prometheus: + endpoint: 0.0.0.0:8889 + logging: + +service: + extensions: [health_check] + pipelines: + traces: + receivers: [otlp] + processors: [] + exporters: [jaeger] + + metrics: + receivers: [otlp] + processors: [] + exporters: [prometheus, logging] \ No newline at end of file diff --git a/example/otel-collector/prometheus-config.yaml b/example/otel-collector/prometheus-config.yaml new file mode 100644 index 00000000000..9ac8879d324 --- /dev/null +++ b/example/otel-collector/prometheus-config.yaml @@ -0,0 +1,6 @@ +scrape_configs: + - job_name: otel-collector + scrape_interval: 5s + static_configs: + - targets: ['otel-collector:8889'] + From 4ca0b64572143c82eabae47fa4d5e5f88e74ce77 Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Sat, 31 Dec 2022 00:17:42 +0700 Subject: [PATCH 2/7] chore: pre-commit source code --- example/otel-collector/go.mod | 8 ++++++++ example/otel-collector/go.sum | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/example/otel-collector/go.mod b/example/otel-collector/go.mod index 99937659981..ba992187d34 100644 --- a/example/otel-collector/go.mod +++ b/example/otel-collector/go.mod @@ -42,3 +42,11 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../../exporters/otl replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../../exporters/otlp/otlptrace/otlptracegrpc replace go.opentelemetry.io/otel/exporters/otlp/internal/retry => ../../exporters/otlp/internal/retry + +replace go.opentelemetry.io/otel/metric => ../../metric + +replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../../exporters/otlp/otlpmetric/otlpmetricgrpc + +replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../../exporters/otlp/otlpmetric + +replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric diff --git a/example/otel-collector/go.sum b/example/otel-collector/go.sum index 98813ccef9c..95ced88c1aa 100644 --- a/example/otel-collector/go.sum +++ b/example/otel-collector/go.sum @@ -155,14 +155,6 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 h1:kpskzLZ60cJ48SJ4uxWa6waBL+4kSV6nVK8rP+QM8Wg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0/go.mod h1:4+x3i62TEegDHuzNva0bMcAN8oUi5w4liGb1d/VgPYo= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 h1:e7kFb4pJLbhJgAwUdoVTHzB9pGujs5O8/7gFyZL88fg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0/go.mod h1:3x00m9exjIbhK+zTO4MsCSlfbVmgvLP0wjDgDKa/8bw= -go.opentelemetry.io/otel/metric v0.34.0 h1:MCPoQxcg/26EuuJwpYN1mZTeCYAUGx8ABxfW07YkjP8= -go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8= -go.opentelemetry.io/otel/sdk/metric v0.34.0 h1:7ElxfQpXCFZlRTvVRTkcUvK8Gt5DC8QzmzsLsO2gdzo= -go.opentelemetry.io/otel/sdk/metric v0.34.0/go.mod h1:l4r16BIqiqPy5rd14kkxllPy/fOI4tWo1jkpD9Z3ffQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= From c71986037023db2e933ee474bff9b8796ab9765b Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Sat, 31 Dec 2022 10:22:23 +0700 Subject: [PATCH 3/7] chore: update document --- example/otel-collector/README.md | 2 ++ example/otel-collector/main.go | 10 ++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/otel-collector/README.md b/example/otel-collector/README.md index 426b6f81b44..271fd85bca8 100644 --- a/example/otel-collector/README.md +++ b/example/otel-collector/README.md @@ -66,10 +66,12 @@ Now the exciting part! Let's check out the telemetry data generated by our sample application ## Jaeger UI + Jaeger UI is available at [http://localhost:16686](http://localhost:16686). Navigate there in your favorite web-browser to view the generated traces. ## Prometheus + Navigate to [http://localhost:9090](http://localhost:9090) to view the Prometheus dashboard. diff --git a/example/otel-collector/main.go b/example/otel-collector/main.go index 1465f8a125b..ea96498bc82 100644 --- a/example/otel-collector/main.go +++ b/example/otel-collector/main.go @@ -56,13 +56,11 @@ func initProvider() (func(context.Context) error, error) { return nil, fmt.Errorf("failed to create resource: %w", err) } - // If the OpenTelemetry Collector is running on a local cluster (minikube or - // microk8s), it should be accessible through the NodePort service at the - // `localhost:30080` endpoint. Otherwise, replace `localhost` with the - // endpoint of your cluster. If you run the app inside k8s, then you can - // probably connect directly to the service through dns. ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() + + // OpenTelemtry Collector is running on docker-compose in same network as this go app, + // and exposes the OTLP receiver on port 4317. conn, err := grpc.DialContext(ctx, "otel-collector:4317", // Note the use of insecure transport here. TLS is recommended in production. grpc.WithTransportCredentials(insecure.NewCredentials()), @@ -108,6 +106,7 @@ func initProvider() (func(context.Context) error, error) { metricglobal.SetMeterProvider(metricProvider) + // Shutdown will flush any remaining spans, meters and shut down the exporter. shutdownFunction := func(ctx context.Context) error { if err := tracerProvider.Shutdown(ctx); err != nil { return fmt.Errorf("failed to shutdown TracerProvider: %w", err) @@ -117,7 +116,6 @@ func initProvider() (func(context.Context) error, error) { } return nil } - // Shutdown will flush any remaining spans and shut down the exporter. return shutdownFunction, nil } From c0afbe9821fb0f8af160407928caca5520f799d7 Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Sat, 31 Dec 2022 10:22:45 +0700 Subject: [PATCH 4/7] Update `otel-collector` example --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff6d25fbe11..c6b3c447577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - `traceIDRatioSampler` (given by `TraceIDRatioBased(float64)`) now uses the rightmost bits for sampling decisions, fixing random sampling when using ID generators like `xray.IDGenerator` and increasing parity with other language implementations. (#3557) +- Update example of `otel-collector`: simplify setup by using `docker-compose` and add metric exporter (#3560) ### Deprecated From c430f321ee84ca5d367ec7c0399caa1f89659754 Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Mon, 2 Jan 2023 19:10:33 +0700 Subject: [PATCH 5/7] remove changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6b3c447577..ff6d25fbe11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - `traceIDRatioSampler` (given by `TraceIDRatioBased(float64)`) now uses the rightmost bits for sampling decisions, fixing random sampling when using ID generators like `xray.IDGenerator` and increasing parity with other language implementations. (#3557) -- Update example of `otel-collector`: simplify setup by using `docker-compose` and add metric exporter (#3560) ### Deprecated From 85f058e725afb22f361e07aedd4088d88f1d9de4 Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Tue, 3 Jan 2023 17:59:53 +0700 Subject: [PATCH 6/7] chore: improve code readablity, indications --- example/otel-collector/README.md | 3 ++ example/otel-collector/main.go | 90 ++++++++++++++++++++------------ 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/example/otel-collector/README.md b/example/otel-collector/README.md index 271fd85bca8..857a732618c 100644 --- a/example/otel-collector/README.md +++ b/example/otel-collector/README.md @@ -70,8 +70,11 @@ sample application Jaeger UI is available at [http://localhost:16686](http://localhost:16686). Navigate there in your favorite web-browser to view the generated traces. +After go application running, you can see the service name `test-service` in Searh bar. ## Prometheus Navigate to [http://localhost:9090](http://localhost:9090) to view the Prometheus dashboard. +After go application running, you can query metrics by expression `work_duration / 1000` in the query bar. +Result is duration of sample work in seconds. diff --git a/example/otel-collector/main.go b/example/otel-collector/main.go index ea96498bc82..1d7e8ea5be8 100644 --- a/example/otel-collector/main.go +++ b/example/otel-collector/main.go @@ -43,17 +43,15 @@ import ( // Initializes an OTLP exporter, and configures the corresponding trace and // metric providers. -func initProvider() (func(context.Context) error, error) { - ctx := context.Background() - +func initOTEL(ctx context.Context) (func(context.Context) error, error) { res, err := resource.New(ctx, resource.WithAttributes( - // the service name used to display traces in backends + // the service name used to display in observer backends semconv.ServiceNameKey.String("test-service"), ), ) if err != nil { - return nil, fmt.Errorf("failed to create resource: %w", err) + return nil, err } ctx, cancel := context.WithTimeout(ctx, 10*time.Second) @@ -70,25 +68,26 @@ func initProvider() (func(context.Context) error, error) { return nil, fmt.Errorf("failed to create gRPC connection to collector: %w", err) } - // Set up a trace exporter - traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithGRPCConn(conn)) + traceShutdownFunc, err := initTracerProvider(ctx, conn, res) if err != nil { - return nil, fmt.Errorf("failed to create trace exporter: %w", err) + return nil, fmt.Errorf("failed to initialize trace provider: %w", err) } + metricShutdownFunc, err := initMetricProvider(ctx, conn, res) + if err != nil { + return nil, fmt.Errorf("failed to initialize metric provider: %w", err) + } + return func(ctx context.Context) error { + if err := traceShutdownFunc(ctx); err != nil { + return fmt.Errorf("failed to shutdown trace provider: %w", err) + } + if err := metricShutdownFunc(ctx); err != nil { + return fmt.Errorf("failed to shutdown metric provider: %w", err) + } + return nil + }, nil +} - // Register the trace exporter with a TracerProvider, using a batch - // span processor to aggregate spans before export. - bsp := sdktrace.NewBatchSpanProcessor(traceExporter) - tracerProvider := sdktrace.NewTracerProvider( - sdktrace.WithSampler(sdktrace.AlwaysSample()), - sdktrace.WithResource(res), - sdktrace.WithSpanProcessor(bsp), - ) - otel.SetTracerProvider(tracerProvider) - - // set global propagator to tracecontext (the default is no-op). - otel.SetTextMapPropagator(propagation.TraceContext{}) - +func initMetricProvider(ctx context.Context, conn *grpc.ClientConn, res *resource.Resource) (func(context.Context) error, error) { // Set up a metric exporter metricExporter, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithGRPCConn(conn)) if err != nil { @@ -102,21 +101,43 @@ func initProvider() (func(context.Context) error, error) { sdkmetric.WithInterval(5*time.Second), ), ), + sdkmetric.WithResource(res), ) metricglobal.SetMeterProvider(metricProvider) - - // Shutdown will flush any remaining spans, meters and shut down the exporter. - shutdownFunction := func(ctx context.Context) error { - if err := tracerProvider.Shutdown(ctx); err != nil { - return fmt.Errorf("failed to shutdown TracerProvider: %w", err) - } + return func(ctx context.Context) error { if err := metricProvider.Shutdown(ctx); err != nil { return fmt.Errorf("failed to shutdown MeterProvider: %w", err) } return nil + }, nil +} + +func initTracerProvider(ctx context.Context, conn *grpc.ClientConn, res *resource.Resource) (func(context.Context) error, error) { + traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithGRPCConn(conn)) + if err != nil { + return nil, fmt.Errorf("failed to create trace exporter: %w", err) } - return shutdownFunction, nil + + // Register the trace exporter with a TracerProvider, using a batch + // span processor to aggregate spans before export. + bsp := sdktrace.NewBatchSpanProcessor(traceExporter) + tracerProvider := sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithResource(res), + sdktrace.WithSpanProcessor(bsp), + ) + otel.SetTracerProvider(tracerProvider) + + // set global propagator to tracecontext (the default is no-op). + otel.SetTextMapPropagator(propagation.TraceContext{}) + + return func(ctx context.Context) error { + if err := tracerProvider.Shutdown(ctx); err != nil { + return fmt.Errorf("failed to shutdown TracerProvider: %w", err) + } + return nil + }, nil } func main() { @@ -125,7 +146,7 @@ func main() { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() - shutdown, err := initProvider() + shutdown, err := initOTEL(ctx) if err != nil { log.Fatal(err) } @@ -136,7 +157,7 @@ func main() { }() tracer := otel.Tracer("test-tracer") - + counter, _ := metricglobal.Meter("MetricCollectorExporter-Example").SyncInt64().Counter("work_duration") // Attributes represent additional key-value descriptors that can be bound // to a metric observer or recorder. commonAttrs := []attribute.KeyValue{ @@ -147,16 +168,17 @@ func main() { // work begins ctx, span := tracer.Start( ctx, - "CollectorExporter-Example", + "TraceCollectorExporter-Example", trace.WithAttributes(commonAttrs...)) defer span.End() - meter, _ := metricglobal.Meter("test-meter").SyncInt64().Counter("test-counter") + for i := 0; i < 10; i++ { _, iSpan := tracer.Start(ctx, fmt.Sprintf("Sample-%d", i)) + startTime := time.Now() log.Printf("Doing really hard work (%d / 10)\n", i+1) - <-time.After(time.Second) - meter.Add(ctx, 1) + <-time.After(time.Duration(i) * time.Millisecond * 100) + counter.Add(ctx, time.Since(startTime).Milliseconds(), commonAttrs...) iSpan.End() } From a37957dd92d8b22d11db86370396d4982a0e5787 Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Wed, 4 Jan 2023 21:54:03 +0700 Subject: [PATCH 7/7] fix: update new metric api --- example/otel-collector/main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/example/otel-collector/main.go b/example/otel-collector/main.go index 1d7e8ea5be8..40948f5a36a 100644 --- a/example/otel-collector/main.go +++ b/example/otel-collector/main.go @@ -157,7 +157,10 @@ func main() { }() tracer := otel.Tracer("test-tracer") - counter, _ := metricglobal.Meter("MetricCollectorExporter-Example").SyncInt64().Counter("work_duration") + counter, err := metricglobal.Meter("MetricCollectorExporter-Example").Int64Counter("work_duration") + if err != nil { + log.Fatal(err) + } // Attributes represent additional key-value descriptors that can be bound // to a metric observer or recorder. commonAttrs := []attribute.KeyValue{