Skip to content

Commit 9b09575

Browse files
committed
Adding OpenChoreo trace module for Moesif
1 parent bd7385c commit 9b09575

8 files changed

Lines changed: 429 additions & 0 deletions

File tree

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Observability Tracing Module for Moesif
2+
3+
This module collects traces using [OpenTelemetry Collector](https://opentelemetry.io) and exports them to [Moesif](https://www.moesif.com).
4+
5+
## Prerequisites
6+
7+
- [OpenChoreo](https://github.com/openchoreo/openchoreo) must be installed with the **observability plane** enabled for this module to work.
8+
- A Moesif account and a **Collector Application ID** for each environment from [Moesif](https://www.moesif.com/).
9+
10+
## Installation
11+
12+
### Create a Kubernetes Secret
13+
14+
Create a Kubernetes secret containing your Moesif Collector Application IDs, with one key per environment.
15+
16+
> **Note:**
17+
> - Use the environment name as the key (e.g., `development`, `production`).
18+
> - For environment names that contain hyphens (e.g., `my-env`), replace hyphens with underscores in the secret key (e.g., `my_env`).
19+
20+
```bash
21+
kubectl create secret generic moesif-tracing-secret \
22+
--from-literal=development="YOUR_DEV_COLLECTOR_APP_ID" \
23+
--from-literal=production="YOUR_PROD_COLLECTOR_APP_ID" \
24+
--namespace openchoreo-observability-plane
25+
```
26+
27+
### Install the Helm Chart
28+
29+
#### Installation modes
30+
31+
This chart supports two `global.installationMode` values:
32+
33+
- **`singleCluster`** *(default)*: Deploy the OpenTelemetry Collector into a single cluster where both the dataplane and the observability plane reside.
34+
- **`multiClusterReceiver`**: Deploy the OpenTelemetry Collector as a central receiver in the observability plane cluster. It accepts OTLP traces from remote dataplane clusters and forwards them to Moesif.
35+
36+
#### Single-cluster topology
37+
38+
```bash
39+
helm upgrade --install observability-tracing-moesif \
40+
oci://ghcr.io/openchoreo/helm-charts/observability-tracing-moesif \
41+
--create-namespace \
42+
--namespace openchoreo-observability-plane \
43+
--version 0.1.0
44+
```
45+
46+
#### Multi-cluster topology (receiver)
47+
48+
Install in the observability plane cluster. An HTTPRoute will be created so that dataplane clusters can push OTLP traces over HTTP/gRPC.
49+
50+
```bash
51+
helm upgrade --install observability-tracing-moesif \
52+
oci://ghcr.io/openchoreo/helm-charts/observability-tracing-moesif \
53+
--create-namespace \
54+
--namespace openchoreo-observability-plane \
55+
--version 0.1.0 \
56+
--set global.installationMode="multiClusterReceiver"
57+
```
58+
59+
### Configuration Options
60+
61+
For easier configuration management, create a `moesif-tracing-values.yaml` file:
62+
63+
```yaml
64+
# moesif-tracing-values.yaml
65+
66+
global:
67+
# installationMode: "singleCluster" # default
68+
# installationMode: "multiClusterReceiver"
69+
70+
moesif:
71+
# List of environment names to collect traces from.
72+
# These must match the openchoreo.dev/environment label on your resources.
73+
environments:
74+
- development
75+
- production
76+
77+
# (Optional) Moesif API endpoint. Defaults to https://api.moesif.net
78+
# endpoint: "https://api.moesif.net"
79+
80+
opentelemetryCollectorCustomizations:
81+
tailSampling:
82+
enabled: false # Enable tail-based sampling if needed
83+
```
84+
85+
Then install with:
86+
87+
```bash
88+
helm upgrade --install observability-tracing-moesif \
89+
oci://ghcr.io/openchoreo/helm-charts/observability-tracing-moesif \
90+
--create-namespace \
91+
--namespace openchoreo-observability-plane \
92+
--version 0.1.0 \
93+
-f moesif-tracing-values.yaml
94+
```
95+
96+
#### Configuration Parameters
97+
98+
| Parameter | Description | Default |
99+
|-----------|-------------|---------|
100+
| `global.installationMode` | Installation mode: `singleCluster` or `multiClusterReceiver` | `singleCluster` |
101+
| `moesif.environments` | List of environment names to collect traces from | `[development, production]` |
102+
| `moesif.endpoint` | (Optional) Moesif API endpoint URL | `https://api.moesif.net` |
103+
| `opentelemetryCollectorCustomizations.tailSampling.enabled` | Enable tail-based sampling | `false` |
104+
105+
## How It Works
106+
107+
This module deploys an **OpenTelemetry Collector** that:
108+
109+
1. Receives OTLP traces (gRPC on port `4317`, HTTP on port `4318`) from instrumented workloads.
110+
2. Enriches spans with Kubernetes metadata (pod name, deployment, namespace, etc.) using the `k8sattributes` processor (in `singleCluster` mode).
111+
3. Routes traces to the correct Moesif application based on the `openchoreo.dev/environment` resource attribute.
112+
4. Exports traces to Moesif using the Moesif Collector Application ID stored in the `moesif-tracing-secret` Kubernetes secret.
113+
114+
## Troubleshooting
115+
116+
### Check OpenTelemetry Collector logs
117+
118+
```bash
119+
kubectl -n openchoreo-observability-plane logs -f deploy/moesif-tracing-collector
120+
```
121+
122+
### Verify the secret exists
123+
124+
```bash
125+
kubectl -n openchoreo-observability-plane get secret moesif-tracing-secret
126+
```
127+
128+
### Check pod health
129+
130+
```bash
131+
kubectl -n openchoreo-observability-plane get pods
132+
```
133+
134+
## Uninstalling
135+
136+
```bash
137+
helm uninstall observability-tracing-moesif \
138+
--namespace openchoreo-observability-plane
139+
```
140+
141+
To also remove the secret:
142+
143+
```bash
144+
kubectl delete secret moesif-tracing-secret \
145+
--namespace openchoreo-observability-plane
146+
```
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright 2026 The OpenChoreo Authors
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# Patterns to ignore when building packages.
5+
# This supports shell glob matching, relative path matching, and
6+
# negation (prefixed with !). Only one pattern per line.
7+
.DS_Store
8+
# Common VCS dirs
9+
.git/
10+
.gitignore
11+
.bzr/
12+
.bzrignore
13+
.hg/
14+
.hgignore
15+
.svn/
16+
# Common backup files
17+
*.swp
18+
*.bak
19+
*.tmp
20+
*.orig
21+
*~
22+
# Various IDEs
23+
.project
24+
.idea/
25+
*.tmproj
26+
.vscode/
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
dependencies:
2+
- name: opentelemetry-collector
3+
repository: https://open-telemetry.github.io/opentelemetry-helm-charts
4+
version: 0.140.0
5+
digest: sha256:95b44d32f6aa013cfb900bb0a34e42551bf87c4891cabba2cfc56b1898c13a3b
6+
generated: "2026-04-02T17:13:19.651043+05:30"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright 2026 The OpenChoreo Authors
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
apiVersion: v2
5+
name: observability-tracing-moesif
6+
description: A Helm chart for OpenChoreo Moesif Tracing module
7+
type: application
8+
version: 0.1.0
9+
appVersion: "0.1.0"
10+
keywords:
11+
- moesif
12+
- observability
13+
- tracing
14+
home: https://github.com/openchoreo/community-modules
15+
maintainers:
16+
- name: Moesif Team
17+
dependencies:
18+
- name: opentelemetry-collector
19+
repository: https://open-telemetry.github.io/opentelemetry-helm-charts
20+
version: 0.140.0
21+
condition: opentelemetry-collector.enabled
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Copyright 2026 The OpenChoreo Authors
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
apiVersion: v1
5+
kind: ConfigMap
6+
metadata:
7+
name: moesif-tracing-collector-config
8+
namespace: {{ .Release.Namespace }}
9+
data:
10+
relay: |
11+
receivers:
12+
otlp:
13+
protocols:
14+
grpc:
15+
endpoint: 0.0.0.0:4317
16+
http:
17+
endpoint: 0.0.0.0:4318
18+
19+
exporters:
20+
debug:
21+
verbosity: detailed
22+
{{- range .Values.moesif.environments }}
23+
otlphttp/{{ . }}:
24+
endpoint: {{ $.Values.moesif.endpoint | default "https://api.moesif.net" | quote }}
25+
headers:
26+
{{- if eq $.Values.moesif.auth_mode "api-key" }}
27+
X-Api-Token: ${env:api_key}
28+
{{- else }}
29+
X-Moesif-Application-Id: ${env:{{ . | replace "-" "_" }}}
30+
{{- end }}
31+
{{- end }}
32+
33+
connectors:
34+
routing:
35+
table:
36+
{{- range .Values.moesif.environments }}
37+
- context: resource
38+
statement: route() where resource.attributes["openchoreo.dev/environment"] == {{ . | quote }}
39+
pipelines: [ traces/{{ . }} ]
40+
{{- end }}
41+
42+
extensions:
43+
health_check:
44+
endpoint: ${env:MY_POD_IP}:13133
45+
46+
processors:
47+
{{- if or (eq .Values.global.installationMode "singleCluster") }}
48+
k8sattributes:
49+
auth_type: "serviceAccount"
50+
passthrough: false
51+
52+
extract:
53+
labels:
54+
- tag_name: $$1
55+
key_regex: (.*)
56+
from: pod
57+
58+
metadata:
59+
- k8s.pod.name
60+
- k8s.pod.uid
61+
- k8s.deployment.name
62+
- k8s.namespace.name
63+
- k8s.node.name
64+
{{- end }}
65+
{{- if .Values.opentelemetryCollectorCustomizations.tailSampling.enabled }}
66+
tail_sampling:
67+
decision_wait: {{ .Values.opentelemetryCollectorCustomizations.tailSampling.decisionWait }}
68+
num_traces: {{ .Values.opentelemetryCollectorCustomizations.tailSampling.numTraces }}
69+
expected_new_traces_per_sec: {{ .Values.opentelemetryCollectorCustomizations.tailSampling.expectedNewTracesPerSec }}
70+
decision_cache:
71+
sampled_cache_size: {{ .Values.opentelemetryCollectorCustomizations.tailSampling.decisionCache.sampledCacheSize }}
72+
non_sampled_cache_size: {{ .Values.opentelemetryCollectorCustomizations.tailSampling.decisionCache.nonSampledCacheSize }}
73+
policies: [
74+
{
75+
name: rate_limiting,
76+
type: rate_limiting,
77+
rate_limiting: {spans_per_second: {{ .Values.opentelemetryCollectorCustomizations.tailSampling.spansPerSecond }} }
78+
},
79+
]
80+
{{- end }}
81+
{{- if eq $.Values.moesif.auth_mode "api-key" }}
82+
batch:
83+
metadata_keys:
84+
- x-org-id
85+
- x-app-id
86+
metadata_cardinality_limit: 1000
87+
timeout: 10s
88+
send_batch_size: 1024
89+
{{- end }}
90+
91+
service:
92+
extensions: [health_check]
93+
pipelines:
94+
traces/in:
95+
receivers: [otlp]
96+
{{- $processors := list }}
97+
{{- if or (eq .Values.global.installationMode "singleCluster") }}
98+
{{- $processors = append $processors "k8sattributes" }}
99+
{{- end }}
100+
{{- if .Values.opentelemetryCollectorCustomizations.tailSampling.enabled }}
101+
{{- $processors = append $processors "tail_sampling" }}
102+
{{- end }}
103+
{{- if $processors }}
104+
processors: [{{ join ", " $processors }}]
105+
{{- end }}
106+
exporters: [ routing ]
107+
{{- range .Values.moesif.environments }}
108+
traces/{{ . }}:
109+
receivers: [ routing ]
110+
exporters: [ otlphttp/{{ . }}, debug ]
111+
{{- end }}
112+
telemetry:
113+
metrics:
114+
readers:
115+
- pull:
116+
exporter:
117+
prometheus:
118+
host: '0.0.0.0'
119+
port: 8888
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2026 The OpenChoreo Authors
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
{{- if eq .Values.global.installationMode "multiClusterReceiver" }}
5+
apiVersion: gateway.networking.k8s.io/v1
6+
kind: HTTPRoute
7+
metadata:
8+
name: opentelemetry-collector-otlp
9+
namespace: {{ .Release.Namespace }}
10+
spec:
11+
parentRefs:
12+
- name: gateway-default
13+
namespace: {{ .Release.Namespace }}
14+
{{- with .Values.opentelemetryCollectorCustomizations.http.hostnames }}
15+
hostnames:
16+
{{- range . }}
17+
- {{ . | quote }}
18+
{{- end }}
19+
{{- end }}
20+
rules:
21+
# OTLP gRPC (4317): match gRPC traffic and route to gRPC receiver.
22+
- matches:
23+
- headers:
24+
- name: content-type
25+
value: application/grpc
26+
- headers:
27+
- name: content-type
28+
value: application/grpc+proto
29+
backendRefs:
30+
- name: opentelemetry-collector
31+
port: 4317
32+
33+
# OTLP HTTP (4318): default route for HTTP OTLP endpoints like /v1/traces.
34+
- matches:
35+
- path:
36+
type: PathPrefix
37+
value: /
38+
backendRefs:
39+
- name: opentelemetry-collector
40+
port: 4318
41+
{{- end }}

0 commit comments

Comments
 (0)