Build a Custom Collector with the OpenTelemetry Collector Builder
Describe the components you need in a manifest, build a small binary or image, and know when it's worth it.
The prebuilt Collector images are convenient but broad. The contrib distribution contains hundreds of components, most of which you’ll never use, and the core distribution has too few. If you want a smaller binary, a reduced attack surface, or a private component of your own, you can build exactly the Collector you need with the OpenTelemetry Collector Builder (ocb). The input is a single YAML manifest, so the whole process stays config-driven.
When to build your own
- You want only the components you use, for a smaller image and fewer dependencies to patch.
- Security policy requires you to build from source and control the supply chain.
- You need a component that isn’t in any official distribution, such as one written in-house.
If none of these apply, use the official distributions. Building your own means you take on rebuilding when components receive security fixes.
Install the builder
ocb is a Go program released with each Collector version. Download the binary for your platform from the Collector’s GitHub releases page, or install it with Go:
go install go.opentelemetry.io/collector/cmd/builder@v0.163.0
Use the same version for the builder and the components. (The version shown is an example; use a current release.) The Go toolchain must be installed to run a build. Check the installation guide in the OpenTelemetry docs for the exact binary name and download links, because they differ by release.
Write the manifest
# builder-config.yaml
dist:
name: otelcol-custom
description: Custom OpenTelemetry Collector
output_path: ./otelcol-custom
# Optional: the version of the core Collector to build against
# otelcol_version: 0.163.0
receivers:
- gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.163.0
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.163.0
processors:
- gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.163.0
- gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.163.0
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sattributesprocessor v0.163.0
exporters:
- gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.163.0
- gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.163.0
- gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.163.0
extensions:
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.163.0
providers:
- gomod: go.opentelemetry.io/collector/confmap/provider/envprovider v1.0.0
- gomod: go.opentelemetry.io/collector/confmap/provider/fileprovider v1.0.0
Key points:
- Each entry names a Go module and a version (
gomod). Contrib components live undergithub.com/open-telemetry/opentelemetry-collector-contrib/..., and core ones undergo.opentelemetry.io/collector/.... - Component versions must be compatible. Core components, contrib components, and the builder are released together; keep all of them on the same release. Mixing versions causes compile errors.
- Providers decide which config sources are available. If you want
${env:VAR}and${file:/path}to work, includeenvproviderandfileprovider. A binary without them can’t resolve those references. Provider modules use their own version numbers (oftenv1.x), so look them up for the release you build against. - Component module paths and names can change, so copy them from each component’s README or from the contrib distribution’s own manifest rather than from memory.
You can use replaces: to substitute a module with a local fork, and gomod entries can point at your private repositories.
Build
ocb --config builder-config.yaml
# or, if installed with go install:
builder --config builder-config.yaml
The output directory contains generated Go source and a compiled binary, ./otelcol-custom/otelcol-custom. Run it with an ordinary config file and check what is included:
./otelcol-custom/otelcol-custom components # list what was compiled in
./otelcol-custom/otelcol-custom validate --config=config.yaml
./otelcol-custom/otelcol-custom --config=config.yaml
If your config references a component that wasn’t built in, the Collector fails at startup and names it. Add it to the manifest and rebuild.
Package as a container image
A multi-stage Dockerfile builds in a Go image and copies the result into a minimal base:
FROM golang:1.24 AS build
WORKDIR /src
RUN go install go.opentelemetry.io/collector/cmd/builder@v0.163.0
COPY builder-config.yaml .
RUN CGO_ENABLED=0 builder --config builder-config.yaml
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /src/otelcol-custom/otelcol-custom /otelcol-custom
USER nonroot
ENTRYPOINT ["/otelcol-custom"]
CMD ["--config=/etc/otelcol/config.yaml"]
Use a Go version that matches the Collector release’s requirement (check the release notes), and consider pinning images by digest. Build and publish the image in CI, and deploy it the same way as any official image: through the Helm chart (image.repository and image.tag) or the Operator (spec.image).
Note that the Helm chart’s presets assume particular components exist. With a custom image, configure the receivers and processors yourself or confirm that each one the preset needs was included.
Keep it maintainable
- Keep
builder-config.yamlin Git and build in CI, not on laptops. - Rebuild when a new Collector release lands or a security advisory affects a component you use. Renovate or Dependabot can watch the version strings.
- Run
componentsand a smoke test with a representative config in CI, so a missing component is caught before deployment. - Start from the contrib manifest and remove what you don’t use, rather than building up from zero.
Popular Guides
-
OpenTelemetry Explained: SDKs, OTLP, and the Collector Understand the moving parts and the three places configuration lives before you write any YAML. -
The Collector Configuration Model: Components, Pipelines, and Providers Learn the rules of the Collector's YAML: naming, pipelines, connectors, merging files, and environment variables. -
Configure SDKs with OTEL_* Environment Variables Set the service name, exporters, sampling, and limits for any language using standard variables. -
Instrument Apps Without Code Changes: Java, Python, and Node.js Attach OpenTelemetry agents with environment variables and command-line flags only. -
Make the Collector Production-Ready: Memory Limits, Batching, and Retries Configure processors, queues, and persistent storage so telemetry survives overload and outages. -
Deploy the Collector on Kubernetes with Helm Install the official chart, use presets for logs and metrics, and override the config through values files. -
Troubleshoot the Collector and SDKs A systematic checklist for when telemetry doesn't arrive: debug exporter, health checks, internal metrics, and common mistakes.