<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Code and ops in simple words]]></title><description><![CDATA[Well wxplained infrastructure and coding topics]]></description><link>https://elenanur.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 01:29:23 GMT</lastBuildDate><atom:link href="https://elenanur.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to send cross-service OpenTelemetry traces from Python to Jaeger: end-to-end setup with Docker Compose]]></title><description><![CDATA[In this tutorial, you will

Create a local OpenTelemetry collector and Jaeger setup using Docker Compose

Build a Python Flask Server Application and instrument it with OpenTelemetry

Build a Python HTTP Client Application and instrument it with Open...]]></description><link>https://elenanur.dev/how-to-send-cross-service-opentelemetry-traces-from-python-to-jaeger-end-to-end-setup-with-docker-compose</link><guid isPermaLink="true">https://elenanur.dev/how-to-send-cross-service-opentelemetry-traces-from-python-to-jaeger-end-to-end-setup-with-docker-compose</guid><category><![CDATA[OpenTelemetry]]></category><category><![CDATA[tracing]]></category><category><![CDATA[Python 3]]></category><dc:creator><![CDATA[Elena Nur]]></dc:creator><pubDate>Fri, 28 Nov 2025 17:28:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/GM9Xpgb0g98/upload/c37372c045172d5ada9c7e857449e2df.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this tutorial, you will</p>
<ul>
<li><p>Create a local OpenTelemetry collector and <a target="_blank" href="https://www.jaegertracing.io/">Jaeger</a> setup using Docker Compose</p>
</li>
<li><p>Build a Python Flask Server Application and instrument it with OpenTelemetry</p>
</li>
<li><p>Build a Python HTTP Client Application and instrument it with OpenTelemetry</p>
</li>
<li><p>Learn how to use context propagation to traces cross-service requests</p>
</li>
<li><p>Trace your cross-service requests in Jaeger</p>
</li>
</ul>
<h2 id="heading-tools-we-will-use">Tools we will use</h2>
<p><strong>Jaeger</strong> is an open-source distributed tracing platform. In this tutorial, we will use a version that contains all components in a single Docker image. It will enable a fast and convenient way to display distributed traces on a local machine.</p>
<p><strong>Docker Compose</strong> is a tool for defining and running multi-container applications. It allows us to describe all Docker images in a single configuration file, making it handy for local testing.</p>
<p>We use <strong>OpenTelemetry Collector</strong> to forward traces from the Python applications to Jaeger. In this case, we could manage without it, however, the OpenTelemetry Collector is useful, for example, if you want to enrich data, or collect not only traces but also metrics, or experiment with different vendors.</p>
<h2 id="heading-pre-requisites">Pre-requisites</h2>
<p>We will use the Unix command interface. If you use Windows, you can use <a target="_blank" href="https://learn.microsoft.com/en-us/windows/wsl/install">WSL</a>.</p>
<p>Install the following programs if you don’t have them</p>
<ol>
<li><p><a target="_blank" href="https://docs.docker.com/compose/install/">Docker Compose</a></p>
</li>
<li><p><a target="_blank" href="https://pythongeeks.org/python-3-installation-and-setup-guide/">Python3</a> and <a target="_blank" href="https://pip.pypa.io/en/stable/installation/">pip</a></p>
</li>
</ol>
<h2 id="heading-set-up-jaeger-and-opentelemetry-collector-using-docker-compose">Set up Jaeger and OpenTelemetry Collector using Docker Compose</h2>
<ol>
<li><p>Create Collector config file</p>
<pre><code class="lang-bash"> cat &gt; otel-collector-config.yaml &lt;&lt; <span class="hljs-string">'EOF'</span>
 receivers:
   otlp:
     protocols:
       grpc:
         endpoint: 0.0.0.0:4317
 processors:
 extensions:
   health_check: {}
 exporters:
   otlp:
     endpoint: jaeger:4317
     tls:
       insecure: <span class="hljs-literal">true</span>
 service:
   pipelines:
     traces:
       receivers: [otlp]
       exporters: [otlp]
 EOF
</code></pre>
</li>
<li><p>Create a Docker compose file</p>
<pre><code class="lang-bash"> cat &gt; docker-compose.yaml &lt;&lt; <span class="hljs-string">'EOF'</span>
 services:
   otel-collector:
     image: otel/opentelemetry-collector-contrib:latest
     <span class="hljs-built_in">command</span>: [<span class="hljs-string">"--config=/etc/otel-collector-config.yaml"</span>]
     volumes:
       - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
     ports:
       - <span class="hljs-string">"4317:4317"</span> <span class="hljs-comment"># OTLP gRPC receiver</span>
   jaeger:
     image: jaegertracing/all-in-one:latest
     ports:
       - <span class="hljs-string">"6831:6831/udp"</span> <span class="hljs-comment"># UDP port for Jaeger agent</span>
       - <span class="hljs-string">"16686:16686"</span> <span class="hljs-comment"># Web UI</span>
       - <span class="hljs-string">"14268:14268"</span> <span class="hljs-comment"># HTTP port for spans(venv)</span>
 EOF
</code></pre>
</li>
<li><p>Start Docker Compose:</p>
<pre><code class="lang-bash"> docker compose -f docker-compose.yaml up
</code></pre>
</li>
<li><p>Verify that the local Jaeger instance works: open <a target="_blank" href="http://localhost:16686/">http://localhost:16686/</a> in your browser.</p>
</li>
</ol>
<h2 id="heading-create-a-virtual-environment-and-install-python-libraries">Create a virtual environment and install Python libraries</h2>
<ol>
<li><p>Create and activate a virtual environment</p>
<pre><code class="lang-bash"> python3 -m venv venv
 <span class="hljs-built_in">source</span> ./venv/bin/activate
</code></pre>
</li>
<li><p>Install python packages</p>
<pre><code class="lang-bash"> pip install flask
 pip install urllib3
</code></pre>
</li>
<li><p>Install OpenTelemetry instrumentation</p>
<pre><code class="lang-bash"> pip install opentelemetry-distro
 opentelemetry-bootstrap -a install
 pip install opentelemetry-exporter-otlp-proto-grpc <span class="hljs-comment"># send traces over OTLP</span>
 pip install opentelemetry-instrumentation-urllib3 <span class="hljs-comment"># instrumentation for urllib3 library</span>
</code></pre>
<h2 id="heading-instrument-a-cross-server-request">Instrument a cross-server request</h2>
<ol>
<li><p>Create a simple Flask server application. It will serve HTTP requests.</p>
<p> ```bash
 mkdir server
 cat &gt; server/app.py &lt;&lt; 'EOF'
 from flask import Flask, jsonify</p>
<p> app = Flask(<strong>name</strong>)</p>
<p> @app.route('/example1/')
 def trace(arg):
     return jsonify({"trace": f"Trace argument is {arg}"})</p>
</li>
</ol>
</li>
</ol>
<p>        if <strong>name</strong> == "<strong>main</strong>":
            app.run(host="0.0.0.0", port=8080, debug=True)
        EOF</p>
<pre><code>
    <span class="hljs-number">2.</span> Start the Flask server application <span class="hljs-keyword">with</span> OpenTelemetry instrumentation

        <span class="hljs-string">``</span><span class="hljs-string">`bash
        cd server &amp;&amp; \
        opentelemetry-instrument \
          --service_name demo-server \
          --metrics_exporter none \
          --logs_exporter none \
          flask run -p 8080</span>
</code></pre><ol start="3">
<li><p>Verify that your Flask application works: open <a target="_blank" href="http://localhost:8080/example1/test">http://localhost:8080/example1/test</a> in your browser</p>
</li>
<li><p>Create a simple client application. We will use <code>urllib3</code> to make HTTP requests and <code>URLLib3Instrumentor</code> for OpenTelemetry instrumentation. Create a file <code>simple-client.py</code> with following content</p>
<pre><code class="lang-python"> <span class="hljs-keyword">import</span> urllib3
 <span class="hljs-keyword">from</span> opentelemetry.instrumentation.urllib3 <span class="hljs-keyword">import</span> URLLib3Instrumentor

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">strip_query_params</span>(<span class="hljs-params">url: str</span>) -&gt; str:</span>
     <span class="hljs-keyword">return</span> url.split(<span class="hljs-string">"?"</span>)[<span class="hljs-number">0</span>]

 URLLib3Instrumentor().instrument(
     <span class="hljs-comment"># Remove all query params from the URL attribute on the span.</span>
     url_filter=strip_query_params,
 )

 http = urllib3.PoolManager()
 response = http.request(<span class="hljs-string">"GET"</span>, <span class="hljs-string">"http://localhost:8080/example1/test"</span>)

 <span class="hljs-keyword">if</span> response.status == <span class="hljs-number">200</span>:
     print(<span class="hljs-string">"Response:"</span>, response.json())
 <span class="hljs-keyword">else</span>:
     print(<span class="hljs-string">"Error:"</span>, response.status_code)
</code></pre>
</li>
<li><p>Run the client application</p>
<pre><code class="lang-bash"> opentelemetry-instrument \
   --service_name demo-client \
   --metrics_exporter none \
   --logs_exporter none \
 python simple-client.py
</code></pre>
</li>
<li><p>Verify the results in Jaeger: open <a target="_blank" href="http://localhost:16686/">http://localhost:16686/</a>, choose “demo-client” in the field <em>Service</em> in the left panel, and click “Find Traces</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764350302905/c325ee2c-6be7-4506-9a66-7bb160346d55.png" alt class="image--center mx-auto" /></p>
<p> Now, you should see cross-service traces in the search results. When you open a trace, you can see how much time it took at each stage:</p>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764350441340/2bb3486d-78e9-4051-a0cf-44785289fd76.png" alt class="image--center mx-auto" /></p>
<p>    Congratulations! You’ve just implemented your first cross-service trace in OpenTelemetry.</p>
<h2 id="heading-clean-up">Clean up</h2>
<p>It is the optional step if you want to clean up the environment on your machine.</p>
<ol>
<li><p>Clean up the Python virtual environment</p>
<pre><code class="lang-bash"> deactivate
 rm -rf venv/
</code></pre>
</li>
<li><p>Shut down Docker Compose components</p>
<pre><code class="lang-bash"> docker compose -f docker-compose.yaml down
</code></pre>
</li>
</ol>
<h2 id="heading-tip">Tip</h2>
<p>Prefer instrumented Python libraries to generate telemetry data. For example, we used the instrumented library <code>urllib3</code> to produce the traces rather than manually instrumenting with OpenTelemetry in this tutorial. You can find the full list of instrumented libraries <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Metrics in OpenTelemetry for beginners: easily explained]]></title><description><![CDATA[This document is an introduction to Metrics in OpenTelemetry for beginners. It briefly explains what metrics are in the context of OpenTelemetry, describes the types of metrics in OpenTelemetry,  and outlines their lifecycle from generation to export...]]></description><link>https://elenanur.dev/metrics-in-opentelemetry-for-beginners-easily-explained</link><guid isPermaLink="true">https://elenanur.dev/metrics-in-opentelemetry-for-beginners-easily-explained</guid><category><![CDATA[Devops]]></category><category><![CDATA[OpenTelemetry]]></category><category><![CDATA[open source]]></category><category><![CDATA[metrics]]></category><dc:creator><![CDATA[Elena Nur]]></dc:creator><pubDate>Mon, 03 Nov 2025 11:00:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/qwtCeJ5cLYs/upload/e8d04e340e9c6ab7c8123dc8f55c09c5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This document is an introduction to Metrics in OpenTelemetry for beginners. It briefly explains what metrics are in the context of OpenTelemetry, describes the types of metrics in OpenTelemetry,  and outlines their lifecycle from generation to export to a metric storage, such as Prometheus, InfluxDB, and many others.</p>
<h2 id="heading-what-is-opentelemetry">What is OpenTelemetry</h2>
<p><strong>OpenTelemetry</strong> is an observability framework for generating and delivering telemetry data, such as metrics, logs, and traces, to an Observability storage.</p>
<h2 id="heading-benefits-of-using-opentelemetry-for-metrics">Benefits of using OpenTelemetry for metrics</h2>
<p>When you build an OpenTelemetry infrastructure for metrics, you can enjoy the following benefits:</p>
<ul>
<li><p>Support of multiple programming languages</p>
</li>
<li><p>Easy integration with different <strong>metric backends</strong> (storages)</p>
</li>
<li><p>Flexibility across environments — Kubernetes, clouds, and bare metal</p>
</li>
<li><p><strong>Unified</strong> infrastructure for metrics, logs, and traces</p>
</li>
</ul>
<h2 id="heading-what-is-a-metric">What is a metric?</h2>
<p><strong>A metric</strong> is a <a target="_blank" href="https://en.wikipedia.org/wiki/Time_series">time-series</a> measure of a process or a state within software. Engineers use metrics to monitor software health, performance, and business efficiency.</p>
<h2 id="heading-what-kind-of-metrics-exist-in-opentelemetry">What kind of metrics exist in OpenTelemetry?</h2>
<h3 id="heading-gauge">Gauge</h3>
<p>A Gauge is an instantaneous snapshot of data at each point in time.</p>
<p>For example, it can be the number of processes on the machine or the CPU temperature.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761927806478/a6d857d5-3862-4e6d-9c27-20bb581f4ec0.png" alt="Metrics in OpenTelemetry for beginners: easily explained gauge metrics" class="image--center mx-auto" /></p>
<h3 id="heading-sum">Sum</h3>
<p>Sum is a numeric metric that represents the cumulative total of all reported measurements over a time interval or a cumulative value from the beginning of time. For example, it can be the total amount of requests served by a service in a minute (1), or a cumulative value of requests from the start (2).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761928612249/f56e07ba-2aa1-4f18-b416-2c6d4a2177d1.png" alt="Metrics in OpenTelemetry for beginners: easily explained Sum metric" class="image--center mx-auto" /></p>
<h3 id="heading-histogram">Histogram</h3>
<p>A histogram describes a distribution of metric values grouped into buckets, where each bucket represents a range of values and the count of measurements that fell into that range.  For example, buckets can represent server request latency intervals, and values - the count of requests that fall in the bucket.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761927888755/461af78c-d641-4e28-91ef-b77c8ea8271c.png" alt="Metrics in OpenTelemetry: easily explained - Histogram" class="image--center mx-auto" /></p>
<p>Each metric in OpenTelemetry contains the following information:</p>
<ul>
<li><p><strong>Metric name</strong></p>
</li>
<li><p><strong>Attributes</strong> - these can be a name of the application that produced a metric, an availability zone, the name of the server, the instrumentation name, and many others</p>
</li>
<li><p><strong>Value type</strong> of the point (integer, floating point, etc.)</p>
</li>
<li><p><strong>Unit of measurement</strong></p>
</li>
<li><p><strong>Points at each time interval</strong></p>
</li>
</ul>
<p>Read more about the Metrics data model in OpenTelemetry in the official <a target="_blank" href="https://opentelemetry.io/docs/specs/otel/metrics/data-model">documentation</a>.</p>
<h2 id="heading-how-the-opentelemetry-metrics-pipeline-works">How the OpenTelemetry metrics pipeline works</h2>
<p>Let’s look at the metrics lifecycle within the Observability framework.</p>
<p><img alt="Metrics in OpenTelemetry for beginners: easily explained - data flow" class="image--center mx-auto" /></p>
<ol>
<li><h3 id="heading-metrics-generation">Metrics generation</h3>
</li>
</ol>
<p>Typically, your application needs to generate metrics. To do that, you can use a corresponding <strong>OpenTelemetry SDK</strong> – a set of tools for generating telemetry data and sending it to the OpenTelemetry Collector.</p>
<ol start="2">
<li><h3 id="heading-metrics-collection">Metrics collection</h3>
</li>
</ol>
<p>The next step is exporting metrics to the <a target="_blank" href="https://opentelemetry.io/docs/collector/">OpenTelemetry collector</a>. OpenTelemetry Collector can collect telemetry data from multiple applications and process it all together. This step is not necessary - the application can send metrics directly to the Metrics Backend, especially if you are just trying it out.</p>
<ol start="3">
<li><h3 id="heading-processing-in-the-collector">Processing in the collector</h3>
</li>
</ol>
<p>OpenTelemetry Collector can <a target="_blank" href="https://opentelemetry.io/docs/collector/transforming-telemetry/">transform metrics</a> before sending them to the Metrics backend. Transformation involves filtering, adding, or deleting attributes, as well as renaming metrics. You can write <a target="_blank" href="https://opentelemetry.io/docs/collector/building/">your own processor</a> if you have a specific need.</p>
<ol start="4">
<li><h3 id="heading-export-to-the-backend">Export to the Backend</h3>
</li>
</ol>
<p>Finally, OpenTelemetry Collector exports your metrics to the Metrics Backend.</p>
<details><summary>Note</summary><div data-type="detailsContent">This is a simplified architecture. In real-world scenarios, the data pipeline might include multiple collectors, such as Kafka.</div></details>

<h2 id="heading-how-opentelemetry-instrumentation-generates-metrics">How OpenTelemetry instrumentation generates Metrics</h2>
<h3 id="heading-for-the-server-application">For the server application</h3>
<p>The exact options for generating metrics depend on the chosen programming language, but the OpenTelemetry community maintains a unified approach. <strong>Opentelemetry instrumentation</strong> is a set of libraries, SDKs, and API for generating metrics and other telemetry data.</p>
<p>Two kinds of instrumentation are generally available:</p>
<ul>
<li><p><strong>Code instrumentation</strong>. Check the development status and availability for your language <a target="_blank" href="https://opentelemetry.io/docs/languages/#status-and-releases">here</a>.</p>
</li>
<li><p><strong>Zero-code</strong> <strong>instrumentation</strong>. For some programming languages, you can instrument your application without touching the code. Check the availability of zero-code instrumentation for your language <a target="_blank" href="https://opentelemetry.io/docs/zero-code/">here</a>. It means that once Zero-code instrumentation is configured, some common use-case metrics work out of the box, and it can also mean that you can use a metric-generation library integrated with OpenTelemetry to produce OpenTelemetry metrics. An example of such a library is <a target="_blank" href="https://micrometer.io/">Java Micrometers</a>.</p>
</li>
</ul>
<p>In a generic scenario, instrumentation generates metrics and other telemetry data and sends them to the OpenTelemetry collector using the <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-proto/tree/main/docs">OpenTelemetry (OTLP) protocol</a>. At this stage, metrics contain information, defined in the <a target="_blank" href="https://opentelemetry.io/docs/specs/otel/metrics/data-model/#opentelemetry-protocol-data-model">OpenTelemetry data model</a>.</p>
<p>OpenTelemetry instrumentation has flexible configuration options; in most cases, it utilizes environment variables that follow the same naming specifications across multiple programming languages. Check the <a target="_blank" href="https://opentelemetry.io/docs/specs/otel/protocol/exporter/">OpenTelemetry Exporter Configuration</a> and <a target="_blank" href="https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/">Environment variable specification</a> to find out more.</p>
<h3 id="heading-other-platforms">Other platforms</h3>
<p>OpenTelemetry also has a set of instrumentations for specific platforms, which don’t run as a server application, such as:</p>
<ul>
<li><p><a target="_blank" href="https://opentelemetry.io/docs/platforms/faas/">AWS lambda</a></p>
</li>
<li><p><a target="_blank" href="https://opentelemetry.io/docs/platforms/kubernetes/">Kubernetes infrastructure</a></p>
</li>
<li><p><a target="_blank" href="https://opentelemetry.io/docs/platforms/client-apps/">Client-side application</a></p>
</li>
</ul>
<h2 id="heading-how-opentelemetry-collector-collects-metrics">How OpenTelemetry collector collects Metrics</h2>
<p>OpenTelemetry Collector collects metrics from multiple applications. The canonical approach is to collect telemetry data using <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver"><code>otlpreceiver</code></a> via the <strong>OTLP protocol</strong>, mentioned earlier; however, in principle, it can collect metrics in any format if a corresponding receiver exists.</p>
<p>An example of such a receiver is <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/prometheusreceiver">Prometheus-Receiver</a>. Instead of instrumenting your application, you can implement the exposure of Prometheus metrics in it, and configure the OpenTelemetry collector to collect these Prometheus metrics via the Prometheus protocol. Several receivers exist in the <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver">opentelemetry-collector-contrib</a> repository, and you can also implement your own receiver if needed.</p>
<h2 id="heading-how-opentelemetry-collector-processes-metrics">How OpenTelemetry collector processes Metrics</h2>
<p>The OpenTelemetry collector can transform metrics using <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor">processors</a>.</p>
<p>Some useful processors include:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/k8sattributesprocessor">k8sattributesprocessor</a>: enrich telemetry data with Kubernetes information, such as cluster name, region, deployment name, etc.</p>
</li>
<li><p><a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/filterprocessor">filterprocessor</a>: filter out incorrect data</p>
</li>
<li><p><a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/attributesprocessor">attributeprocessor</a>: add, rename, and delete metric attributes</p>
</li>
</ul>
<p>You can also write a custom processor if you have specific needs.</p>
<h2 id="heading-destinations-where-metrics-can-be-exported">Destinations where metrics can be exported</h2>
<p>An OpenTelemetry collector can write metrics into any metric storage that supports OTLP format, such as. But, as always, it is not limited to that. It can export data in any format if a corresponding processor exists.</p>
<p>Example of metric exporters:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/prometheusremotewriteexporter">prometheusremotewriteexporter</a>: can write metrics to a storage that supports the Prometheus Remote Write protocol, such as Uptrace, VictoriaMetrics, Thanos, and others</p>
</li>
<li><p><a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/influxdbexporter">influxdbexporter</a>: write metrics to InfluxDb</p>
</li>
<li><p><a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/clickhouseexporter">clickhoseexporter</a>: write metrics to clickhouse</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This is a brief overview of how metrics work in OpenTelemetry, and you are now ready to try it out in real- world scenarios. Do you plan to set up OpenTelemetry Collector in production? Learn <a target="_blank" href="https://elenanur.dev/how-to-choose-the-opentelemetry-collector-distribution">how to choose the OpenTelemetry collector distribution</a></p>
]]></content:encoded></item><item><title><![CDATA[How to choose the OpenTelemetry collector distribution]]></title><description><![CDATA[Choosing the right distribution is crucial for optimizing the use of system resources and building a robust OpenTelemetry pipeline. In this post, we will explore in detail what OTEL distribution is, its architecture, and the principles to consider wh...]]></description><link>https://elenanur.dev/how-to-choose-the-opentelemetry-collector-distribution</link><guid isPermaLink="true">https://elenanur.dev/how-to-choose-the-opentelemetry-collector-distribution</guid><category><![CDATA[OpenTelemetry]]></category><category><![CDATA[opentelemetry collector]]></category><category><![CDATA[architecture]]></category><category><![CDATA[distribution]]></category><category><![CDATA[observability]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Elena Nur]]></dc:creator><pubDate>Mon, 06 Oct 2025 11:28:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/pKeF6Tt3c08/upload/f0e577fe4c83e7f4915006d7b38a285f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Choosing the right distribution is crucial for optimizing the use of system resources and building a robust OpenTelemetry pipeline. In this post, we will explore in detail <strong>what OTEL distribution is</strong>, <strong>its architecture</strong>, and <strong>the principles to consider when selecting the distribution</strong> for your purpose. We will also look at the pros and cons of building a custom distribution.</p>
<p>Before understanding the logic of distributions, let’s revisit the architecture of the OpenTelemetry collector. Feel free to skip this section if you are already familiar with it.</p>
<h1 id="heading-architecture-of-the-opentelemetry-collector">Architecture of the OpenTelemetry Collector</h1>
<p>The primary purpose of the collector is to receive, process, and export OpenTelemetry data (also referred to as <a target="_blank" href="https://opentelemetry.io/docs/concepts/signals/">signals</a>) into the pipeline. The collector achieves these goals by combining components for:</p>
<ul>
<li><h3 id="heading-receiving-data">Receiving data</h3>
</li>
</ul>
<p>A collector can receive data from various sources, such as another Opentelemetry Collector, application <a target="_blank" href="https://opentelemetry.io/docs/concepts/instrumentation/">Opentelemetry instrumentation</a>, Kafka queue, and many others, by using corresponding components.</p>
<ul>
<li><h3 id="heading-processing-data">Processing data</h3>
</li>
</ul>
<p>Between receiving and exporting data, a collector can process it using various <a target="_blank" href="https://opentelemetry.io/docs/collector/transforming-telemetry/">processors</a>. For example, it can enrich the data with <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/attributesprocessor">attributeprocessor</a>, sample data with <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/tailsamplingprocessor">tailingsampleprocessor</a>, combine data into batches with <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/batchprocessor">batchprocessors</a> for optimizing performance, and much more.</p>
<ul>
<li><h3 id="heading-exporting-data">Exporting data</h3>
</li>
</ul>
<p>Similarly to receiving data, an OpenTelemetry Collector can use various components for sending data to multiple destinations, such as another collector, Observability Backend, Kafka, and more.</p>
<ul>
<li><h3 id="heading-additional-purposes">Additional purposes</h3>
</li>
</ul>
<p>Additionally, a collector can utilize <a target="_blank" href="https://opentelemetry.io/docs/collector/building/connector/">connectors</a> to connect multiple pipelines and <a target="_blank" href="https://opentelemetry.io/docs/collector/building/authenticator-extension/">extensions</a> for features that do not directly relate to data processing. We will not discuss them in this manual, but the logic of using them is the same as for other components.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759748661374/1eba0984-4bea-4d7d-91fa-38f1c72891fd.png" alt class="image--center mx-auto" /></p>
<p>You can configure pipelines in OTEL Collector by combining multiple receivers, processors, and exporters, as shown in the diagram above. Within a single collector, you have the flexibility to use <strong>any number of components</strong> to create <strong>multiple pipelines</strong>, as long as these components are <strong>part of the collector build</strong>.</p>
<blockquote>
<p><em>For example, you can create a pipeline inside the OpenTelemetry collector, which</em></p>
<ol>
<li><p><em>Receives traces from applications over the</em> <a target="_blank" href="https://opentelemetry.io/docs/specs/otel/protocol/"><em>OTLP protocol</em></a> <em>using</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver"><em>otlpreceiver</em></a></p>
</li>
<li><p><em>Enriches them with attributes from the Kubernetes cluster using</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/k8sattributesprocessor"><em>k8sattributesprocessor</em></a></p>
</li>
<li><p><em>Samples them based on probability using</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/probabilisticsamplerprocessor"><em>probalisticsampleprocessor</em></a></p>
</li>
<li><p><em>Combines in batches using</em>  <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/batchprocessor"><em>batchprocessor</em></a></p>
</li>
<li><p><em>And exports results to Elastic backend using</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/elasticsearchexporter"><em>elasticsearchexporter</em></a></p>
</li>
</ol>
<p><em>In the same collector, you can create another pipeline, which</em></p>
<ol>
<li><p><em>Reads Kubernetes logs using</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/k8slogreceiver"><em>k8slogreceiver</em></a></p>
</li>
<li><p><em>Enriches them with attributes from the Kubernetes cluster using</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/k8sattributesprocessor"><em>k8sattributesprocessor</em></a></p>
</li>
<li><p><em>Sample them based on probability using</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/probabilisticsamplerprocessor"><em>probalisticsampleprocessor</em></a></p>
</li>
<li><p><em>Combine in batches using</em>  <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/batchprocessor"><em>batchprocessor</em></a></p>
</li>
<li><p><em>And exports results to Elastic backend using</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/elasticsearchexporter"><em>elasticsearchexporter</em></a></p>
</li>
</ol>
<p><em>For such a case,  the collector build must include</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver"><em>otlpreceiver</em></a><em>,</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/k8slogreceiver"><em>k8slogreceiver</em></a><em>,</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/k8sattributesprocessor"><em>k8sattributesprocessor</em></a><em>,</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/probabilisticsamplerprocessor"><em>probalisticsampleprocessor</em></a><em>,</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/batchprocessor"><em>batchprocessor</em></a><em>, and</em> <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/elasticsearchexporter"><em>elasticsearchexporter</em></a><em>, with minimal possible overhead.</em></p>
</blockquote>
<p>The OTEL community and third-party vendors maintain a wide range of components that, when assembled, form <strong>a distribution</strong>.</p>
<h1 id="heading-what-is-a-distribution">What is a distribution?</h1>
<p>The OpenTelemetry community defines a distribution as:</p>
<p><em>A distribution is a customized version of an OpenTelemetry component. A distribution is a wrapper around an upstream OpenTelemetry repository with some customizations.</em></p>
<p>Put simply, the distribution is a customized version of the OpenTelemetry collector, which may include:</p>
<ul>
<li><p>a custom set of components,</p>
</li>
<li><p>custom default settings,</p>
</li>
<li><p>additional tests,</p>
</li>
<li><p>performance tunings,</p>
</li>
<li><p>and <a target="_blank" href="https://opentelemetry.io/docs/concepts/distributions/">a few other specifics</a>.</p>
</li>
</ul>
<p>The central part of a distribution is the set of included components. Common components are typically located in the <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib">otel-collector-contrib</a> and <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector">opentelemetry collector</a> repositories, while vendor-specific ones may reside in third-party repositories. The distribution pulls the required ones from any of the available repositories, as demonstrated in the diagram below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759748418675/f9968000-1e20-4adb-8fa5-78d3c29da357.png" alt class="image--center mx-auto" /></p>
<p>More components in distribution means <strong>more available features to use</strong>, but, at the same time, including excessive components <strong>increases the binary size</strong>, which leads to higher resource consumption and increased security risks. Therefore, the ideal distribution should include <strong>the minimum amount of excessive components</strong>.</p>
<p>When deciding on the OpenTelemetry distribution for your organization, you have a few options:</p>
<ul>
<li><p>Use one of the pre-built OpenTelemetry community distributions</p>
</li>
<li><p>Use third-party distribution maintained by Vendors</p>
</li>
<li><p>Build a custom collector</p>
</li>
</ul>
<p>Let’s examine each option in detail.</p>
<h1 id="heading-opentelemetry-community-distributions">Opentelemetry community distributions</h1>
<p>The OpenTelemetry community maintains <a target="_blank" href="https://opentelemetry.io/docs/collector/distributions/">a few pre-built distributions</a>. It means that the community owns the building pipeline and version releases.</p>
<ul>
<li><h2 id="heading-opentelemetry-collector-contrib-distro">OpenTelemetry collector contrib distro</h2>
</li>
</ul>
<p>This distribution contains <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol-contrib/manifest.yaml">all</a> the components from both the <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib">otel-collector-contrib</a> and <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector">opentelemetry collector</a> repositories. It provides a convenient way to explore the full range of features with minimal effort, but it may be too resource-intensive for production. Generally, the OpenTelemetry community <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol-contrib/README.md#recommendation">does not recommend</a> the otel collector contrib distro for real-time use.</p>
<ul>
<li><h2 id="heading-opentelemetry-collector-core-distribution">Opentelemetry collector core distribution</h2>
</li>
</ul>
<p>This distribution is a ‘<a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol/README.md">classic</a>’ distribution. It includes the compact set of components to work with OTLP protocol, Kafka, Zipkin, Prometheus, Jaeger, and a few other features.</p>
<blockquote>
<p><strong>Example</strong>. The collector pipeline, when core distribution <strong>may be a fit</strong>:</p>
<p><em>The collector collects Metrics and traces via OTLP, enriches them with additional attributes, applies probabilistic sampling, and exports to Kafka. Additionally, it may export metrics to Prometheus-based metrics storage and traces to Jaeger.</em></p>
<p><em>If the collector also needs to collect</em> <strong><em>events from the Kubernetes API</em></strong>*, the Otel collector core distro* <strong><em>won’t fit</em></strong>*.*</p>
</blockquote>
<ul>
<li><h2 id="heading-opentelemetry-collector-ebpf-profiling-distribution">Opentelemetry Collector EBPF profiling distribution</h2>
</li>
</ul>
<p>The goal of this distribution is to collect data about processes running on the system. It contains a limited set of <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol-ebpf-profiler/manifest.yaml">components</a> for collecting K8s metadata, EBPF data, and exporting them to a file or via OTLP.</p>
<blockquote>
<p><strong>Example</strong>. The collector pipeline, when EBPF profiling distribution <strong>may be a fit</strong>:</p>
<p><em>The collector runs on a Kubernetes node, collects EBPF data, enriches it with k8s attributes, and sends it via OTLP to another OTLP collector. But you can’t include components for collecting metrics or traces via OTLP.</em></p>
</blockquote>
<ul>
<li><h2 id="heading-opentelemetry-collector-kubernetes-distro">Opentelemetry Collector Kubernetes distro</h2>
</li>
</ul>
<p>This is the distribution optimized for Kubernetes. It contains components to collect information from journald, K8s events, fluentd, OTLP, and others. It also includes a few basic exporters, such as <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector/tree/main/exporter/otlpexporter">OTLP exporter</a>, <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/fileexporter">fileexporter</a>, <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/loadbalancingexporter">load balancer exporter</a>. The full list of components is available in the <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol-k8s/manifest.yaml">manifest</a>.</p>
<blockquote>
<p><strong>Example</strong>. The collector pipeline, when the Kubernetes distro <strong>may be a fit</strong>:</p>
<p><em>The collector collects Metrics, traces, and logs via OTLP, enriches them with Kubernetes attributes, applies probabilistic sampling, and additionally collects Kubernetes events and logs from Fluentd. The collector exports processed data over OTLP to another Opentelemetry collector.</em></p>
<p><em>The</em> distribution <strong>won’t fit</strong> if <em>the collector exports data to Kafka instead of OTLP or exports to the Zipkin Backend.</em></p>
</blockquote>
<ul>
<li><h2 id="heading-opentelemetry-collector-otlp-distro">Opentelemetry Collector OTLP distro</h2>
</li>
</ul>
<p>It is the most minimalistic distribution. It contains modules for receiving and exporting data over the OTLP protocol. It is a good option to serve as a proxy, protocol translation, and a few other <a target="_blank" href="https://github.com/open-telemetry/opentelemetry-collector-releases/blob/main/distributions/otelcol-otlp/README.md#opentelemetry-collector-otlp-distro">scenarios</a>.</p>
<blockquote>
<p><strong>Example</strong>. The collector pipeline, when OTLP distro <strong>may be a fit</strong>:</p>
<p><em>The collector runs as a sidecar for a Kubernetes application, collects data from this application over OTLP, and sends it to another OTEL collector.</em></p>
</blockquote>
<h1 id="heading-vendors-distributions">Vendors distributions</h1>
<p>Some organizations maintain and distribute their <a target="_blank" href="https://opentelemetry.io/ecosystem/distributions/">own versions</a> of OpenTelemetry collectors. Vendor distributions often offer additional features, such as adapting the collector for easier integration with vendor software, easier configuration, optimized performance, and others.</p>
<blockquote>
<p><em>For example,</em> <a target="_blank" href="https://www.elastic.co/docs/reference/opentelemetry"><em>Elastic EDOT Distribution</em></a> <em>of OpenTelemetry Collector includes components from OpenTelemetry Collector Core Distro and</em> <a target="_blank" href="https://github.com/elastic/opentelemetry-collector-components"><em>Elastic Collector components</em></a><em>. It offers additional features that can be useful for Elastic users.</em></p>
</blockquote>
<p>Other examples include <a target="_blank" href="https://github.com/DataDog/datadog-agent/tree/main/comp/otelcol">DataDog</a> distribution, <a target="_blank" href="https://aws-otel.github.io/docs/getting-started/collector">AWS Distro</a> distribution, and others.</p>
<h1 id="heading-custom-build-distribution">Custom Build distribution</h1>
<p>For the highest level of control and flexibility, consider <a target="_blank" href="https://opentelemetry.io/docs/collector/custom-collector/">building a custom collector</a>. By building your own collector, you gain full control over which components to include, which default configuration to use, when to upgrade the version, whether to include <a target="_blank" href="https://opentelemetry.io/docs/collector/building/">custom components</a>, and so on. As a downside, you have to handle the version upgrades on your own if you choose this option.</p>
<h1 id="heading-summary">Summary</h1>
<p>We can summarize all the benefits and drawbacks of each option in the table below:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Distribution</strong></td><td><strong>Benefits</strong></td><td><strong>Drawbacks</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Otel community distribution</td><td>✓ The choice of distributions for several use cases</td><td>✗ The set of components cannot be changed</td></tr>
<tr>
<td>Third-party distribution</td><td>✓ Extended support and optimizations for vendor software</td><td>✗ The upgrades’ availability depends on the Vendor's release schedule</td></tr>
<tr>
<td>Custom distribution</td><td>✓ Full control over the component set</td><td>✗ The need to organize and maintain the building and the release pipeline</td></tr>
</tbody>
</table>
</div><h1 id="heading-conclusion">Conclusion</h1>
<p>The community and third-party vendors maintain different <strong>OpenTelemetry collector distributions</strong> for various use cases. However, you don’t have to limit yourself to choosing one distribution for solving all observability pipeline tasks. Your infrastructure may utilize multiple distributions simultaneously and form a solid pipeline together.  <em>For example</em>, you can use the k8s distribution for collecting k8s-specific information, the EBPF distribution for EBPF data, the Elastic EDOT distribution to process data for elastic backends, and so on. If none of the pre-built distributions fit your needs, or for the maximal flexibility and control, you can build <strong>a custom OpenTelemetry collector distribution</strong>.</p>
<p>By understanding these pros and cons, you can select the distribution that best aligns with your infrastructure's needs.</p>
]]></content:encoded></item></channel></rss>