Skip to content

Custom OTel Collector

Adding a CustomOTelCollector to your namespace gives your application a dedicated OpenTelemetry Collector and automatic instrumentation — with no cluster-admin access required.

When you create a CustomOTelCollector in your namespace, two resources are created alongside it:

ResourceNamePurpose
OpenTelemetryCollector<your-name>Receives, processes, and exports telemetry from your pods
InstrumentationgrpcAuto-instruments Java, .NET, and Go workloads via a pod annotation

The collector is pre-configured with exporters for traces (Tempo), logs (Loki), and optionally Splunk. You only configure what is specific to your application.

Use a CustomOTelCollector when:

  • Your application needs a dedicated OTel pipeline (e.g. custom log filters).
  • You want auto-instrumentation for Java, .NET, or Go without writing OTel SDK code.
  • You need to route logs to Splunk in addition to the default flow pipeline.

If your application has no special pipeline requirements, ask your TABBer whether a shared collector already exists in the namespace.

Add a CustomOTelCollector to your Helm chart and annotate your Deployment.

Create templates/otel.yaml in your Helm chart:

custom-otel-collector-example.yaml
apiVersion: k8s.flow.rws.nl/v1alpha1
kind: CustomOTelCollector
metadata:
name: {{ include "my-app.fullname" . }}-otel
namespace: {{ .Release.Namespace }}
spec: {}

That’s the minimal configuration. Crossplane creates the collector and instrumentation automatically.

2. Enable auto-instrumentation on your Deployment

Section titled “2. Enable auto-instrumentation on your Deployment”

You need to add an annotation to the spec.template.metadata of your Deployment. The annotation name must match the CustomOTelCollector name in the same namespace. If you named it my-app-otel, set the annotation value to my-app-otel:

instrumentation.opentelemetry.io/inject-java: "my-app-otel"

3. Optional — custom log pipelines and processors

Section titled “3. Optional — custom log pipelines and processors”

To add a log filter and route logs to a Splunk instance:

custom-otel-collector-splunk-example.yaml
apiVersion: k8s.flow.rws.nl/v1alpha1
kind: CustomOTelCollector
metadata:
name: {{ include "my-app.fullname" . }}-otel
namespace: {{ .Release.Namespace }}
spec:
extraProcessors:
filter/audit_logs:
error_mode: ignore
logs:
log_record:
- 'not IsMatch(body, ".*AUDIT.*")'
pipelines:
splunk:
extraProcessors:
- filter/audit_logs
flow:
extraProcessors:
- filter/audit_logs

4. Optional — pin auto-instrumentation images

Section titled “4. Optional — pin auto-instrumentation images”

Override the cluster-default instrumentation image per collector:

custom-otel-collector-pin-image-example.yaml
spec:
instrumentation:
grpc:
java:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:2.5.0
FieldTypeDescription
extraProcessorsobjectNamed OTel processors merged into the collector. Keys are processor names, values are processor config.
pipelines.splunk.extraProcessors[]stringProcessor names added to the logs/splunk pipeline. Omit pipelines.splunk to skip this pipeline.
pipelines.flow.extraProcessors[]stringProcessor names added to the logs/flow pipeline. Omit pipelines.flow to skip this pipeline.
instrumentation.grpc.dotnet.imagestringOverride .NET instrumentation image for this collector.
instrumentation.grpc.go.imagestringOverride Go instrumentation image for this collector.
instrumentation.grpc.java.imagestringOverride Java instrumentation image for this collector.