Skip to content

Commit

Permalink
using opentelemetry.io* namespace for extracing resource based on an…
Browse files Browse the repository at this point in the history
…notations from k8s Api #2330  (#3010)

* using opentelemetry.io* namespace for extracing resource

Signed-off-by: Horiodino <[email protected]>

* refactor ReservedNamespace to OtelAnnotationNamespace

Signed-off-by: Horiodino <[email protected]>

* added changelog

Signed-off-by: Horiodino <[email protected]>

* Updated README: using opentelemetry.io* namespace for extracting resource

Signed-off-by: Horiodino <[email protected]>

* Update README.md

Co-authored-by: Mikołaj Świątek <[email protected]>

* Update README.md

Co-authored-by: Mikołaj Świątek <[email protected]>

---------

Signed-off-by: Horiodino <[email protected]>
Co-authored-by: Mikołaj Świątek <[email protected]>
  • Loading branch information
Horiodino and swiatekm committed Aug 7, 2024
1 parent c839f73 commit 2f73582
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 5 deletions.
13 changes: 13 additions & 0 deletions .chloggen/extract-resources-ns.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
change_type: enhancement

component: instrumentation

note: "introduced ability to set Otel resource attributes based on annotations for instrumentation"

issues:
- 2181


subtext: |
resource.opentelemetry.io/your-key: "your-value"
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,25 @@ spec:
EOF
```

### Setting instrumentation resource attributes via namespace annotations

This example shows a pod configuration with OpenTelemetry annotations using the `resource.opentelemetry.io/` prefix. These annotations can be used to add resource attributes to data produced by OpenTelemetry instrumentation.

```yaml
apiVersion: v1
kind: Pod
metadata:
name: example-pod
annotations:
resource.opentelemetry.io/service.name: "my-service"
resource.opentelemetry.io/service.version: "1.0.0"
resource.opentelemetry.io/environment: "production"
spec:
containers:
- name: main-container
image: your-image:tag
```

## Compatibility matrix

### OpenTelemetry Operator vs. OpenTelemetry Collector
Expand Down
11 changes: 6 additions & 5 deletions pkg/constants/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ const (
AnnotationDefaultAutoInstrumentationApacheHttpd = InstrumentationPrefix + "default-auto-instrumentation-apache-httpd-image"
AnnotationDefaultAutoInstrumentationNginx = InstrumentationPrefix + "default-auto-instrumentation-nginx-image"

EnvPodName = "OTEL_RESOURCE_ATTRIBUTES_POD_NAME"
EnvPodUID = "OTEL_RESOURCE_ATTRIBUTES_POD_UID"
EnvPodIP = "OTEL_POD_IP"
EnvNodeName = "OTEL_RESOURCE_ATTRIBUTES_NODE_NAME"
EnvNodeIP = "OTEL_NODE_IP"
EnvPodName = "OTEL_RESOURCE_ATTRIBUTES_POD_NAME"
EnvPodUID = "OTEL_RESOURCE_ATTRIBUTES_POD_UID"
EnvPodIP = "OTEL_POD_IP"
EnvNodeName = "OTEL_RESOURCE_ATTRIBUTES_NODE_NAME"
EnvNodeIP = "OTEL_NODE_IP"
OtelAnnotationNamespace = "resource.opentelemetry.io/"

FlagCRMetrics = "enable-cr-metrics"
FlagApacheHttpd = "enable-apache-httpd-instrumentation"
Expand Down
9 changes: 9 additions & 0 deletions pkg/instrumentation/sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,15 @@ func (i *sdkInjector) createResourceMap(ctx context.Context, otelinst v1alpha1.I
res[string(k)] = v
}
}

for k, v := range pod.GetAnnotations() {
if strings.HasPrefix(k, constants.OtelAnnotationNamespace) {
key := strings.TrimSpace(strings.TrimPrefix(k, constants.OtelAnnotationNamespace))
if _, ok := res[key]; !ok {
res[key] = v
}
}
}
return res
}

Expand Down
106 changes: 106 additions & 0 deletions pkg/instrumentation/sdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,112 @@ func TestSDKInjection(t *testing.T) {
},
},
},
{
name: "Resource attribute propagate",
inst: v1alpha1.Instrumentation{
Spec: v1alpha1.InstrumentationSpec{
Exporter: v1alpha1.Exporter{
Endpoint: "https://collector:4317",
},
Resource: v1alpha1.Resource{
Attributes: map[string]string{
"fromcr": "val",
},
},
Propagators: []v1alpha1.Propagator{"jaeger"},
Sampler: v1alpha1.Sampler{
Type: "parentbased_traceidratio",
Argument: "0.25",
},
},
},
pod: corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"resource.opentelemetry.io/fromtest": "val",
"resource.opentelemetry.io/foo": "test",
},
Namespace: "project1",
Name: "app",
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Image: "app:latest",
Env: []corev1.EnvVar{
{
Name: "OTEL_SERVICE_NAME",
Value: "explicitly_set",
},
{
Name: "OTEL_EXPORTER_OTLP_ENDPOINT",
Value: "explicitly_set",
},
{
Name: "OTEL_PROPAGATORS",
Value: "b3",
},
{
Name: "OTEL_TRACES_SAMPLER",
Value: "always_on",
},
{
Name: "OTEL_RESOURCE_ATTRIBUTES",
Value: "foo=bar,k8s.container.name=other,service.version=explicitly_set,",
},
},
},
},
},
},
expected: corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: "project1",
Name: "app",
Annotations: map[string]string{
"resource.opentelemetry.io/fromtest": "val",
"resource.opentelemetry.io/foo": "test",
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Image: "app:latest",
Env: []corev1.EnvVar{
{
Name: "OTEL_SERVICE_NAME",
Value: "explicitly_set",
},
{
Name: "OTEL_EXPORTER_OTLP_ENDPOINT",
Value: "explicitly_set",
},
{
Name: "OTEL_PROPAGATORS",
Value: "b3",
},
{
Name: "OTEL_TRACES_SAMPLER",
Value: "always_on",
},
{
Name: "OTEL_RESOURCE_ATTRIBUTES_NODE_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "spec.nodeName",
},
},
},
{
Name: "OTEL_RESOURCE_ATTRIBUTES",
Value: "foo=bar,k8s.container.name=other,service.version=explicitly_set,foo=test,fromcr=val,fromtest=val,k8s.namespace.name=project1,k8s.node.name=$(OTEL_RESOURCE_ATTRIBUTES_NODE_NAME),k8s.pod.name=app",
},
},
},
},
},
},
},
}

for _, test := range tests {
Expand Down

0 comments on commit 2f73582

Please sign in to comment.