Skip to main contentSkip to navigationSkip to footer
    Back to Blog

    OpenTelemetry is not hard

    Juraci Paixão Kröhling
    opentelemetryobservabilityopinion
    OpenTelemetry is not hard

    When I asked the community about their pain points with OpenTelemetry, one response kept appearing: "it's complicated." The project has too many components, too many specifications, too much to learn. I understand why people feel this way. But I think the framing is wrong.

    OpenTelemetry is not hard. OpenTelemetry is deep.

    The difference matters. Hard means you struggle to get started. Deep means there is more to discover as you go further. Getting started with OpenTelemetry takes two commands. Mastering every corner of the project takes years. Most people only need something in between.

    Two commands

    Here is a Java application getting full observability. First, download the Java Agent:

    curl -L -o opentelemetry-javaagent.jar \
      https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
    

    Then run your application with the agent attached:

    java -javaagent:opentelemetry-javaagent.jar \
         -Dotel.service.name=spring-petclinic \
         -jar build/libs/spring-petclinic-4.0.0-SNAPSHOT.jar
    

    The application now emits traces, metrics, and logs to localhost:4317 using the OpenTelemetry Protocol (OTLP). Point it at any OTLP-compatible backend and you have observability. For local testing, a single container gives you everything:

    docker run --rm -p 3000:3000 -p 4317:4317 grafana/otel-lgtm:latest
    

    Browse your application at localhost:8080, then check localhost:3000. You will find traces showing HTTP requests flowing through your code, database queries with their durations, and even an N+1 query pattern if your application has one. Metrics and logs are there too. No code changes. No configuration files. Two commands.

    This is not a toy example. The Java Agent instruments dozens of libraries automatically. For many applications, this level of observability is enough to debug production issues, understand performance characteristics, and identify bottlenecks.

    To be fair, Java is one of the most mature implementations in the OpenTelemetry ecosystem. The Java Agent has been battle-tested in production for years, and the auto-instrumentation covers a wide range of frameworks and libraries out of the box. This makes getting started with Java particularly straightforward. The experience can be quite different for other languages. Some SDKs require more manual setup, have fewer auto-instrumentation options, or lack the same level of polish in their tooling. If you are working with Ruby, Rust, or even Python, you might find yourself writing more instrumentation code by hand, or discovering that certain libraries are not yet covered. This is not a criticism of those implementations; OpenTelemetry is a massive undertaking, and not all languages have the same level of community investment. It is simply a reality worth acknowledging.

    The map is not the territory

    If OpenTelemetry is this simple, why do people think it is complicated? Because they see the map before they walk the territory.

    The OpenTelemetry project includes the Collector, the Operator, semantic conventions, the API, the SDK, Weaver, OTLP, eleven language implementations, and dozens of Special Interest Groups (SIGs) working on specific domains. Looking at that list, anyone would feel overwhelmed. But that list represents everything the project offers, not everything you need to use.

    A menu with two hundred items does not mean you have to order two hundred dishes. You pick what you need.

    Problems create components

    Every OpenTelemetry component exists because someone had a specific problem. Understanding which problem each component solves tells you whether you need it.

    The Java Agent we used above sends telemetry directly to a backend. This works fine until you have hundreds of services and want to change your backend. Updating hundreds of deployments to point at a new endpoint is painful. The OpenTelemetry Collector solves this: it acts as a gateway between your applications and your backends. Applications send to the Collector; the Collector sends to the backend. Change the backend, update one place. If you have five services and a stable backend, you do not need a Collector.

    The Collector requires configuration and deployment. On Kubernetes, the OpenTelemetry Operator simplifies this by managing Collectors through Custom Resource Definitions (CRDs). It can also inject the Java Agent into your workloads automatically. If you are not on Kubernetes, or you have twenty services and a working deployment script, you do not need the Operator.

    Auto-instrumentation captures common operations, but sometimes you need to record business-specific data. The OpenTelemetry API lets you create custom spans and metrics. If auto-instrumentation covers your needs, you do not need to learn the API.

    Different languages should use consistent attribute names so you can query across services. Semantic conventions define those names. Auto-instrumentation already follows them. You only care about semantic conventions when you add custom instrumentation or query data across polyglot services.

    Large organizations find that different teams instrument the same concepts differently. "team" versus "squad", "org" versus "organization", "cluster.name" versus "cluster_name". Weaver lets you define and enforce your own conventions. If you have three services and five engineers, you do not need Weaver.

    Each component is an answer to a question. If you are not asking the question, you do not need the answer.

    Why OpenTelemetry cannot be smaller

    Some specialized tools are simpler because they make decisions OpenTelemetry cannot make. The Prometheus client library, for example, has excellent performance for metrics. But using it commits you to Prometheus-compatible backends at instrumentation time. You also need a separate solution for traces.

    OpenTelemetry optimizes for flexibility. Some backends expect cumulative metrics, others expect deltas. Some thrive on high-cardinality data, others choke on it. OpenTelemetry works with all of them. The cost of that flexibility is that OpenTelemetry cannot take shortcuts that assume a specific backend.

    This is a trade-off, not a flaw. If you know your backend will never change and you need maximum performance for one signal type, a specialized library might serve you better. If you want one instrumentation approach that works everywhere and gives you options, OpenTelemetry is the answer.

    A framework that grows with you

    Most teams follow a similar progression. Auto-instrumentation comes first, providing immediate visibility without code changes. The exporter points directly at a backend, and telemetry starts flowing.

    As the number of services grows, the Collector enters the picture. It decouples applications from backend decisions and centralizes concerns like sampling, enrichment, and routing. Teams running on Kubernetes often adopt the Operator next, automating agent injection and Collector management across the cluster.

    Custom instrumentation arrives when auto-instrumentation cannot capture business-specific operations. The API provides the primitives; semantic conventions provide the vocabulary. At enterprise scale, tools like Weaver enforce consistency across teams that would otherwise drift apart.

    The framework meets you where you are and offers more when you need it.

    Summary

    OpenTelemetry has many components because observability has many problems. Not everyone has all the problems, and not everyone has the same problems. The project gives you tools to solve the problems you have and leaves the rest on the shelf.

    Getting started is two commands. The Java Agent, or equivalent auto-instrumentation for other languages, provides meaningful observability with no code changes. From there, you add components as needs arise: a Collector for backend flexibility, the API for custom instrumentation, the Operator for Kubernetes scale, Weaver for organizational consistency.

    The project is deep, not hard. You do not need to learn everything before you start. You need to start, and learn what you need as you go.

    We use analytics cookies to improve our website and understand how you use it. You can accept analytics cookies or decline to use only essential cookies.