<?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[Roger Coll - Elastic Observability Labs]]></title>
    <description><![CDATA[Trusted security news & research from the team at Elastic.]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Roger Coll - Elastic Observability Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltad972c1c27dbefc6/6a88d9782904ea5e8511d473/observability-labs-thumbnail.png</url>
      <link>https://www.elastic.co/observability-labs/author/roger-coll</link>
    </image>
    <link>https://www.elastic.co/observability-labs/author/roger-coll</link>
    <atom:link href="https://www.elastic.co/observability-labs/rss/author/roger-coll.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[en]]></language>
    <lastBuildDate>Sun, 13 Sep 2026 04:45:24 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Self-Driving Observability: From Stacktraces to Profiling-Derived Metrics]]></title>
    <description><![CDATA[Profiling-derived metrics turn raw stacktraces into time-series KPIs, unlock continuous profiling for every user and lay the foundation for an observability system that detects, investigates, and acts on its own.]]></description>
    <content:encoded><![CDATA[<p>Continuous profiling has come a long way. With the <a href="https://opentelemetry.io/blog/2026/profiles-alpha/">OpenTelemetry Profiles signal entering Alpha</a> and the <a href="https://github.com/open-telemetry/opentelemetry-ebpf-profiler">OpenTelemetry eBPF profiler</a> — donated by Elastic — now operating as a first-class OpenTelemetry Collector receiver, low-overhead, whole-system profiling on Linux is finally available to every OpenTelemetry user. No instrumentation, no recompilation, no service restarts. Just deploy the profiler and get visibility from the kernel, through native code, all the way up into HotSpot, Python, V8, .NET, Go, PHP, Perl, BEAM Erlang and Ruby runtimes.</p>
<p>The processing pipeline is straightforward: The profiler samples every CPU core on the system at a fixed rate
(19Hz by default), unwinds execution stacks, symbolizes the resulting stacktraces and ships the profiles to
a backend like Elasticsearch.</p>
<p>And then… the user has to figure out what to do with them.</p>
<p>That last step is where continuous profiling has historically faced adoption challenges, as
the path from "profiling is on" to "profiling is useful" is steeper than it should be.</p>
<h2 id="fourbarrierstoadoption">Four barriers to adoption</h2>
<ul>
<li><p><strong>Storage cost:</strong> Full stacktraces, even after deduplication and clever storage schemas, are expensive to store at fleet scale. That cost makes continuous profiling an opt-in feature in practice: a lot of potential users never enable it, and the ones who do, tend to enable it only on a subset of hosts.</p></li>
<li><p><strong>Query friction:</strong> A normalized stacktrace schema is optimized for ingestion and storage but complicates ad-hoc questions. "How much CPU time does my service spend in TLS?" is a simple question that may require intricate ES|QL or custom code in order to be answered.</p></li>
<li><p><strong>AI-hostile data:</strong> Normalized stacktrace data (typically involving multiple levels of indirection) resists straightforward algorithmic analysis. LLMs in particular struggle with it and necessitate further data transformations into representations more amenable to LLM processing.</p></li>
<li><p><strong>UX barrier:</strong> Flamegraphs are extremely useful when you know how to read them but intimidating when you don't.</p></li>
</ul>
<p>These four barriers compound: storage cost limits coverage, the UX barrier limits who benefits from coverage, query friction limits what questions users can ask and the AI-hostile data representation limits what the system can do when users don't know what questions to ask.</p>
<h2 id="howprofilingderivedmetricsworkclassifyattheedge">How profiling-derived metrics work: classify at the edge</h2>
<p>The core idea is simple: instead of sending full stacktraces all the way to a backend and asking the user to make sense of them there, we classify and count at the edge, inside an OpenTelemetry Collector pipeline, and emit ordinary OpenTelemetry time-series counters. The profiling logic itself doesn't change; it's still the OpenTelemetry eBPF profiler running inside the OpenTelemetry Collector. All the new work happens in a stateless connector inside the Collector: the connector inspects each stacktrace produced by the profiler, classifies its frames into one or more categories and increments counters.</p>
<p>We've released <a href="https://github.com/elastic/opentelemetry-collector-components/tree/main/connector/profilingmetricsconnector"><code>profilingmetricsconnector</code></a> as part of Elastic's <code>opentelemetry-collector-components</code> repository. It sits between the OpenTelemetry eBPF profiler receiver and any metrics exporter, and turns symbolized stacktraces into named, aggregated counters with attributes.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5bb4283e563187e2/6a7f197c33fa8a9fe8202b6c/profilingmetricsconnector-pipeline.svg" alt="profilingmetricsconnector pipeline" /></p>
<p>Because the profilingmetricsconnector lives inside the standard OpenTelemetry Collector pipeline, every metric it produces flows through the same processors as the rest of your telemetry. In the following example, the <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md"><code>resourcedetectionprocessor</code></a> enriches each counter with host-derived attributes.</p>
<pre><code>connectors:
  profilingmetrics:
    flush_interval: 30s

receivers:
  profiling: {}

exporters:
  elasticsearch:
    endpoints:
      - # ENDPOINT
    api_key: # API_KEY
    mapping:
      mode: otel

processors:
  resourcedetection:
    detectors: ["system"]
    system:
      hostname_sources: ["os"]
      resource_attributes:
        host.name:
          enabled: true
        host.id:
          enabled: false
        host.arch:
          enabled: true
        os.description:
          enabled: true
        os.type:
          enabled: true

service:
  pipelines:
    profiles:
      receivers: [ profiling ]
      exporters: [ profilingmetrics ]
    metrics:
      receivers: [ profilingmetrics ]
      processors: [resourcedetection]
      exporters: [ elasticsearch ]
</code></pre>
<h2 id="profilingderivedcpumetricswhatgetsemitted">Profiling-derived CPU metrics: what gets emitted</h2>
<p>The connector ships with a set of pre-baked counters built from useful classification rules. Each metric is a count of stacktrace samples whose leaf frame matched a particular category, with the frequency value standing in for CPU consumption.</p>
<p>| Metric | Classifies | Attached metadata |
|---|---|---|
| <code>kernel.count</code> | Kernel leaf frames | <code>syscall</code>, <code>category</code> (<code>disk/rw</code>, <code>ipc/rw</code>, <code>network/{tcp,udp,other}/rw</code>, <code>memory</code>, <code>synchronization</code>, …) |
| <code>native.count</code> | Native C/C++/Rust leaf frames | shared library name (<code>libcrypto</code>, <code>libclrjit</code>, <code>libsystemd</code>, …) |
| <code>hotspot.count</code>, <code>go.count</code>, <code>python.count</code>, … | Runtime-specific leaf frames | runtime-specific attributes |</p>
<p>The kernel categorization is worth a closer look as a modern Linux kernel has more than 400 system calls. However, most of what shows up in CPU stacktraces falls into a handful of subsystems: filesystem read/write, network read/write, memory management, scheduling, synchronization. Some syscalls (e.g. <code>read</code>, <code>write</code>) are ambiguous on their own and only become specific when one examines more frames down the stack: <code>ext4_file_read_iter</code> points to filesystem, <code>tcp_v4_rcv</code> to network. The connector handles this disambiguation as part of frame iteration.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt282d1eb8637b61fc/6a7f197fb4377095a24d70e6/kibana-kernel-cpu-by-category.png" alt="Kernel CPU breakdown by category in Kibana" /></p>
<p>Native frames typically lack symbolic information beyond shared library names, but those names are still informative: <code>libssl</code> and <code>libcrypto</code> mean cryptographic work as part of OpenSSL or one of its variants; <code>libz</code> means compression; <code>libclrjit</code> means the .NET JIT is busy. We don't need to enumerate libraries statically as the connector dynamically generates <code>shlib_name</code> attribute values using the trimmed library name (e.g. <code>libssl</code> not <code>libssl.so.3</code>) for clean cardinality.</p>
<p>Currently, for each stacktrace, the connector computes a <strong>Self CPU</strong> count (the leaf frame matched the category) corresponding to exclusive CPU usage. A complication exists for fine-grained kernel categories like <code>network/tcp/write</code> where the actual leaf frame is usually a device-driver call that we can't meaningfully match. We deal with that by trying to match frames further up the stack (e.g. <code>tcp_sendmsg</code> is enough to correctly classify the sample).</p>
<p>Users can also add their own categories by specifying a frame pattern (e.g. a function or package) and the connector will generate counters for them.</p>
<h2 id="benefitsofprofilingderivedmetricsforobservability">Benefits of profiling-derived metrics for observability</h2>
<p>This shift looks small from the outside — "we're emitting counters" — but it changes almost everything about how profiling fits into an observability stack.</p>
<ul>
<li><p><strong>Orders of magnitude less storage:</strong> A counter aggregated over a 5-second (or 30-second or one-minute) window is dramatically cheaper than the full stacktraces it distills. The pre-aggregation interval is configurable with the trade-off being time resolution rather than categorization fidelity. For most "where is my CPU being spent?" questions, 30 seconds is plenty.</p></li>
<li><p><strong>On by default:</strong> Because the storage cost is now in line with regular metrics, profiling-derived metrics can be on for everyone, on every host, from the moment the profiler is deployed. Users get a CPU breakdown by runtime, syscall, kernel category and shared library on day one.</p></li>
<li><p><strong>Standard dashboards:</strong> These are ordinary OpenTelemetry time-series counters and can be visualized ad-hoc using stacked bar graphs, pie charts, top-N panels or any other visualization Kibana supports out of the box. The same Lens and TSDB-backed views for application metrics work here.</p></li>
</ul>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte715bd8eb945ab75/6a7f198296b5a6391f87b86b/kibana-user-cpu-over-time.png" alt="User CPU by frame type over time in Kibana" /></p>
<ul>
<li><p><strong>AI and query-friendly:</strong> Standard time-series data is trivially consumable by ES|QL, ML jobs, anomaly detectors and by LLMs. "Show me the top services by <code>network/udp/write</code> time, filtered to the payments namespace, over the last six hours" is one query that is not only simple for the system to answer but also simple for an LLM to generate.</p></li>
<li><p><strong>Cross-signal correlation:</strong> Because the metrics flow through the standard OpenTelemetry Collector pipeline, they pick up the same resource attributes (e.g. <code>service.name</code>, <code>k8s.pod.name</code>, <code>host.name</code>, <code>deployment.environment</code>) that logs, other metrics and traces already carry.</p></li>
<li><p><strong>Instant value, with a path to more detail:</strong> A user who just wants to know "what's burning my CPU?" gets a meaningful answer without ever opening a flamegraph. A user who wants to dig deeper still has the full eBPF profiler underneath, ready to hand back complete stacktraces when they're warranted.</p></li>
</ul>
<h2 id="userprogrammableprofilingandadaptivesampling">User-programmable profiling and adaptive sampling</h2>
<p>The longer-term direction is for the profiler to stop being something users <em>consume</em> and start being something they <em>program</em>. User-defined metrics are the first step in this direction, complemented by on-demand (full) profiling and adaptive sampling.</p>
<p>Profiling-derived metrics or other signals can act as a trigger for on-demand profiling where the system enables full profiling on a specific host or service to capture complete stacktraces. In that way, the full profiling processing and storage cost is paid only when it matters.</p>
<p>We can apply the same idea to the sampling rate. 19Hz is a sensible baseline for steady state but when the metrics signal an interesting event or an anomaly, the system can automatically ramp to 100Hz or higher to capture high-fidelity data for the time window during which it's relevant. It can then ramp down to baseline.</p>
<h2 id="howprofilingderivedmetricsenableselfdrivingobservability">How profiling-derived metrics enable self-driving observability</h2>
<p>Most observability stacks today use an open-loop model: the profiler emits data with a fixed configuration. Then a human looks at flamegraphs and dashboards, potentially correlates with logs, other metrics and traces, forms a hypothesis and triggers a deeper investigation. Every link in this chain requires a human decision. Nothing feeds back into the profiler at speed and the system cannot act on its own observations.</p>
<p>Profiling-derived metrics close that loop.</p>
<ol>
<li><p>A "significant host events" metric, an anomaly on <code>network/udp/write</code> or a spike in <code>native.count/libz</code>: something crosses a threshold.</p></li>
<li><p>The profiler adjusts in response: sampling rate increases, full profiling turns on for the affected hosts.</p></li>
<li><p>The richer data is correlated against logs, traces, and other metrics by an LLM, by a human or both. The same resource attributes that make cross-signal correlation easy for the user make it easy for the system.</p></li>
<li><p>A root cause is identified. A remediation is suggested or applied. The metric returns to baseline and the loop continues.</p></li>
</ol>
<p>This is what we mean when we talk about <em>self-driving observability</em>. The profiler is no longer just an instrument that someone wields. It is the sensory organ of an autonomous feedback loop: a system that observes itself, decides what to look at more closely and adjusts its own configuration in response to what it sees.</p>
<h2 id="whatsnextinclusivecpuoffcpumetricsandruntimespecificprofiling">What's next: inclusive CPU, off-CPU metrics, and runtime-specific profiling</h2>
<p>Any piece of data visible in a stacktrace can be a metric source and several extensions are already on the roadmap.</p>
<ul>
<li><p><strong>Inclusive-CPU metrics:</strong> Today's pre-baked counters attribute CPU at the leaf frame (exclusive-CPU). Inclusive-CPU metrics will attribute the entire call chain which is useful when you care about the total cost of a function call — the function plus everything it transitively calls — not just the work done directly in its own body.</p></li>
<li><p><strong>Runtime-specific metrics:</strong> GC time per runtime, JSON/Protobuf serialization, RPC frameworks, FFI boundaries. The kinds of questions every team eventually asks about their language runtime, answered by default.</p></li>
<li><p><strong>Off-CPU metrics:</strong> On-CPU profiling tells you where you're spending CPU but Off-CPU profiling tells you where you're <em>not</em> (e.g. blocked on I/O, locks). The same classification logic applies, with the only change being the source signal.</p></li>
</ul>
<p>Profiling-derived metrics are an active area of work within Elastic and the <a href="https://github.com/elastic/opentelemetry-collector-components/tree/main/connector/profilingmetricsconnector">profilingmetricsconnector</a> is the place to start if you want to play with this today. A ready-made <a href="https://www.elastic.co/docs/reference/integrations/profilingmetrics_otel">Kibana integration</a> ships dashboards for all the metrics described above.</p>
<p>If you're already using Elastic's continuous profiling, expect these metrics to show up as first-class citizens in the Elastic stack. If you're not, this is a very low-friction way in as no flamegraph expertise is required and storage
cost is minimal.</p>
<p>The flamegraph isn't going anywhere, but for the first time, it isn't the <em>only</em> way profiling yields results.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/otel-profiling-metrics</link>
    <guid isPermaLink="false">otel-profiling-metrics</guid>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[Metrics]]></category>
    <category><![CDATA[APM]]></category>
    <dc:creator><![CDATA[Christos Kalkanis,Roger Coll]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt418826f669e25898/6a7f19859090b02bc984ee13/header.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 01 Jun 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[OpenTelemetry Profiles Signal Enters Alpha: Elastic’s Continuous Commitment to Profiling]]></title>
    <description><![CDATA[OpenTelemetry Profiles has officially reached Alpha, entrenching profiling as the fourth observability signal. Elastic's core contribution of its eBPF profiling agent, continued OpenTelemetry Profiles signal work and commitment to a vendor-agnostic ecosystem are driving this industry-wide standard forward.]]></description>
    <content:encoded><![CDATA[<p>Following intensive collaboration between Elastic and the OpenTelemetry community, we are thrilled to announce that the OpenTelemetry Profiles signal has officially entered public Alpha.
This milestone is a testament to the community's dedication and marks a significant step towards establishing profiling as the fourth key observability signal in OpenTelemetry, alongside logs, metrics and traces.</p>
<p>As a core contributor, Elastic is proud to have accelerated this effort by previously donating its Universal Profiling™ eBPF-based continuous profiling agent to OpenTelemetry.
This production-grade agent enables whole-system visibility across all applications, covering a multitude of programming languages and runtimes including third-party libraries and kernel operations with minimal overhead.
It allows SREs and developers to quickly identify performance bottlenecks, maximize resource utilization, and optimize cloud spend.</p>
<p>Additionally, over the last two years, Elastic has been heavily contributing to the OpenTelemetry Collector, Semantic Conventions and Profiling Special Interest Groups (SIGs) to lay the technical foundation for the promotion of Profiles to Alpha.</p>
<p>This Alpha milestone not only boosts the standardization of continuous profiling but also accelerates the practical adoption of profiling as the fourth key signal in observability.
Customers now have a vendor-agnostic way of collecting profiling data and enabling correlation with existing signals, like logs, metrics and traces, unveiling new potential for observability insights and a more efficient troubleshooting experience.</p>
<h2 id="whatiscontinuousprofiling">What is continuous profiling?</h2>
<p>Profiling is a technique used to understand the behavior of a software application by collecting information about its execution.
This includes tracking the duration of function calls, memory usage, CPU usage, and other system resources. </p>
<p>However, traditional profiling solutions have significant drawbacks limiting adoption in production environments:</p>
<ul>
<li>Significant cost and performance overhead due to code instrumentation</li>
<li>Disruptive service restarts</li>
<li>Inability to get visibility into third-party libraries</li>
</ul>
<p>Unlike traditional profiling, which is often done only in a specific development phase or under controlled test conditions, continuous profiling runs in the background with minimal overhead, eliminating the need for service restarts or manual intervention.
This provides real-time, actionable insights without replicating issues in separate environments.
SREs, DevOps, and developers can see how code affects performance and cost, making code and infrastructure improvements easier.</p>
<h2 id="elasticscontributionpoweringthealpha">Elastic's contribution: Powering the Alpha</h2>
<p>The Elastic-donated profiler now forms the reference eBPF-based profiler implementation within OpenTelemetry: <a href="https://github.com/open-telemetry/opentelemetry-ebpf-profiler/">opentelemetry-ebpf-profiler</a>.
With the Alpha release, the eBPF profiler operates as an OpenTelemetry Collector receiver and contains numerous improvements such as automatic Go symbolization and support for new language runtimes.
Operating as an OpenTelemetry Collector receiver enables the profiler to seamlessly leverage existing OpenTelemetry processing and filtering pipelines. </p>
<p>For example, the <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/k8sattributesprocessor">k8sattributesprocessor</a> can use the <code>container.id</code> resource attribute to automatically enrich every profile with its corresponding Kubernetes context.
This means you don't just see a raw stack trace; you see exactly which namespace, pod, and deployment produced it.</p>
<pre><code>receivers:
  # Profiling receiver
  profiling: {}

processors:
  k8sattributes:
    passthrough: false 
    pod_association:
      - sources:
          - from: resource_attribute
            name: container.id
    extract:
      metadata:
        - "k8s.namespace.name"
        - "k8s.deployment.name"
        - "k8s.replicaset.name"
        - "k8s.statefulset.name"
        - "k8s.daemonset.name"
        - "k8s.node.name"
        - "k8s.pod.name"
        - "k8s.pod.ip"
        - "k8s.pod.uid"
</code></pre>
<p>Besides improvements to the eBPF profiler, Elastic has made significant contributions to:</p>
<ul>
<li>Correlating profiles with the information produced by OpenTelemetry eBPF instrumentation (<a href="https://opentelemetry.io/docs/zero-code/obi/">OBI</a>), a powerful auto-instrumentation tool that can enable distributed tracing. </li>
<li><a href="https://github.com/open-telemetry/opentelemetry-specification/pull/4719">Process Context Sharing OTEP</a> which is designed to bridge the gap between application SDKs and the profiler. This mechanism will allow OpenTelemetry SDKs to "publish" their resource attributes (like <code>service.name</code>) into a small, standardized memory region. Because this data is stored in the process's own memory map, the eBPF Profiler can instantly discover and associate it with its corresponding Profile.</li>
<li>Semantic conventions and integration of OpenTelemetry Profiles with Google's pprof format (transparent conversion)</li>
<li>OpenTelemetry Collector processing pipelines, allowing it to better integrate with the profiling receiver</li>
</ul>
<h2 id="elasticsnextgenerationprofilingdevelopment">Elastic's Next-Generation Profiling Development</h2>
<p>Elastic remains deeply committed to OpenTelemetry's vision and is pushing the boundaries of what is possible with profiling data.
We are dedicating a team of profiling domain experts to co-maintain and advance profiling capabilities within OpenTelemetry, while simultaneously working on groundbreaking features built on this new open standard.</p>
<p>Exciting areas of internal profiling-specific development include:</p>
<ul>
<li>OpenTelemetry Profiles derived Metrics: We are developing innovative ways to automatically generate actionable performance metrics directly from the raw OTel Profiles data, providing a new dimension for infrastructure modeling and alerting.</li>
<li>Rapid Integration with the Elastic Stack: We are making swift progress on first-class support for OTLP Profiles within the Elastic Stack, ensuring seamless ingestion (the ebpf-profiler receiver is already integrated with the <a href="https://github.com/elastic/elastic-agent/tree/main/internal/edot#components">Elastic Distributions of OpenTelemetry (EDOT) collector</a>), storage, and visualization of this new signal alongside your existing logs, metrics and traces.</li>
<li>AI-Powered Workflows: We are leveraging the deep insights provided by continuous profiling data to power new AI-driven workflows, enabling automatic root-cause analysis, anomaly detection, and intelligent optimization suggestions for both code and infrastructure.</li>
</ul>
<p>While the Alpha release marks a significant milestone, it is just the beginning.
We encourage the community to start testing early preview versions of the OTel Profiles integration and contribute to the ongoing profiling work.
To get started with an actual, local deployment, you can use the <a href="https://github.com/open-telemetry/opentelemetry-ebpf-profiler">OpenTelemetry eBPF profiler</a> in combination with a self-hosted <a href="https://www.elastic.co/docs/solutions/observability">Elastic Observability Stack</a> or <a href="https://github.com/elastic/devfiler">devfiler</a>, a standalone desktop application that acts as an OpenTelemetry Profiles compliant backend aimed at experimentation and development.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/otel-profiling-alpha</link>
    <guid isPermaLink="false">otel-profiling-alpha</guid>
    <category><![CDATA[OpenTelemetry]]></category>
    <category><![CDATA[APM]]></category>
    <dc:creator><![CDATA[Christos Kalkanis,Florian Lehner,Roger Coll]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt710a2b45a0da343d/6a7f1978bd21986753758495/header.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 25 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Assembling an OpenTelemetry NGINX Ingress Controller Integration]]></title>
    <description><![CDATA[This blog post explores how to set up an OpenTelemetry integration for the NGINX Ingress Controller, detailing the configuration process, key transformations, and upcoming enhancements for modular configuration support.]]></description>
    <content:encoded><![CDATA[<p>Our vision is clear: to support OpenTelemetry within Elastic. A key aspect of
this transition are integrations — how can we seamlessly adapt all existing
integrations to fit the OpenTelemetry model?</p>
<p>Elastic integrations are designed to simplify observability by providing tools
to ingest application data, process it through Ingest pipelines, and deliver
prebuilt dashboards for visualization. With OpenTelemetry support, data
collection and processing will transition to the OpenTelemetry Collector, while
dashboards will need to adopt the OpenTelemetry data structure.</p>
<h2 id="fromalogtoanintegration">From a Log to an Integration</h2>
<p>Although the concept of an OpenTelemetry Integration has not yet been officially
defined, we envision it as a structured collection of artifacts that enables users
to start monitoring an application from scratch. Each artifact has a specific role;
for example, an OpenTelemetry Collector configuration file, which must be
integrated into the main Collector setup. This bundled configuration instructs
the Collector on how to gather and process data from the relevant application.</p>
<p>In the OpenTelemetry Collector, data collection is handled by the <a href="https://opentelemetry.io/docs/collector/configuration/#receivers">receivers</a>
component. Some receivers are tailored for specific applications, such as Kafka
or MySQL, while others are designed to support general data collection methods.
The specialized receivers combine data gathering and transformation within a
single component. For the more generic receivers, however, additional components
are needed to refine and transform the incoming data into a more
application-specific format. Let’s take a look at how we can build an
integration for monitoring a Nginx Ingress Controller.</p>
<p>The Ingress Nginx is an Ingress controller for Kubernetes, using NGINX as a
reverse proxy and load balancer. Widely adopted, it plays a crucial role in
directing external traffic into Kubernetes services, making its usage,
performance and health essential to observe. How can we start observing the external
requests done to our Ingress controller? Fortunately, the NGINX Ingress Controller
generates a structured log entry for each processed request. This structured
format ensures that each log entry follows a consistent structure, making it
straightforward to parse and generate consistent output.</p>
<pre><code>log_format upstreaminfo '$remote_addr - $remote_user [$time_local]
    "$request" ' '$status $body_bytes_sent "$http_referer" "$http_user_agent" '
    '$request_length $request_time [$proxy_upstream_name]
    [$proxy_alternative_upstream_name] $upstream_addr ' '$upstream_response_length
    $upstream_response_time $upstream_status $req_id';
</code></pre>
<p>All the field's definition can be found
<a href="https://github.com/kubernetes/ingress-nginx/blob/controller-v1.11.3/docs/user-guide/nginx-configuration/log-format.md">here</a>.</p>
<p>The OpenTelemetry Contrib Collector does not include a receiver capable of
reading and parsing all fields in an NGINX Ingress log. There are two primary
reasons for this:</p>
<ul>
<li><strong>Application Diversity</strong>: The landscape of applications is vast, with each
generating logs in unique formats. Developing and maintaining a dedicated
receiver for every application would be resource-intensive and difficult to
scale.</li>
<li><strong>Data Source Flexibility</strong>: Receivers are typically designed to collect data
from a specific source, like an HTTP endpoint. However, in some cases, we
may want to parse logs from an alternate source, such as an NGINX Ingress
log file stored in an AWS S3 bucket.</li>
</ul>
<p>These challenges can be addressed by combining receivers and processors.
Receivers handle the collection of raw data, while processors can extract
specific values when a known data structure is detected. Do we need a dedicated
processor to parse NGINX logs? Not necessarily. The transform processor can
handle this by modifying telemetry data according to a specified configuration.
This configuration is written in the OpenTelemetry Transformation Language
(OTTL), a language for transforming open telemetry data based on the
<a href="https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/rfcs/processing.md">OpenTelemetry Collector Processing
Exploration</a>.</p>
<p>The concept of processors in OpenTelemetry is quite similar to the Ingest
pipeline strategy currently used in Elastic integrations. The main challenge,
therefore, lies in migrating Ingest pipeline configurations to OpenTelemetry
Collector configurations. For a deeper dive into the challenges of such
migrations, check out this
<a href="https://www.elastic.co/observability-labs/blog/logstash-to-otel">article</a>.</p>
<p>For reference, you can view the current Elastic NGINX Ingress
Controller Ingest pipeline configuration in the following link: <a href="https://github.com/elastic/integrations/blob/main/packages/nginx_ingress_controller/data_stream/access/elasticsearch/ingest_pipeline/default.yml">Elastic NGINX
Ingress Controller Ingest
Pipeline</a>.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt621c17a76ed7169b/6a7f0d23eab5becd0520a6f5/logstash-pipeline-to-otel-pipeline.png" alt="logstash-pipeline-to-otel-pipeline" /></p>
<p>Let’s start with the data collection. By default, the NGINX Ingress Controller
logs to stdout, and Kubernetes captures and stores these logs in a file.
Assuming that the
OpenTelemetry Collector running the following configuration has access to the
Kubernetes Pod logs, we can use the <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/filelogreceiver">filelog
receiver</a>
to read the controller logs:</p>
<pre><code>receivers:
  filelog/nginx:
    include_file_path: true
    include: [/var/log/pods/*nginx-ingress-nginx-controller*/controller/*.log]
    operators:
      - id: container-parser
        type: container
</code></pre>
<p>This configuration is designed to exclusively read the controller's pod logs,
focusing on their default file path within a Kubernetes node. Furthermore, since
the Ingress controller does not inherently have access to its associated
Kubernetes metadata, the <code>container-parser</code> operator has been implemented to
bridge this gap. This operator appends Kubernetes-specific attributes, such as
<code>k8s.pod.name</code> and <code>k8s.namespace.name</code>, based solely on information available
from the filename. For a detailed overview of the <code>container-parser</code> operator, see
the following <a href="https://opentelemetry.io/blog/2024/otel-collector-container-log-parser/">OpenTelemetry blog
post</a>.</p>
<h3 id="avoidingduplicatedlogs">Avoiding duplicated logs</h3>
<p>The configuration outlined in this blog is designed for Kubernetes environments,
where the collector runs as a Kubernetes Pod. In such setups, handling Pod
restarts properly is crucial. By default, the <code>filelog</code> receiver reads the entire
content of log files on startup. This behavior can lead to duplicate log entries
being reprocessed and sent through the pipeline if the collector Pod is
restarted.</p>
<p>To make the configuration resilient to restarts, you can use a storage extension
to track file offsets. These offsets allow the <code>filelog</code> receiver to resume
reading from the last processed position in the log file after a restart. Below
is an example of how to add a <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/storage/filestorage">file storage extension</a> and update the <code>filelog</code>
receiver configuration to store the offsets in a file:</p>
<pre><code>extensions:
  file_storage:
  directory: /var/lib/otelcol

receivers:
  filelog/nginx:
    storage: file_storage
    ...
</code></pre>
<p><strong>Important</strong>: The /var/lib/otelcol directory must be mounted as part of a
Kubernetes persistent volume to ensure the stored offsets persist across Pod
restarts.</p>
<h3 id="datatransformationwithopentelemetryprocessors">Data transformation with OpenTelemetry processors</h3>
<p>Now it’s time to parse the structured log fields and transform them into
queryable OpenTelemetry fields. Initially, we considered using regular
expressions with the <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/ottlfuncs#extract_patterns">extract_patterns
function</a>
available in the OpenTelemetry Transformation Language (OTTL). However, Elastic
recently contributed a new OTTL function,
<a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/ottlfuncs#extractgrokpatterns">ExtractGrokPatterns</a>,
based on Grok—a regular expression dialect that supports reusable, aliased
expressions. The function’s underlying library <a href="https://github.com/elastic/go-grok">Elastic
Go-Grok</a> ships with numerous predefined grok
patterns that simplify working with pattern matching, like <code>%NUMBER</code>
that will match any number type; "123", "456.789", "-0.123".</p>
<p>Each Ingress Controller log entry begins with the client's source IP address
(which may be a single IP or a list of IPs) and the username provided via Basic
authentication, represented as “$remote_addr - $remote_user”. The Grok IP alias
can be used to parse either an IPv4 or IPv6 address from the remote_addr field,
while the <code>%GREEDYDATA</code> alias can capture the remote_user value.</p>
<p>For example, the following OTTL configuration will transform an unstructured
body message to a structured one with two fields:</p>
<ul>
<li>Parses a single IP address and assign it to the source.address key.</li>
<li>Delimited by a “-”, captures the optional value of the authenticated username
in the <code>user.name</code> key.</li>
</ul>
<pre><code>transform/parse_nginx_ingress_access/log:
  log_statements:
    - context: log
      statements:
        - set(body, ExtractGrokPatterns(body, "%{IP:source.address} - (-|%{GREEDYDATA:user.name})", true))
</code></pre>
<p>The screenshot below illustrates the transformation process, showing the
original input data alongside the resulting structured format (diff):</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf1c84f9d0271011b/6a7f02e833fa8a181e20223d/data-diff.png" alt="data-transform-diff" /></p>
<p>In real-world scenarios, NGINX Ingress Controller logs may begin with a list of
IP addresses or, at times, a domain name. These variations can be handled with
an extended Grok pattern. Similarly, we can use Grok to parse an HTTP UserAgent
and URL strings, but additional OTTL functions, such as
<a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/ottlfuncs#url">URL</a>
or
<a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/pkg/ottl/ottlfuncs#useragent">UserAgent</a>,
are required to extract meaningful data from these fields.</p>
<p>The complete configuration is available in the documentation for Elastic’s
OpenTelemetry NGINX Ingress Controller integration: <a href="https://github.com/elastic/integrations/blob/main/packages/nginx_ingress_controller_otel/docs/README.md">Integration
Documentation</a>.</p>
<h2 id="usage">Usage</h2>
<p>The Elastic OpenTelemetry NGINX Ingress Controller is currently on <strong>Technical
preview</strong>. To access it, you must enable the "Display beta integrations" toggle
in the <strong>Integrations</strong> menu within Kibana.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfb3ad090d9931319/6a7f02ebb43770063c4d6867/kibana-integration.png" alt="kibana-nginx-integration" /></p>
<p>By installing the Elastic OpenTelemetry NGINX Ingress Controller integration, a
couple of dashboards will become available in your Kibana profile. One of these
dashboards provides insights into access events for the controller, displaying
information such as HTTP response status codes over time, request volume per
URL, distribution of incoming requests by browser, top requested pages, and
more. The screenshot below shows the NGINX Ingress Controller Access Logs
dashboard, displaying data from a controller routing requests to an
<a href="https://github.com/elastic/opentelemetry-demo">OpenTelemetry Demo</a> deployment:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb3ce0992bb121156/6a7f02eeead8ec75d5baa39f/main-dashboard.png" alt="nginx-ingress-controller-otel-access-dashboard" /></p>
<p>The second dashboard focuses on errors within the Nginx Ingress controller, highlighting the
volume of error events generated over time:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt13ae13e034223d6e/6a7f02f1227b1ced1e598194/error-access-dashboard.png" alt="nginx-ingress-controller-otel-error-access-dashboard" /></p>
<p>To start gathering and processing controller logs, we recommend incorporating
the OpenTelemetry Collector pipeline outlined in the integration’s documentation
into your collector configuration: <a href="https://www.elastic.co/guide/en/integrations/current/nginx_ingress_controller_otel.html">Integration
Documentation</a>.
Keep in mind that this configuration requires access to the Kubernetes node's
Pods logs,
typically stored in <code>/var/log/pods/*</code>. To ensure proper access, we recommend
deploying the OpenTelemetry Collector as a daemonset in Kubernetes, as this
deployment type allows the collector to access the necessary log directory on
each node.</p>
<p>The OpenTelemetry Collector configuration service pipeline should include a
similar configuration:</p>
<pre><code>service:
  extensions: [file_storage]
  pipelines:
    logs/nginx_ingress_controller:
      receivers:
        - filelog
      processors:
        - transform/parse_nginx_ingress_access/log
        - transform/parse_nginx_ingress_error/log
        - resourcedetection/system
      exporters:
        - elasticsearch
</code></pre>
<h3 id="addinggeoipmetadata">Adding GeoIP Metadata</h3>
<p>As an optional enhancement, the OpenTelemetry Collector <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/geoipprocessor">GeoIP processor</a> can be configured and added to the pipeline to enrich each NGINX Ingress Controller log with geographical attributes, such as the request’s originating country, region, and city, enabling geo maps in Kibana to visualize traffic distribution and geographic patterns.</p>
<p>While the OpenTelemetry GeoIP processor is similar to <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/geoip-processor.html">Elastic's GeoIP
processor</a>,
it requires users to provide their own local GeoLite2 database. The following
configuration extends the Integration’s configuration to include the GeoIP
processor with a <a href="https://dev.maxmind.com/geoip/geolite2-free-geolocation-data/">MaxMind's database</a>.</p>
<pre><code>processors:
  geoip:
    context: record
    providers:
      maxmind:
        database_path: /tmp/GeoLite2-City.mmdb

service:
  extensions: [file_storage]
  pipelines:
    logs/nginx_ingress_controller:
      receivers:
        - filelog
      processors:
        - transform/parse_nginx_ingress_access/log
        - transform/parse_nginx_ingress_error/log
        - resourcedetection/system
        - geoip
      exporters:
        - elasticsearch
</code></pre>
<p>Sample Kibana Map with the OpenTelemetry Nginx Ingress Controller integration:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfaac1676362f353d/6a7f02f4de23150e8bfd7726/geoip-map.png" alt="geoip-map-dashboard" /></p>
<h2 id="nextsteps">Next steps</h2>
<h3 id="opentelemetrylogevent">OpenTelemetry Log Event</h3>
<p>A closer look at the OTTL integration’s statements reveals that the raw log
message is replaced by the parsed fields. In other words, the configuration
transforms the body log field* from a string into a structured map of key-value
pairs, as seen in “set(body, ExtractGrokPatterns(body,…)”. This approach is
based on treating each NGINX Ingress Controller log entry as an <a href="https://opentelemetry.io/docs/specs/otel/logs/event-api/#event-data-model">OpenTelemetry
Event</a>—a
specialized type of LogRecord. Events are OpenTelemetry’s standardized semantic
formatting for LogRecords, containing an
“<a href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/events.md#event-definition">event.name</a>”
attribute which defines the structure of the body field. An NGINX Ingress
Controller log record aligns well with the OpenTelemetry Event data model. It
follows a structured format and clearly distinguishes between two event types:
access logs and error logs. There is an ongoing PR to incorporate the NGINX
Ingress controller log into the OpenTelemetry semantic convention:
https://github.com/open-telemetry/semantic-conventions/pull/982</p>
<h3 id="operatingsystembreakdown">Operating system breakdown</h3>
<p>Each controller log contains the source UserAgent, from which the integration
extracts the browser that originated the request. This information is valuable
for understanding user access patterns, as it provides insights into the types
of browsers commonly interacting with your services. Additionally, an <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/35458">ongoing
pull
request</a>
into OTTL aims to extend this functionality by extracting operating system (OS)
details as well, providing even deeper insights into the environments
interacting with the NGINX Ingress Controller.</p>
<h3 id="configurationencapsulation">Configuration encapsulation</h3>
<p>Setting up the configuration for the NGINX Ingress Controller integration can be
somewhat tedious, as it involves adding several complex processor configurations
to the existing collector pipelines. This process can quickly become cumbersome,
especially for non-expert users or in cases where the collector configuration is
already quite complex. In an ideal scenario, users would simply reference a
pre-defined integration configuration, and the collector would automatically
"unwrap" all the necessary components into the corresponding pipelines. This
would significantly simplify the setup process, making it more accessible and
reducing the risk of misconfigurations. To address this, there is a
<a href="https://github.com/open-telemetry/opentelemetry-collector/pull/11631">RFC</a>
(Request for Comments) proposing support for shareable, modular configurations
within the OpenTelemetry Collector. This feature would allow users to easily
collect signals from specific services or applications by referencing modular
configurations, streamlining the setup and enhancing usability for complex
scenarios.</p>
<p>*The OpenTelemetry community is currently discussing whether structured
body-extracted information should be stored in the attributes or body field.
For details, see this <a href="https://github.com/open-telemetry/semantic-conventions/issues/1651">ongoing issue</a>.</p>
<blockquote>
  <p>This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com</p>
</blockquote>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/assembling-an-opentelemetry-nginx-ingress-controller-integration</link>
    <guid isPermaLink="false">assembling-an-opentelemetry-nginx-ingress-controller-integration</guid>
    <category><![CDATA[OpenTelemetry]]></category>
    <dc:creator><![CDATA[Roger Coll]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3f19ad0ab3ff293a/6a7f02f76693f85a25663b37/ingress-controller.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 15 Jan 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[OpenTelemetry Demo with the Elastic Distributions of OpenTelemetry]]></title>
    <description><![CDATA[Discover how Elastic is dedicated to supporting users in their journey with OpenTelemetry. Explore our public deployment of the OpenTelemetry Demo and see how Elastic's solutions enhance your observability experience.]]></description>
    <content:encoded><![CDATA[<p>Recently, Elastic <a href="https://www.elastic.co/observability-labs/blog/elastic-distributions-opentelemetry">introduced the Elastic Distributions
(EDOT)</a>
for various OpenTelemetry components, we are proud to announce that these EDOT
components are now available in the <a href="https://github.com/elastic/opentelemetry-demo">Elastic's fork of the OpenTelemetry
Demo</a>. We've also made public a
<a href="https://ela.st/demo-otel">Kibana endpoint</a>, allowing you to dive into the
demo’s live data and explore its capabilities firsthand. In this blog post,
we'll elaborate on the reasons behind the fork and explore the powerful new
features it introduces. We'll also provide a comprehensive overview of how
these enhancements can be leveraged with the Elastic Distributions of
OpenTelemetry (EDOT) for advanced error detection, as well as the EDOT
Collector—a cutting-edge evolution of the Elastic Agent—for seamless data
collection and analysis.</p>
<h2 id="whatistheopentelemetrydemo">What is the OpenTelemetry Demo?</h2>
<p>The <a href="https://github.com/open-telemetry/opentelemetry-demo">OpenTelemetry Demo</a>
is a microservices-based application created by OpenTelemetry's community to
showcase its capabilities in a realistic, and distributed system environment.
This demo application, known as the OpenTelemetry Astronomy Shop, simulates an
e-commerce website composed of over 10 interconnected microservices (written in
multiple languages: Go, Java, .NET, Node.js, etc.), communicating via HTTP and
gRPC. Each service is fully instrumented with OpenTelemetry, generating
comprehensive traces, metrics, and logs. The demo serves as an invaluable
resource for understanding how to implement and use OpenTelemetry in real-world
applications.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt786e28cae6a3d1fc/6a85cb0233f2445e1649f50a/opentelemetry_demo_service_map.png" alt="1 - Service Map for the OpenTelemetry Demo Elastic
fork" /></p>
<p>One of the microservices, called <code>loadgenerator</code>, automatically starts
generating requests to the various endpoints of the demo, simulating a
real-world environment where multiple clients are interacting with the system.
This helps replicate the behavior of a busy, live application with concurrent
user activity.</p>
<h3 id="elasticsfork">Elastic's fork</h3>
<p>Elastic recognized an opportunity to enhance the OpenTelemetry Demo by forking
it and integrating advanced Elastic features for deeper observability and
simpler monitoring. While forking is the <a href="https://github.com/open-telemetry/opentelemetry-demo?tab=readme-ov-file#demos-featuring-the-astronomy-shop">recommended OpenTelemetry
approach</a>,
we aim to leverage the robust foundation and latest updates from the upstream
version as much as possible. To achieve this, Elastic’s fork of the
OpenTelemetry Demo performs daily pulls from upstream, seamlessly integrating
them with Elastic-specific changes. To avoid conflicts, we continuously
contribute upstream, ensuring Elastic's modifications are always additive or
configurable through environment variables. One such contribution is the
<a href="https://github.com/elastic/opentelemetry-demo/blob/main/.env.override">.env.override
file</a>,
designed exclusively for vendor forks to override the microservices images and
configuration files used in the demo.</p>
<h2 id="deeperinsightswithelasticdistributions">Deeper Insights with Elastic Distributions</h2>
<p>In our current update of Elastic's OpenTelemetry Demo fork, we have replaced
some of the microservices OTel SDKs used for instrumentation with Elastic's
specialized distributions. These changes ensure deeper integration with
Elastic's observability tools, offering richer insights and more robust
monitoring capabilities. These are some of the fork's changes:</p>
<p><strong>Java services:</strong> The Ad, Fraud Detection, and Kafka services now utilize the
Elastic distribution of the OpenTelemetry Java Agent. One of the included
features in the distribution are stack traces, which provides precise
information of where in the code path a span was originated. Learn more about
the Elastic Java Agent
<a href="https://www.elastic.co/observability-labs/blog/elastic-distribution-opentelemetry-java-agent">here</a>.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta9b95e4656860d7f/6a85cb056826665c9a1eabfd/adservice_span_stacktrace.png" alt="2 - Ad Service span stack trace
example" /></p>
<p>The <strong>Cart service</strong> has been upgraded to use the Elastic distribution of the
OpenTelemetry .NET Agent. This replacement gives visibility on how the Elastic
Distribution of OpenTelemetry .NET (EDOT .NET) can be used to get started using
OpenTelemetry in your .NET applications with zero code changes. Discover more
about the Elastic .NET Agent in <a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-distribution-dotnet-applications">this blog
post</a>.</p>
<p>In the <strong>Payment service</strong>, we've configured the Elastic distribution of the
OpenTelemetry Node.js Agent. The distribution ships with the host-metrics
extension, and Kibana provides a curated service metrics UI. Read more about
the Elastic Node.js Agent
<a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-distribution-node-js">here</a>.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfd1a7d73cfff293b/6a85cb085c2790e01df59b1d/payment_service_host_metrics.png" alt="3 - Payment service host
metrics" /></p>
<p>The <strong>Recommendation service</strong> now leverages the EDOT Python, replacing the
standard OpenTelemetry Python agent. The Python distribution is another example
of a Zero-code (or Automatic) instrumentation, meaning that the distribution
will set up the OpenTelemetry SDK and enable all the recommended
instrumentations for you. Find out more about the Elastic Python Agent in <a href="https://www.elastic.co/observability-labs/blog/elastic-opentelemetry-distribution-python">this
blog
post</a>.</p>
<p>It's important to highlight that Elastic Distributions of OpenTelemetry don't
bundle proprietary software, they have been build on top of the vanilla OTel
SDKs but they offer some advantages, such as single package for installation,
easy auto-instrumentation with reasonable default configuration, automatic logs
telemetry sending, and many more. Along these lines, the ultimate goal is to
contribute as many features from EDOT's back to the upstream OpenTelemetry
agents; they are designed in such a way that the additional features, realized
as extensions, work directly with the OTel SDKs.</p>
<h2 id="collectingdatawiththeelasticcollectordistribution">Collecting Data with the Elastic Collector Distribution</h2>
<p>The OpenTelemetry Demo applications generate and send their signals to an
OpenTelemetry Collector OTLP endpoint. In the Demo's fork, the EDOT collector
is set up to forward all OTLP signals from the microservices to an <a href="https://www.elastic.co/guide/en/observability/current/apm.html">APM
server</a> OTLP
endpoint. Additionally, it sends all other metrics and logs collected by the
collector to an Elasticsearch endpoint.</p>
<p>If the fork is deployed in a Kubernetes environment, the collector will
automatically start collecting the system's metrics. The collector will be
configured to use the <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/hostmetricsreceiver">hostmetrics
receivers</a>
to monitor all the K8s node's metrics, the <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/kubeletstatsreceiver">kuebeletstats
receiver</a>
to retrieve Kubelet's metrics and the <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/filelogreceiver">filelog
receiver</a>,
that will collect all cluster's.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta05b08da80d30cd4/6a85cb0b43c0b760522f0618/node_host_metrics.png" alt="4 - Host
metrics" /></p>
<p>Both the signals generated by the microservices and those collected by the EDOT
collector are enriched with Kubernetes metadata, allowing users to correlate
them seamlessly. This makes it easy to track and observe which Kubernetes nodes
and pods each service is running on, providing deep insights into both
application performance and infrastructure health.</p>
<p>Learn more about the Elastic's OpenTelemetry Collector distribution:
https://www.elastic.co/observability-labs/blog/elastic-distribution-opentelemetry-collector</p>
<h2 id="errordetectionwithelastic">Error detection with Elastic</h2>
<p>The OpenTelemetry Demo incorporates <a href="https://flagd.dev/">flagd</a>, a feature flag
evaluation engine used to simulate error scenarios. For example, the
<code>paymentServiceFailure</code> flag will force an error for every request to the
payment service <code>charge</code> endpoint. Since the service is instrumented with
OpenTelemetry, the error will be captured in the generated traces. We can then
use Kibana's powerful visualization and search tools to trace the error back to
its root cause.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt73f9a645195e575c/6a85cb0eabdc290505122502/payment_error.png" alt="5 - Payment service
error" />
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8f403208700f3316/6a85cb1199083f08ca40f9d3/payment_trace_error.png" alt="6 - Payment service trace
error" /></p>
<p>Another available flag is named <code>adServiceHighCpu</code>, which causes a high CPU
load in the ad service. This increased CPU usage can be monitored either
through the service's metrics or the related metrics of its Kubernetes pod:</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0a990b3b7a69ee30/6a85cb13d7b2e7bbcafe84d4/adservice_high_cpu_error.png" alt="7 - AdService High CPU
error" /></p>
<p>The full list of simulated scenarios can be found at <a href="https://opentelemetry.io/docs/demo/feature-flags/">this
link</a>.</p>
<h2 id="startyourownexploration">Start your own exploration</h2>
<p>Ready to explore the OpenTelemetry Demo with Elastic and its enhanced
observability capabilities? Follow the link to Kibana and begin your own
exploration of how Elastic and OpenTelemetry can transform your approach to
observability.</p>
<p>Live demo: https://ela.st/demo-otel</p>
<p>But that's not all—if you want to take it a step further, you can deploy the
OpenTelemetry Demo directly with your own Elasticsearch stack. Follow the steps
provided <a href="https://github.com/elastic/opentelemetry-demo">here</a> to set it up and
start gaining valuable insights from your own environment.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/opentelemetry-demo-with-the-elastic-distributions-of-opentelemetry</link>
    <guid isPermaLink="false">opentelemetry-demo-with-the-elastic-distributions-of-opentelemetry</guid>
    <category><![CDATA[OpenTelemetry]]></category>
    <dc:creator><![CDATA[Roger Coll]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3f772ca5b5a7535d/6a85cb16bc5bb35d0ef81af9/elastic-oteldemo.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 07 Oct 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>