<?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" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Observability.]]></title><description><![CDATA[Your go-to for in-depth insights on logs, metrics, and traces for modern software and hardware.]]></description><link>https://www.observability.how</link><image><url>https://substackcdn.com/image/fetch/$s_!3y9a!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png</url><title>Observability.</title><link>https://www.observability.how</link></image><generator>Substack</generator><lastBuildDate>Sat, 07 Mar 2026 12:04:49 GMT</lastBuildDate><atom:link href="https://www.observability.how/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Jigar Bhatt]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[hello@observability.how]]></webMaster><itunes:owner><itunes:email><![CDATA[hello@observability.how]]></itunes:email><itunes:name><![CDATA[Jigar Bhatt]]></itunes:name></itunes:owner><itunes:author><![CDATA[Jigar Bhatt]]></itunes:author><googleplay:owner><![CDATA[hello@observability.how]]></googleplay:owner><googleplay:email><![CDATA[hello@observability.how]]></googleplay:email><googleplay:author><![CDATA[Jigar Bhatt]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[🚀 Introducing Observability Architect GPT — Your Copilot for All Things Telemetry]]></title><description><![CDATA[I&#8217;ve been tinkering with AI&#8209;assisted workflows for months, and today I&#8217;m thrilled to announce Observability Architect GPT, now live in ChatGPT.]]></description><link>https://www.observability.how/p/introducing-observability-architect-gpt-your-copilot-for-all-things-telemetry</link><guid isPermaLink="false">https://www.observability.how/p/introducing-observability-architect-gpt-your-copilot-for-all-things-telemetry</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Wed, 23 Jul 2025 04:25:49 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0d6bfc8b-a6e7-47b1-9467-e651d8e34c12_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Tq-R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Tq-R!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Tq-R!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Tq-R!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Tq-R!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Tq-R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&#128640; Introducing Observability Architect GPT &#8212; Your Copilot for All Things Telemetry&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="&#128640; Introducing Observability Architect GPT &#8212; Your Copilot for All Things Telemetry" title="&#128640; Introducing Observability Architect GPT &#8212; Your Copilot for All Things Telemetry" srcset="https://substackcdn.com/image/fetch/$s_!Tq-R!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Tq-R!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Tq-R!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Tq-R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c01ae6b-d357-49e6-8029-bcd0979a0ce7_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>I&#8217;ve been tinkering with AI&#8209;assisted workflows for months, and today I&#8217;m thrilled to announce <strong><a href="https://chatgpt.com/g/g-687f313743108191910a88db99c77c98-observability-architect?ref=observability.how">Observability&#8239;Architect GPT</a></strong>, now live in ChatGPT. Think of it as a drop&#8209;in teammate that speaks fluent metrics, logs, and traces &#8212; and never sleeps.</p><p>Why build it? Because every time someone asks, &#8220;How should I instrument my code for distributed tracing?&#8221; or &#8220;How do I shard Kafka topics for 10&#8239;TB/day of logs?&#8221; Instead of copy&#8209;pasting the same guidance, I encoded my playbooks into a dedicated GPT so <em>anyone</em>&nbsp;can get high&#8209;quality answers instantly.</p><div><hr></div><h2>What can you do with it?</h2><ul><li><p><strong>Green-field design </strong>&#8211; Generate architecture diagrams and component lists for a brand&#8209;new telemetry pipeline (e.g., OpenTelemetry &#8594; Kafka &#8594; Flink &#8594; ClickHouse).</p></li><li><p><strong>Instrument on the fly </strong>&#8211; Spit out ready&#8209;to&#8209;run code snippets for tracing a Spring Boot service, a Node.js Lambda, or a Rust sidecar.</p></li><li><p><strong>Capacity &amp; cost modeling </strong>&#8211; Forecast storage and egress costs from&nbsp;<em>&#8220;We&#8217;ll emit 20k spans/sec with 10 attributes&#8221;</em>&nbsp;to a dollar figure in seconds.</p></li><li><p><strong>SLO &amp; alert tuning </strong>&#8211; Suggest error&#8209;budget policies and alert thresholds that balance reliability and on&#8209;call sanity.</p></li><li><p><strong>Root&#8209;cause brainstorming </strong>&#8211; Walk through failure scenarios (high p99 latency, noisy GC, Kafka backlog) and propose investigative queries in PromQL, LogQL, or SQL.</p></li><li><p><strong>Learning &amp; mentoring </strong>&#8211; Explain, in plain English&nbsp;<em>or</em>&nbsp;deep&#8209;dive RFC&#8209;style, why tail&#8209;based sampling works, how eBPF profiling differs from JFR, or whether to batch or stream your transforms.</p></li></ul><div><hr></div><h3>How to try it</h3><ol><li><p>Open<strong> <a href="https://chatgpt.com/?ref=observability.how">ChatGPT</a></strong></p></li><li><p>Search for <strong>&#8220;Observability&#8239;Architect&#8221;</strong> in the GPT store</p></li><li><p>Start a conversation:&nbsp;<em>&#8220;Design a multi&#8209;tenant metrics pipeline for 5M&#8239;time&#8209;series/sec.&#8221;</em> <a href="https://chatgpt.com/share/68805db4-8cec-8000-bc16-f51a22845166?ref=observability.how">Watch it go to work!</a></p></li></ol><div><hr></div><h3>Join the feedback loop</h3><p>I&#8217;ll keep refining the model with real&#8209;world questions and new patterns. Have a crazy use&#8209;case? Found a blind spot? DM me on <a href="https://www.linkedin.com/in/jigarkb/?ref=observability.how">LinkedIn</a> &#8212; I&#8217;d love to fold your edge cases into the next update.</p><p>Until then, happy instrumenting!</p>]]></content:encoded></item><item><title><![CDATA[Datadog’s Toto: Open-Source Observability Model]]></title><description><![CDATA[Datadog unveils Toto, a 151M-parameter time-series foundation model and BOOM benchmark, sparking a new open-source, AI-driven observability wave.]]></description><link>https://www.observability.how/p/datadogs-toto-open-source-observability-model</link><guid isPermaLink="false">https://www.observability.how/p/datadogs-toto-open-source-observability-model</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Mon, 09 Jun 2025 02:35:34 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0186a69d-6d1f-4214-babb-b2e43d7b99e2_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zmMW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zmMW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!zmMW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!zmMW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!zmMW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zmMW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Datadog&#8217;s Toto: Open-Source Observability Model&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Datadog&#8217;s Toto: Open-Source Observability Model" title="Datadog&#8217;s Toto: Open-Source Observability Model" srcset="https://substackcdn.com/image/fetch/$s_!zmMW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!zmMW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!zmMW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!zmMW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc09683a5-b32b-4b1c-98f9-1e9ee828dfb1_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Toto: Open-Source Observability Model</figcaption></figure></div><p>Recently, Datadog <a href="https://www.datadoghq.com/blog/ai/toto-boom-unleashed/?ref=observability.how">unveiled</a>&nbsp;<strong>Toto</strong>, a new open-source AI foundation model tailored for observability data, alongside a companion benchmark dataset called <strong>BOOM</strong>. Toto is a <strong>time series foundation model (TSFM)</strong>&nbsp;&#8211; essentially to metrics what large language models (LLMs) are to text &#8211; designed to learn from massive telemetry datasets and adapt to a range of monitoring tasks. Both the 151-million-parameter model and the 350-million-point BOOM benchmark have been open-sourced under a permissive license. Toto is&nbsp;<em>the industry&#8217;s first foundation model focused on observability</em>, potentially reshaping how engineers apply AI in monitoring and reliability.</p><div><hr></div><h2><strong>Observability Gets Its Own Foundation Model</strong></h2><p>Toto&#8217;s release is a milestone for the observability and AI communities. By open-sourcing a high-performing model trained on real-world telemetry, Datadog is bridging academic AI advancements with practical infrastructure monitoring needs. <strong>Zero-shot</strong>&nbsp;capabilities are a key highlight &#8211; Toto can flag anomalies or forecast capacity&nbsp;<em>without</em>&nbsp;needing custom per-metric training, an important advantage when dealing with millions of ephemeral time series in cloud environments. In essence, the model has learned generic patterns of how infrastructure and application metrics behave, enabling instant insight on fresh data. For observability engineers, this promises more accurate alerts and predictions with less manual tuning.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G91b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G91b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg 424w, https://substackcdn.com/image/fetch/$s_!G91b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg 848w, https://substackcdn.com/image/fetch/$s_!G91b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!G91b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G91b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg" width="2000" height="826" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:826,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Datadog&#8217;s Toto: Open-Source Observability Model&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Datadog&#8217;s Toto: Open-Source Observability Model" title="Datadog&#8217;s Toto: Open-Source Observability Model" srcset="https://substackcdn.com/image/fetch/$s_!G91b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg 424w, https://substackcdn.com/image/fetch/$s_!G91b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg 848w, https://substackcdn.com/image/fetch/$s_!G91b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!G91b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68425c6f-0c6c-46d2-ad38-698ba9b1a100_2000x826.jpeg 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Toto achieves top-ranked performance on both the observability benchmark (BOOM) and a general time-series test (GIFT-Eval), according to Datadog&#8217;s evaluations. (Keep an eye on follow-up peer reviews or papers)</em></figcaption></figure></div><p>Equally notable is the release of BOOM (Benchmark of Observability Metrics), a comprehensive dataset of 2,800+ real production time series for evaluating models. By publishing this alongside Toto, Datadog provides a standard yardstick for measuring progress on observability AI. It addresses the unique challenges of telemetry data &#8211; high sparsity, spiky outliers, short-lived series &#8211; which typical time-series benchmarks don&#8217;t fully capture. This kind of domain-focused foundation model and benchmark combo could accelerate innovation, allowing researchers and practitioners to iterate on solutions that are directly relevant to operational engineering problems.</p><div><hr></div><h2><strong>How Toto Stacks Up in the AIOps Landscape</strong></h2><p>Toto&#8217;s debut also invites comparison with other efforts to inject AI into DevOps and infrastructure management. Traditionally, AIOps tools have been narrower in scope &#8211; for example, open-source projects like&nbsp;<strong><a href="https://github.com/logpai/loglizer?ref=observability.how">Loglizer</a></strong>&nbsp;apply machine learning to detect anomalies in log files, and platforms like&nbsp;<strong><a href="https://opni.io/?ref=observability.how">Opni</a></strong>&nbsp;use pretrained models to spot unusual patterns in Kubernetes logs and metrics. While useful, these tools are often limited to specific data types or require significant tuning for each use case. In contrast, Toto arrives as a&nbsp;<strong>general-purpose model</strong>&nbsp;for time-series telemetry, pre-trained on a vast corpus of observability data. This makes it more akin to a GPT-style model for ops: a single model that can potentially handle diverse tasks (forecasting, anomaly detection, capacity planning, etc.) out-of-the-box.</p><p>It&#8217;s also noteworthy that many monitoring vendors have offered proprietary AI-assisted features for years (from anomaly alerts to automated root-cause hints), but those models typically operate as black boxes. Datadog&#8217;s open approach with Toto stands out. By releasing the weights and code, they enable the broader community to validate, improve, or repurpose the model beyond Datadog&#8217;s own platform. This openness echoes the trend seen in other domains where open-source foundation models (like computer vision or NLP models) spur faster adoption and innovation compared to closed solutions.</p><div><hr></div><h2><strong>Open Model, Open Opportunities</strong></h2><p>Having a specialized foundation model under Apache 2.0 license means&nbsp;others in the industry can leverage Toto freely. Observability engineers could integrate Toto into their existing toolchains &#8211; for instance, <strong>plugging it into open-source monitoring stacks to get smarter anomaly detection on metrics streams</strong>. Because the model is domain-optimized, it may deliver more relevant results on telemetry data than a generic AI service. Organizations might also fine-tune Toto on their own datasets (e.g. refining it for a particular environment or for predicting specific KPIs), building on its foundation instead of starting from scratch.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;9a4ea15c-3eb4-4659-a7e1-2ff0ac900774&quot;,&quot;caption&quot;:&quot;Goal: Spin up Prometheus+Alertmanager, Loki+Promtail, Jaeger, and Grafana with a single docker&#8209;compose.yml, then watch a tiny Java HTTP service emit metrics, logs, and traces&#8212;all in less than an hour.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Building Your First Observability Stack with Open&#8209;Source Tools&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-27T19:51:17.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5f6f0b4a-10d9-4384-8365-993bd3f038a6_1475x858.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/building-your-first-observability-stack-with-open-source-tools&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843147,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>The release may also encourage collaboration across companies and open-source projects. We could see community-driven improvements to Toto&#8217;s architecture or the emergence of&nbsp;<strong>adjacent models for logs and traces</strong>, applying a similar philosophy to other observability signals. For decision-makers, Toto exemplifies how AI capabilities can be productively shared: a major vendor contributing a state-of-the-art tool back to the community, which others can adopt and even commercialize in new ways. In a space as critical as reliability engineering, this democratization of advanced AI tools is a welcome development. It suggests that AI-powered observability is entering a new phase &#8211; one where&nbsp;<strong>open, shared intelligence</strong>&nbsp;helps everyone keep systems running smoothly.</p><p>The upshot is that Datadog&#8217;s Toto model is more than just a one-off release; it&#8217;s a signal of things to come. As foundation models continue to spread beyond NLP into IT operations, the observability field stands to benefit immensely. Open-source models like Toto provide a common technological base that practitioners, vendors, and researchers alike can build upon. That could accelerate the evolution of AIOps, making sophisticated AI-driven monitoring a standard part of the engineering toolkit across the industry.</p><div class="pullquote"><p>Head over to &#129303; and happy <em>TSFM-ing!</em></p><p><a href="https://huggingface.co/Datadog/Toto-Open-Base-1.0?ref=observability.how">Get Started</a></p></div><p><strong>Sources:</strong>&nbsp;Datadog <a href="https://www.datadoghq.com/blog/ai/toto-boom-unleashed/?ref=observability.how">blog</a> and <a href="https://arxiv.org/pdf/2505.14766?ref=observability.how">paper</a>.</p>]]></content:encoded></item><item><title><![CDATA[Observability for LLMs: Why It Matters and How to Achieve It]]></title><description><![CDATA[Observability is crucial for LLM apps to ensure performance, reliability, and user trust. It involves monitoring metrics, logging prompts, outputs, and user interactions.]]></description><link>https://www.observability.how/p/observability-for-llms</link><guid isPermaLink="false">https://www.observability.how/p/observability-for-llms</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Tue, 27 May 2025 15:00:38 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/af84a01e-868d-45e6-914d-ac1f99950f61_2000x1330.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DkBE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DkBE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg 424w, https://substackcdn.com/image/fetch/$s_!DkBE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg 848w, https://substackcdn.com/image/fetch/$s_!DkBE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!DkBE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DkBE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Observability for LLMs: Why It Matters and How to Achieve It&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Observability for LLMs: Why It Matters and How to Achieve It" title="Observability for LLMs: Why It Matters and How to Achieve It" srcset="https://substackcdn.com/image/fetch/$s_!DkBE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg 424w, https://substackcdn.com/image/fetch/$s_!DkBE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg 848w, https://substackcdn.com/image/fetch/$s_!DkBE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!DkBE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa229357f-ca51-4164-a37f-c41c37217d3a_2000x1330.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Large Language Models (LLMs) like <a href="https://openai.com/index/gpt-4/?ref=observability.how">GPT-4</a> and <a href="https://www.llama.com/?ref=observability.how">Llama</a> are powering a new wave of applications &#8211; from chatbots and coding assistants to search engines and enterprise analytics. However, deploying these LLM-driven applications in production is&nbsp;not&nbsp;a set-and-forget task. LLMs are massive, complex, and often unpredictable systems. Ensuring they perform well, remain reliable, and behave as expected requires robust observability.&nbsp;In this post, we&#8217;ll explore why observability is essential for LLM applications, how to achieve it with the right tools and best practices and a simple demo to get you started!</p><div><hr></div><h2>Why Observability is Essential for LLM Applications</h2><p>Running LLMs in production presents unique challenges compared to traditional software or even classic ML models. These models are&nbsp;<strong>non-deterministic, resource-intensive, and behave like black boxes</strong>, so you often can&#8217;t predict or easily debug their outputs. Observability is crucial in this context because it lets you&nbsp;monitor and understand the system through its outputs and metrics, catching issues early and ensuring a good user experience. Here are some key reasons LLM observability is vital:</p><ul><li><p><strong>Performance and Reliability:</strong>&nbsp;Users expect responsive, reliable AI services. Monitoring metrics like&nbsp;<strong>inference latency, throughput, and error rates</strong>&nbsp;ensures the LLM meets performance SLAs. For example, if latency spikes or the model stops responding, observability alerts you immediately to investigate. High uptime (e.g. 99.95% availability) is often needed in production &#8211; you can&#8217;t achieve that without visibility into system health. Continuous tracking of these metrics lets teams detect degradations and compare against benchmarks to catch regressions early.</p></li><li><p><strong>Quality and Hallucination Detection:</strong>&nbsp;LLMs sometimes produce <strong>incorrect or fabricated answers (&#8220;hallucinations&#8221;)</strong>, or otherwise unsatisfactory outputs. Without observability, these bad outputs might go unnoticed until users report them. By logging and reviewing LLM responses, or by implementing automated checks, teams can catch when the model&#8217;s output is factually wrong, incoherent, or toxic. Observability helps identify patterns of failure &#8211; for instance, if certain prompts consistently lead to nonsense answers or if the model&#8217;s accuracy drifts over time. This is critical for maintaining user trust.</p></li><li><p><strong>Understanding User Interactions:</strong>&nbsp;Observability isn&#8217;t only about the model &#8211; it&#8217;s also about the&nbsp;<strong>user experience</strong>. By recording user prompts, queries, and how the LLM responds, product teams can gain insight into how people are actually using the application. This data reveals user needs, common failure scenarios, and opportunities for improvement. For example, prompt logs might show that users frequently ask questions outside the model&#8217;s knowledge scope &#8211; information that could inform better prompt design or model updates. Tracking <strong>user feedback </strong>(like thumbs-up/down ratings on responses) further closes the loop, highlighting where the LLM is meeting expectations and where it&#8217;s not.</p></li><li><p><strong>Security and Trust:</strong>&nbsp;LLM applications face novel failure modes and security risks.&nbsp;<strong>Prompt injections</strong>&nbsp;(where a user&#8217;s input tricks the model into ignoring its instructions or producing disallowed content) are a real threat. An observability layer can detect anomalous inputs or outputs that indicate such attacks or misuse. Similarly, monitoring can catch when the model outputs sensitive data or biased content, which is crucial for maintaining ethical standards and user trust. For industries under compliance requirements, detailed logs of model decisions and interactions are indispensable &#8211; they provide an audit trail to explain the AI&#8217;s behavior to regulators or to internal risk teams.</p></li><li><p><strong>Cost and Resource Management:</strong>&nbsp;Large language models are&nbsp;<strong>resource-hungry</strong>&nbsp;and, if using third-party APIs, can rack up substantial token costs. Observability enables you to keep an eye on&nbsp;<strong>token usage, CPU/GPU utilization, and memory</strong>&nbsp;in real time. By tracking these, teams can optimize infrastructure and usage patterns to control costs. For instance, you might discover that a particular prompt or user workflow is consuming an unusually high number of tokens or causing excessive load &#8211; a signal to optimize the prompt or scale hardware accordingly. Observability tools help attribute usage and cost to specific features or user segments via tagging, so business owners (e.g. a CTO or product manager) can understand ROI and ensure the LLM&#8217;s operating cost stays within budget.</p></li></ul><p>Without strong observability, you risk flying blind with your LLM in production. Monitoring and logging are the safety net that catches model hallucinations, latency spikes, security incidents, and other issues before&nbsp;they spiral into user-facing problems. They also provide the data to continuously improve the system. Next, let's discuss how to actually achieve this observability in practice.</p><div><hr></div><h2>Achieving Observability for LLMs: Tools and Best Practices</h2><p>Implementing observability for an LLM system means capturing data at multiple levels of the application. Best practices are still emerging, but several key techniques and tools have proven valuable:</p><ul><li><p><strong>Logging Prompts and Outputs (Prompt Analytics):</strong>&nbsp;A fundamental step is to&nbsp;<strong>log every prompt and the model&#8217;s response</strong>, along with relevant metadata. This includes the raw user query or input, any prompt templates or chain-of-thought used, the model&#8217;s outputs, and metadata like timestamps, model version, or prompt ID. Structured logging of prompts and responses is invaluable &#8211; it lets you later search and filter interactions to debug issues or analyze trends. For example, you can query logs to find all instances where the model answered &#8220;I don&#8217;t know&#8221; or produced an error, then examine what prompts caused it. Prompt analytics involves aggregating this log data to answer questions like:&nbsp;<em>Which prompts are most common? What categories of user questions lead to the longest responses or highest error rate?</em>&nbsp;By tracking prompt usage and outcomes, you can refine your prompt templates and&nbsp;<strong>A/B test</strong>&nbsp;prompt variations to see which yield better answers or lower latency.&nbsp;<strong>User feedback</strong>&nbsp;should also be logged and tied to the corresponding prompts/responses &#8211; even simple thumbs-up/down signals can highlight problematic outputs and guide prompt or model improvements.</p></li><li><p><strong>End-to-End Tracing of LLM Workflows:</strong>&nbsp;Logging alone may not show how a request flows through a complex LLM application, especially if your app involves multiple steps (retrieval, calling external APIs or tools, chaining multiple model calls, etc.).&nbsp;<strong>Distributed tracing</strong>&nbsp;is the practice of capturing a single transaction&#8217;s path through the system. In an LLM app, a trace might start when a user question arrives, include a vector database retrieval step, then the LLM generation step, and finally any post-processing before a response is returned. Each step is recorded as a&nbsp;<strong>span</strong>&nbsp;with timing and metadata. Tracing is crucial for debugging multi-component chains: it helps isolate where bottlenecks occur (e.g. a slow database lookup or an LLM call waiting on an external API), and why a chain might be failing or looping. Modern LLM frameworks like <a href="https://docs.smith.langchain.com/observability?ref=observability.how">LangChain</a> and <a href="https://docs.llamaindex.ai/en/stable/module_guides/observability?ref=observability.how">LlamaIndex</a> support tracing of their chains, and there are standards like&nbsp;<strong>OpenTelemetry</strong>&nbsp;(with initiatives such as <a href="https://github.com/traceloop/openllmetry?ref=observability.how">OpenLLMetry</a>/<a href="https://openlit.io/?ref=observability.how">OpenLIT</a>) to standardize LLM tracing across tools. Setting up tracing typically involves instrumenting your code or using middleware that records spans automatically. The result is a&nbsp;<strong>rich trace</strong>&nbsp;that can be visualized for each user query.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8kFN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8kFN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png 424w, https://substackcdn.com/image/fetch/$s_!8kFN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png 848w, https://substackcdn.com/image/fetch/$s_!8kFN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png 1272w, https://substackcdn.com/image/fetch/$s_!8kFN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8kFN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png" width="2000" height="1156" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1156,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Observability for LLMs: Why It Matters and How to Achieve It&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Observability for LLMs: Why It Matters and How to Achieve It" title="Observability for LLMs: Why It Matters and How to Achieve It" srcset="https://substackcdn.com/image/fetch/$s_!8kFN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png 424w, https://substackcdn.com/image/fetch/$s_!8kFN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png 848w, https://substackcdn.com/image/fetch/$s_!8kFN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png 1272w, https://substackcdn.com/image/fetch/$s_!8kFN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fecfeaf-b0e4-4da0-ae17-c755d8b1e224_2000x1156.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Example of a trace visualization for an LLM-powered application (from LangSmith, LangChain&#8217;s observability tool)&nbsp;</em></figcaption></figure></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;b56eb43e-2ce3-445a-affb-dbc304f78e07&quot;,&quot;caption&quot;:&quot;OpenTelemetry (OTel) has quickly become a cornerstone of modern observability. If you&#8217;re a developer or engineer looking to instrument your applications for better insight, this beginner&#8217;s guide is for you. I&#8217;ll explain what OpenTelemetry is, why it matters, and walk through a step-by-step tutorial to instrument a simple Java app with basic traces and m&#8230;&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Getting Started with OpenTelemetry (OTel 101)&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-14T23:52:17.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49466716-1518-43e8-bb40-da1c66482077_1972x692.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/getting-started-with-opentelemetry-otel-101&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843149,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><ul><li><p><strong>Monitoring Performance Metrics:</strong>&nbsp;In addition to logs and traces, you should collect quantitative&nbsp;<strong>metrics</strong>&nbsp;on the LLM&#8217;s performance and resource usage. Common metrics include&nbsp;<strong>latency</strong>&nbsp;(how long each request or each step takes),&nbsp;<strong>throughput</strong>&nbsp;(requests processed per second),&nbsp;<strong>token usage</strong>&nbsp;per request (input and output tokens, which often correlates with latency and cost), and&nbsp;<strong>error rates</strong>&nbsp;(how often the model fails to return a result or triggers an exception). Resource metrics like&nbsp;<strong>CPU/GPU utilization, memory usage, and GPU VRAM</strong>&nbsp;are also important to ensure your infrastructure isn&#8217;t becoming a bottleneck. Observability systems (whether <a href="https://www.observability.how/building-your-first-observability-stack-with-open-source-tools/">custom</a> or via existing APM tools) should be set up to track these over time and trigger alerts on abnormal spikes. For example, you might set an alert if the 95th percentile latency exceeds a threshold, or if token usage per response suddenly doubles (which could indicate the model is rambling or not grounding answers properly). Monitoring these metrics in real time allows for proactive scaling decisions and performance tuning.</p></li><li><p><strong>Automated Evaluation and Drift Detection:</strong>&nbsp;One of the hardest parts of LLM observability is measuring&nbsp;<strong>output quality</strong>, because for many queries there&#8217;s no single correct answer. Nonetheless, it&#8217;s important to track proxies for quality and detect when the model&#8217;s responses start to deteriorate or deviate from desired behavior. This can be done via&nbsp;<strong>LLM evaluations</strong>&nbsp;&#8211; automatically scoring or classifying model outputs on certain criteria. Some approaches include using a separate AI judge model to rate responses for correctness/relevance, comparing answers to a set of curated reference answers, or logging&nbsp;<strong>user ratings</strong>&nbsp;as a direct quality signal. For instance, you might periodically feed the model a set of test questions (with known good answers or using an AI evaluator) to compute an accuracy or coherence score over time. A drop in these scores would flag a potential&nbsp;<strong>model drift</strong>&nbsp;issue. <strong>Drift detection</strong>&nbsp;is crucial: over time, the distribution of user queries may shift, or if you&#8217;re pulling a model from an API, the provider might update it behind the scenes, causing behavior changes. If an LLM that once answered correctly is now frequently wrong on the same kind of question, that&#8217;s a red flag. To catch these issues, implement regular checks such as: track the percentage of &#8220;good&#8221; vs &#8220;bad&#8221; responses per day (using whatever quality metric you define), monitor the distribution of response lengths or languages (since abnormal lengths or gibberish might indicate a problem), and examine whether new user inputs are falling outside the model&#8217;s previously seen domain. The goal is to surface quality issues early so you can retrain models, adjust prompts, or roll out fixes before users churn.</p></li><li><p><strong>Retrieval &amp; External Data Monitoring:</strong>&nbsp;A large portion of LLM applications today use&nbsp;<strong>Retrieval-Augmented Generation (RAG)</strong>&nbsp;or other external tools to ground the model with up-to-date or domain-specific information. In these systems, observability needs to extend to those external components as well. If your LLM fetches context from a vector database or calls a web API, you should monitor the&nbsp;<strong>quality and timing</strong>&nbsp;of those operations. For example, track the relevance of retrieved documents (perhaps by logging retrieval scores or performing a secondary check on whether the answer actually used the docs), and track failures or timeouts in the retrieval process. An observability solution might let you trace and analyze retrieval steps similarly to LLM calls. This is important because if retrieval fails silently or returns irrelevant data, the model&#8217;s output will suffer even though the model itself is fine. By analyzing this, you might decide to tweak your vector index, improve the embedding model, or adjust your retrieval strategy.</p></li><li><p><strong>Using the Right Tools and Platforms:</strong>&nbsp;Achieving all of the above can be complex, but fortunately a number of tools have emerged to help. Many teams start with a combination of existing observability tools (like logging platforms or APM dashboards) and some custom scripts, but there are now purpose-built <strong>LLM Observability platforms</strong>. For example, open-source libraries like <strong><a href="https://phoenix.arize.com/?ref=observability.how">Arize Phoenix</a></strong>&nbsp;or&nbsp;<strong>LangChain&#8217;s LangSmith</strong>&nbsp;SDK can instrument your LLM app to automatically capture prompts, traces, token counts, and even run evaluations. Other tools like&nbsp;<strong>Langfuse</strong>&nbsp;and&nbsp;<strong>Helicone</strong>&nbsp;provide hosted solutions to log and visualize LLM usage with minimal integration effort. These platforms often offer UIs to explore traces, prompt management interfaces, and analytics specifically designed for LLM use cases. When implementing LLM observability, it&#8217;s a good practice to leverage such frameworks and standards (e.g. use OpenTelemetry for traces, use existing SDKs for your LLM framework) rather than reinventing the wheel. The field is evolving quickly, and tools will continue to adapt as new best practices emerge.</p></li></ul><div><hr></div><h2>Demo: LangChain + OpenTelemetry</h2><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;fa7b9dbd-d635-4dcb-b63c-8f7a7575b4bc&quot;,&quot;caption&quot;:&quot;Goal: Spin up Prometheus+Alertmanager, Loki+Promtail, Jaeger, and Grafana with a single docker&#8209;compose.yml, then watch a tiny Java HTTP service emit metrics, logs, and traces&#8212;all in less than an hour.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Building Your First Observability Stack with Open&#8209;Source Tools&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-27T19:51:17.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5f6f0b4a-10d9-4384-8365-993bd3f038a6_1475x858.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/building-your-first-observability-stack-with-open-source-tools&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843147,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Let's look at a demo example of instrumenting traces in your LLM application:</p><h3>1 &#8211; Configure your environment</h3><pre><code>export LANGSMITH_OTEL_ENABLED=true
export LANGSMITH_TRACING=true
# This example uses OpenAI, but you can use any LLM provider of choice
export OPENAI_API_KEY=&lt;your-openai-api-key&gt;</code></pre><h3>2 &#8211; Trace LangChain workflow with OpenTelemetry</h3><pre><code>"""Minimal example that traces a LangChain workflow with OpenTelemetry."""
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

# 1&#65039;&#8419;  Configure OpenTelemetry
resource = Resource.create({"service.name": "llm-demo"})
provider = TracerProvider(resource=resource)
provider.add_span_processor(
    BatchSpanProcessor(OTLPSpanExporter())
)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)

# 2&#65039;&#8419;  Build a LangChain
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = PromptTemplate.from_template("Translate to French:\n\n{input}")
chain = prompt | llm

# 3&#65039;&#8419;  Invoke within a parent span for full end&#8209;to&#8209;end context
with tracer.start_as_current_span("user_translate_request") as span:
    result = chain.invoke({"input": "Hello, how are you?"})
    print(result)</code></pre><h3>3 &#8211; View your Trace</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vnhH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vnhH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png 424w, https://substackcdn.com/image/fetch/$s_!vnhH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png 848w, https://substackcdn.com/image/fetch/$s_!vnhH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png 1272w, https://substackcdn.com/image/fetch/$s_!vnhH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vnhH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png" width="2000" height="1153" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1153,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Observability for LLMs: Why It Matters and How to Achieve It&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Observability for LLMs: Why It Matters and How to Achieve It" title="Observability for LLMs: Why It Matters and How to Achieve It" srcset="https://substackcdn.com/image/fetch/$s_!vnhH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png 424w, https://substackcdn.com/image/fetch/$s_!vnhH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png 848w, https://substackcdn.com/image/fetch/$s_!vnhH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png 1272w, https://substackcdn.com/image/fetch/$s_!vnhH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc18e2c09-a6cb-40f3-bc33-1d8d8f889e1b_2000x1153.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">End-to-End Tracing of LLM Demo app visualized in Grafana</figcaption></figure></div><div><hr></div><p><strong>Make observability a first-class concern</strong>&nbsp;when building LLM applications. Instrument early and extensively &#8211; it will save you countless hours of debugging and help ensure your application delivers consistent value to users. As LLM technology and usage evolve, so will observability practices. The organizations that succeed with AI will be those that treat observability as an integral part of their LLM deployment strategy, giving them the confidence to scale these powerful models responsibly and effectively. <em>Happy Prompting!</em></p>]]></content:encoded></item><item><title><![CDATA[Building an In-House Observability Platform with a Data Lake (AWS S3 + Apache Iceberg)]]></title><description><![CDATA[In-house observability with data lake: unify metrics, logs & traces on AWS S3 + Iceberg to slash cost, dodge vendor lock-in & boost analytics.]]></description><link>https://www.observability.how/p/building-an-in-house-observability-platform-with-a-data-lake</link><guid isPermaLink="false">https://www.observability.how/p/building-an-in-house-observability-platform-with-a-data-lake</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Fri, 16 May 2025 20:01:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0b5ddb4c-3da0-4701-9f0e-16759a644188_2000x1216.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!b71x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!b71x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png 424w, https://substackcdn.com/image/fetch/$s_!b71x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png 848w, https://substackcdn.com/image/fetch/$s_!b71x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!b71x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!b71x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Building an In-House Observability Platform with a Data Lake (AWS S3 + Apache Iceberg)&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Building an In-House Observability Platform with a Data Lake (AWS S3 + Apache Iceberg)" title="Building an In-House Observability Platform with a Data Lake (AWS S3 + Apache Iceberg)" srcset="https://substackcdn.com/image/fetch/$s_!b71x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png 424w, https://substackcdn.com/image/fetch/$s_!b71x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png 848w, https://substackcdn.com/image/fetch/$s_!b71x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!b71x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe666bd82-5ad4-411b-9b1c-0a3ed3316468_2000x1216.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">In-house observability platform using a data lake.</figcaption></figure></div><p>Observability &#8211; encompassing logs, metrics, and traces &#8211; is the nervous system of modern IT operations. But it comes at a cost. As cloud-native applications and microservices proliferate,&nbsp;<strong>the volume of telemetry data has exploded</strong>. Companies using traditional SaaS observability platforms (Datadog, New Relic, Splunk, etc.) often face&nbsp;<em>skyrocketing bills &#128184;</em>&nbsp;and fragmented data silos &#9939;&#65039;&#8205;&#128165;. In fact, at large scales (hundreds of GB/day of logs), SaaS tools can cost&nbsp;<strong>hundreds of thousands to millions of dollars per year</strong>. Beyond cost, relying on vendors means your valuable operational data lives in someone else&#8217;s platform, potentially limiting how you can analyze or retain it.</p><p>An emerging solution is to&nbsp;<strong>build an in-house observability platform backed by a unified data lake</strong>&nbsp;&#8211; typically using Amazon S3 for cheap, durable storage and Apache Iceberg as the table format for reliable data management. <em><a href="https://thenewstack.io/observability-without-a-data-lake-might-no-longer-work/?ref=observability.how">Data lakes have become a necessity for effective observability</a></em>, serving as a single repository for all telemetry and enabling deep analytics and AI-driven insights not possible with siloed tools. By combining open telemetry standards with an open data architecture, enterprises can finally&nbsp;<strong>own their observability data</strong>&nbsp;instead of handing it over to a vendor. This blog post explores why an S3 + Iceberg data lake approach can be a game-changer for observability, the benefits and trade-offs to consider, and how to present a compelling case to both technical leaders and executives.</p><div><hr></div><h2>Why Use a Data Lake for Logs, Metrics, and Traces?</h2><p>Traditional observability stacks often segregate data types: logs in one system, metrics in another, tracing in yet another. This&nbsp;<strong>fragmentation</strong>&nbsp;makes it hard to correlate issues across different signals and typically requires expensive licenses for each tool. In contrast, a data lake approach centralizes&nbsp;<em>all telemetry data in one place</em>, eliminating data silos. For example, instead of sending logs to a log analytics SaaS and metrics to a time-series database,&nbsp;<strong>all data lands in S3</strong>&nbsp;in raw or parquet format, tracked by Iceberg tables. This unification allows powerful cross-domain queries &#8211; you can join traces with logs or metrics in a single SQL query &#8211; something nearly impossible across disparate SaaS tools.</p><p>Cost is a driving factor. Cloud object storage like S3 is&nbsp;<em>extremely cheap</em>&nbsp;compared to vendor retention costs. Storing 1 TB of data on S3 costs on the order of&nbsp;<strong>$23 per month</strong>&nbsp;(and even less on colder tiers), whereas ingesting that much data into a SaaS platform can cost orders of magnitude more. As <a href="https://blog.scanner.dev/how-not-to-spend-half-a-million-dollars-on-logs/?ref=observability.how">one analysis</a> showed, ingesting ~700 GB of logs per day (&#8776;250 TB/year) would incur&nbsp;<strong>over $500,000 per year</strong>&nbsp;with typical log management tools. Datadog, for instance, might charge ~$0.10 per GB ingested &#8211; which sounds low &#8211;&nbsp;<em>but</em>&nbsp;about&nbsp;<strong>$2.50 per million log events indexed</strong>, leading to an annual cost in the millions for full fidelity data. In an S3 + Iceberg data lake, that same 250 TB/year could be stored for a fraction of the cost (on the order of ~$70k/year in S3 storage), and querying it with a tool like Athena (Presto SQL at $5 per TB scanned) might only add tens of thousands more. In short,&nbsp;<strong>moving observability data to your own S3-based lake can cut storage and query costs by 50&#8211;90%</strong>&nbsp;in many cases. This cost efficiency means you can&nbsp;<em>afford</em>&nbsp;to retain full-resolution telemetry for much longer &#8211;&nbsp;<strong>months or years instead of weeks</strong>&nbsp;&#8211; without breaking the bank.</p><p>Another motivation is&nbsp;<strong>flexibility for analytics and AI/ML</strong>. A data lake in an open format unlocks your telemetry data for any kind of analysis. You&#8217;re not limited to whatever queries or dashboards a vendor provides. Data scientists can run Python notebooks, BI teams can join observability data with business data, and you can apply machine learning to detect anomalies or predict incidents. In fact, achieving maximum observability is increasingly tied to applying AI/ML to large telemetry datasets &#8211; something that practically&nbsp;<em>requires</em>&nbsp;a data lake with rich historical data. With S3 + Iceberg, building custom anomaly detectors or feeding data to an AI assistant (like an LLM that can sift through logs) becomes much easier, since all the data is accessible via standard SQL and data science tools.</p><p>Finally,&nbsp;<strong>data ownership and compliance</strong>&nbsp;drive the in-house approach. By keeping observability data in your own AWS account (your S3 buckets), you maintain full control over security, access policies, and compliance requirements. There&#8217;s no need to ship potentially sensitive logs (which may contain customer data or secrets) to a third party. In essence, an observability data lake lets you treat telemetry as a first-class data asset that you own, rather than a byproduct you offload to a vendor.</p><div><hr></div><h2>Benefits of a Data Lake Architecture (S3 + Apache Iceberg)</h2><p>Building your observability platform on <a href="https://aws.amazon.com/s3/?ref=observability.how">S3</a> and <a href="https://iceberg.apache.org/?ref=observability.how">Apache Iceberg</a> comes with a host of advantages:</p><ul><li><p><strong>Unified Storage &amp; Single Source of Truth:</strong>&nbsp;All logs, metrics, traces, and even related events are stored together in a&nbsp;<strong>central data lake</strong>, rather than spread across separate tools. This makes it trivial to correlate across data types &#8211; e.g. linking a spike in CPU (metric) with a specific error in logs and the corresponding trace &#8211; using one query interface. Engineers and SREs no longer have to swivel-chair between systems, speeding up root cause analysis.</p></li><li><p><strong>Massive Cost Savings:</strong>&nbsp;Object storage is&nbsp;<strong>dramatically cheaper</strong>&nbsp;than SaaS retention. You pay roughly ~$0.023 per GB-month on S3, versus SaaS platforms that charge by ingestion volume (often $2&#8211;$3&nbsp;<em>per</em>&nbsp;GB ingested or substantial per-host fees). Iceberg allows you to use this cheap storage without sacrificing queryability. Moreover, you avoid vendor &#8220;overage&#8221; penalties and can use cloud-native cost controls (like S3 lifecycle policies or reserved capacity) for further savings. In short,&nbsp;<strong>you can retain more data for longer</strong>&nbsp;without budget angst.</p></li><li><p><strong>Open Format &amp; No Vendor Lock-In:</strong>&nbsp;Apache Iceberg is an&nbsp;<strong>open-source table format</strong>&nbsp;backed by a broad community. Data is stored in open columnar files (Parquet/ORC) on S3 and tracked with Iceberg&#8217;s metadata layer. This means your observability data is not locked into any proprietary system &#8211; many engines (Spark, Trino, Flink, Presto, etc.) can read it out-of-the-box. By using open ingestion standards like <a href="https://www.observability.how/getting-started-with-opentelemetry-otel-101/">OpenTelemetry</a> and an open storage format, you ensure&nbsp;<strong>your data remains portable and accessible</strong>. This alleviates the classic concern of being stuck with a single vendor&#8217;s tool or paying exorbitant fees to get your own data back later.</p></li><li><p><strong>Schema Evolution and Flexibility:</strong>&nbsp;Observability data schemas change as applications evolve &#8211; new log fields appear, metric names change, etc. Apache Iceberg&nbsp;<strong>supports in-place schema evolution</strong>, so you can add or remove fields without painful re-partitioning or losing historical data. This is critical in a fast-moving DevOps environment where telemetry formats aren&#8217;t static. Iceberg tables also handle semi-structured data well (e.g. logs with nested JSON) by storing them in flexible columnar form. You get the&nbsp;<em>best of both worlds</em>: schema when you need it for structured queries, but tolerance for evolving data shapes.</p></li><li><p><strong>ACID Transactions &amp; Data Integrity:</strong>&nbsp;Unlike raw data lakes of old, Iceberg brings&nbsp;<strong>database-like reliability</strong>&nbsp;to your S3 storage. It provides&nbsp;<strong>ACID transactions</strong>&nbsp;even as many writers stream data concurrently. For observability, this means you won&#8217;t end up with partial or corrupt data in an incident timeline &#8211; e.g. a trace&#8217;s spans can be committed atomically along with the related logs. Consistency is guaranteed, which is essential when you rely on this data to make critical decisions during outages. Iceberg&#8217;s design (immutable files with a transactional metadata layer) was specifically created to solve data lake consistency and &#8220;small file&#8221; problems at scale.</p></li><li><p><strong>Performance &amp; SQL Query Power:</strong>&nbsp;Modern &#8220;lakehouse&#8221; tech like Iceberg closes much of the performance gap between a data lake and specialized query engines. Features like hidden partitioning, column statistics for&nbsp;<strong>predicate pushdown</strong>, and query planning based on metadata allow even huge tables to be queried efficiently. With the right cluster or query service, <a href="https://medium.com/@jaydav/apache-iceberg-and-modern-data-lakes-4b4656a67ee6?ref=observability.how">teams have achieved interactive query speeds on Iceberg</a> that&nbsp;<em>rival dedicated time-series databases</em>&nbsp;&#8211; all while using standard SQL and without the cost overhead. In practice, you might use a query engine like Trino or Amazon Athena to get sub-second to seconds response on recent data, and Spark for heavy batch analyses. Furthermore, Iceberg supports&nbsp;<strong>time-travel queries</strong>&nbsp;(querying data as of a past point in time), which is incredibly useful for comparing today&#8217;s system behavior to last week&#8217;s or performing incident post-mortems on historical states.</p></li><li><p><strong>Long-Term Retention &amp; Analytics/ML Friendly:</strong>&nbsp;Because of the low storage cost and flexible schema, you can&nbsp;<strong>retain raw observability data long-term</strong>&nbsp;&#8211; far beyond the 30-90 day window many SaaS tools offer. This unlocks rich historical analysis for capacity planning, security forensics, and feeding machine learning models. For example, you might store&nbsp;<em>years</em>&nbsp;of logs and use Spark MLlib or Pandas on a subset to train anomaly detection models specific to your environment. Essentially, your data lake can become the <strong>foundation for AI-driven observability</strong>, where algorithms mine the trove of data to surface insights that no human would easily spot in real-time streams.</p></li></ul><p>In summary, an S3 + Iceberg observability platform promises&nbsp;<strong>centralization, cost efficiency, flexibility, and control</strong>. It lets you do more with your data (because you own it and can apply any tools to it) at a lower cost, while leveraging cutting-edge open technology to maintain performance and reliability.</p><div><hr></div><h2>Architecture Overview: From Data Generation to Analytics</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Al0s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Al0s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png 424w, https://substackcdn.com/image/fetch/$s_!Al0s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png 848w, https://substackcdn.com/image/fetch/$s_!Al0s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!Al0s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Al0s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png" width="2000" height="1216" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1216,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Building an In-House Observability Platform with a Data Lake (AWS S3 + Apache Iceberg)&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Building an In-House Observability Platform with a Data Lake (AWS S3 + Apache Iceberg)" title="Building an In-House Observability Platform with a Data Lake (AWS S3 + Apache Iceberg)" srcset="https://substackcdn.com/image/fetch/$s_!Al0s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png 424w, https://substackcdn.com/image/fetch/$s_!Al0s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png 848w, https://substackcdn.com/image/fetch/$s_!Al0s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!Al0s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5bef06c7-4694-4410-b267-6daccc7566a3_2000x1216.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>High-level architecture of an in-house observability platform using a data lake.</em></figcaption></figure></div><p>In this design,&nbsp;<strong>telemetry sources </strong>(applications, microservices, hosts, etc.) emit logs, metrics, and traces which are collected by a flexible pipeline (often using the <strong><a href="https://www.observability.how/using-the-opentelemetry-collector-a-practical-guide/">OpenTelemetry Collector</a></strong>&nbsp;or similar agents). Data can be streamed in near-real-time via Kafka, Kinesis Data Firehose, or Fluent Bit, and landed into Amazon S3 in an optimized columnar format (Parquet files partitioned by time). Using Apache Iceberg&#8217;s table layer on S3, these raw files are tracked as&nbsp;<strong>managed tables</strong> with schema and partitions.</p><p>Ingesting data might be done through a streaming ETL job &#8211; for example, an <a href="https://flink.apache.org/?ref=observability.how">Apache Flink</a> job reading off Kafka and writing to Iceberg, or simply using AWS Glue&nbsp;<strong>batch jobs</strong>&nbsp;to regularly compact and organize incoming data. The&nbsp;<strong>Iceberg table format</strong>&nbsp;ensures each new batch or stream write is transactional and immediately queryable. You might have separate Iceberg tables for logs, metrics, and traces (to optimize each appropriately), or even a single wide table linking all telemetry types (depending on your strategy).</p><p>On the query side, various&nbsp;<strong>compute engines</strong>&nbsp;can be used to analyze the data lake. For ad-hoc queries and dashboards, teams often use&nbsp;<strong>SQL engines like <a href="https://trino.io/?ref=observability.how">Trino</a> (Presto) or Amazon Athena</strong>&nbsp;to run fast analytic SQL directly against the Iceberg tables. These engines understand the Iceberg table metadata, so they can read only the relevant partitions and data (for example, scanning just one day of logs, or a specific service&#8217;s metrics) to answer a query efficiently. For more complex processing or machine learning,&nbsp;<strong>Apache Spark</strong>&nbsp;can be used to load large volumes from S3 and perform distributed computations (Spark also has native Iceberg support for reading and writing). The query results can feed into familiar <strong>observability tools and visualizations</strong>&nbsp;&#8211; for instance, you can connect Athena or Trino to Amazon QuickSight or <a href="https://grafana.com/grafana/?ref=observability.how">Grafana</a> to create dashboards, or build internal tools that query the data lake for on-demand investigations. Alerts can be defined as SQL queries running on a schedule, detecting patterns in the data lake (e.g. a sudden drop in requests or an error code surge).</p><p>This architecture essentially decouples storage and compute: S3 + Iceberg is your durable, scalable&nbsp;<strong>storage layer</strong>, and you can scale out the&nbsp;<strong>compute/query layer</strong>&nbsp;as needed (from small on-demand queries to large batch jobs). Importantly, since all data is in one place, analytics that were difficult with siloed SaaS tools become straightforward. For example, a single&nbsp;<strong>JOIN across metrics and logs</strong>&nbsp;could be done in Trino to correlate a metric anomaly with specific log entries &#8211; something that might require exporting data from multiple SaaS tools (if even possible) in the old model. Many organizations are recognizing these benefits; even AWS has introduced services like <a href="https://aws.amazon.com/security-lake/?ref=observability.how">Amazon Security Lake</a> which&nbsp;<em>&#8220;centralizes security data&#8221;</em>&nbsp;&#8211; a sign that the data lake pattern is the future of broad observability and analytics.</p><div><hr></div><h2>Implementation Example: Storing Observability Data in an Iceberg Table</h2><p>One of the advantages of an open data architecture is that it uses common technologies and skills (e.g. SQL, Spark) rather than proprietary APIs. As a brief example, here&#8217;s how you could store incoming log events into an Iceberg table using PySpark:</p><pre><code># Configure Spark to use an Iceberg Catalog (could be Glue or Hadoop based catalog)
spark.conf.set("spark.sql.catalog.my_iceberg", "org.apache.iceberg.spark.SparkCatalog")
spark.conf.set("spark.sql.catalog.my_iceberg.type", "hadoop")  # using Hadoop catalog for simplicity
spark.conf.set("spark.sql.catalog.my_iceberg.warehouse", "s3://my-observability-bucket/iceberg_warehouse")

# Imagine we have a DataFrame of parsed log events with schema (timestamp, level, message, attributes...)
logs_df = ...  # obtained from reading a stream or batch of logs

# Write the DataFrame into an Iceberg table (partitioning by date for efficiency)
logs_df.write.format("iceberg") \
    .mode("append") \
    .partitionBy("date") \
    .save("my_iceberg.observability_logs")  # Catalog.table identifier
</code></pre><p>In the above snippet, Spark is configured with an Iceberg catalog pointing to an S3 location. The&nbsp;<code>logs_df</code>&nbsp;(which could have been created by reading JSON log files or via a streaming source) is written in&nbsp;<strong>Iceberg format</strong>&nbsp;into the <code>observability_logs</code>&nbsp;table, partitioned by date. Under the hood, this creates Parquet files in S3 and maintains Iceberg metadata (in S3 or AWS Glue) about file locations, schema, and snapshots. Once this is done, the new log data is immediately available to query via any Iceberg-compatible engine. For instance, the same data could be queried in Amazon Athena with a SQL statement (<code>SELECT * FROM observability_logs WHERE date='2025-05-15' AND level='ERROR' ...</code>) or via Trino using the Iceberg connector. Metrics and traces can be handled similarly &#8211; e.g., metrics might be aggregated into minute-level time buckets and stored in an Iceberg table partitioned by service and date.</p><p>The code above illustrates that&nbsp;<strong>building on Iceberg doesn&#8217;t require reinventing the wheel</strong>&nbsp;&#8211; you leverage big data frameworks to handle the heavy lifting. The heavy-duty aspects (like small file compaction, partition management, schema handling) are abstracted away by Iceberg&#8217;s table format. This means your team can focus on defining what data to collect and how to use it, rather than low-level storage mechanics.</p><div><hr></div><h2>Comparing In-House Data Lake vs. SaaS Observability Platforms</h2><p>It&#8217;s important to acknowledge trade-offs and differences between an in-house data lake approach and traditional SaaS observability solutions:</p><ul><li><p><strong>Cost Structure:</strong>&nbsp;SaaS platforms typically charge per host, per GB ingested, or per query &#8211; and these costs scale&nbsp;<em>non-linearly</em>&nbsp;at high volumes. As discussed, logs especially become prohibitively expensive at scale (e.g. Datadog could run&nbsp;<strong>&gt;$3M/year for ~250TB of logs</strong>&nbsp;if fully indexed). The data lake model shifts the cost to cloud infrastructure (storage and on-demand compute).&nbsp;<strong>Storage is cheap (S3) and effectively pay-as-you-go</strong>, and compute/query costs are usage-based. This often results in an order-of-magnitude reduction in total cost for large environments. However, it also means you incur operational costs directly (which you manage) instead of a flat SaaS bill. An executive-friendly way to frame this:&nbsp;<em>we&#8217;re turning a recurring high SaaS fee into a much lower cloud infrastructure cost that we control</em>. Plus, any existing cloud spend commitments (AWS enterprise discounts, credits) now work in your favor.</p></li><li><p><strong>Performance and Latency:</strong>&nbsp;SaaS observability tools are often optimized for very fast queries on recent data (e.g. a Splunk search or Datadog query might return in seconds on indexed data). A data lake, by contrast, trades some latency for cost and flexibility. Scanning data on S3 via SQL might take a few seconds or even tens of seconds for complex queries, whereas an in-memory time-series database might be instantaneous. For many troubleshooting and analysis tasks, a few seconds is acceptable &#8211; but for real-time alerting on high-frequency metrics, you might still need to incorporate a real-time processing layer or caching. Combine the two: e.g., ingest into a fast&nbsp;<strong>OLAP store (like Apache Pinot)</strong>&nbsp;for recent data to achieve sub-second query latencies, while simultaneously archiving all data to Iceberg on S3 for long-term analysis. This hybrid approach ensures alerts and dashboards are snappy, while the data lake serves deeper analytical needs. The key point to convey is that&nbsp;<em>the Iceberg data lake can approximate the performance of specialized stores for many queries</em>, but extremely low-latency needs may require additional architecture considerations. Executives should understand there&#8217;s a trade-off:&nbsp;<strong>blazing-fast queries vs. cost &#8211;</strong>&nbsp;and the in-house solution seeks a balance that dramatically lowers cost while keeping query performance reasonable for most purposes.</p></li><li><p><strong>Feature Richness and Ease of Use:</strong>&nbsp;Companies like Datadog and New Relic offer polished UI experiences, out-of-the-box integrations, and turn-key alerting. An in-house data lake will require assembling or building those user-facing components. Engineers will likely use tools like Grafana or custom UIs on top of the data lake for visualization and alerting. While this gives ultimate flexibility (you can design exactly the views and correlations you need), it is an area where&nbsp;<strong>initial development effort</strong>&nbsp;is higher. Fortunately, the ecosystem is growing &#8211; for example, you can plug the data lake into Grafana for dashboards, use SQL-based alerting tools, and leverage open-source front-ends. Still, expect to invest engineering time to achieve the smooth UX of a SaaS platform. On the flip side, your in-house platform can be tailored to your organization&#8217;s needs (custom metrics, business context, etc.), whereas SaaS tools are one-size-fits-all.</p></li><li><p><strong>Data Ownership &amp; Compliance:</strong>&nbsp;With SaaS, you are effectively outsourcing data storage and must trust the vendor&#8217;s security and compliance. With an in-house S3-based lake,&nbsp;<strong>you own the data</strong>&nbsp;end-to-end &#8211; which can ease compliance audits and allow stricter security controls. For industries with stringent data governance (finance, healthcare), keeping observability data in-house can be a big advantage. Also, if you ever decide to switch tools or vendors, having all data in open formats on S3 means you won&#8217;t lose historical telemetry or face costly data migrations. This ownership principle is a significant strategic benefit.</p></li><li><p><strong>Scalability and Future-Proofing:</strong>&nbsp;SaaS platforms abstract away scalability (at a high price), whereas with a DIY data lake you&#8217;ll design for scale from the start. The good news is technologies like Iceberg are&nbsp;<strong>built for petabyte scale</strong>&nbsp;(originating from <a href="https://github.com/Netflix/iceberg?ref=observability.how">Netflix&#8217;s needs</a>) and can handle massive throughput. S3 will scale virtually infinitely for storage. The challenge is in scaling the ingestion pipeline and query engines &#8211; which is solvable with cloud services (Kinesis, auto-scaling clusters, etc.) but needs careful planning. The data lake approach is often called a &#8220;lakehouse&#8221; when combined with query engines, and it&#8217;s quickly becoming the industry standard for big data analytics. In observability, adopting this architecture now is a forward-looking move that aligns with where the industry is headed (as evidenced by several observability startups and even <a href="https://www.splunk.com/en_us/blog/platform/announcing-splunk-federated-search-for-amazon-s3-now-generally-available-in-splunk-cloud-platform.html?ref=observability.how">Splunk&#8217;s newer architectures embracing S3-backed storage</a>). <em>However, be prepared:</em>&nbsp;building a robust data pipeline and platform does require engineering expertise, and not every organization wants to be in the business of maintaining such a platform. It&#8217;s wise to candidly discuss the <strong>complexity</strong> (and read through this blog series on <a href="https://www.observability.how/scaling-observability-designing-a-high-volume-telemetry-pipeline-series/">building high-volume telemetry pipeline</a>). That said, once built, it can serve as a foundation for not just observability, but also security analytics, BI, and more, providing far more value than a black-box SaaS tool.</p></li></ul><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;2f2663b8-4983-4a69-ab2d-2f5d772e9746&quot;,&quot;caption&quot;:&quot;&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline Series&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-01-17T08:37:37.709Z&quot;,&quot;cover_image&quot;:null,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-series&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184849757,&quot;type&quot;:&quot;page&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>Presenting the Case to Leadership</h2><p>Building an in-house observability platform on AWS S3 and Apache Iceberg offers a compelling proposition:&nbsp;<strong>drastically lower costs, unlimited data retention, and freedom to innovate on your telemetry data</strong>. You&#8217;re essentially applying the proven &#8220;data lakehouse&#8221; pattern to observability &#8211; treating log, trace and metric data as you would big data in an analytics platform, rather than as exhaust to be discarded due to cost. For architects and DevOps leaders, the technical benefits (centralization, flexibility, scale) are clear. For executives, the pitch centers on cost savings, strategic data ownership, and enabling advanced insights (like AI/ML) that drive competitive advantage.</p><p>It&#8217;s important to set expectations: an in-house solution requires engineering investment. You may need a small team to manage data pipelines, optimize queries, and build user interfaces or integrations on top of the data lake. However, this investment can pay for itself quickly with the savings from SaaS fees. Moreover, it future-proofs the organization &#8211; you won&#8217;t be stuck in a contract if a vendor raises prices, nor will you be constrained by a tool&#8217;s capabilities. Instead, you have&nbsp;<strong>full control of a core competency</strong>: your ability to understand and troubleshoot your systems.</p><p>Many forward-thinking companies have already started down this road, blending open-source and cloud services to build their own observability stacks. The tooling ecosystem is maturing rapidly, making it easier than ever (for example, managed services for Kafka, Flink, or using AWS Glue and Athena can reduce the ops burden). Apache Iceberg&#8217;s rise as the&nbsp;<em>de facto</em>&nbsp;standard for data lakes means you&#8217;re aligning with an industry trend, not venturing out alone.</p><p>In closing, building an in-house observability platform with a data lake architecture is about&nbsp;<strong>taking control of your telemetry data</strong>. It&#8217;s about turning what was once a cost center (big bills for third-party services) into an asset (a rich, queryable repository of operational intelligence). By leveraging AWS S3 and Apache Iceberg, you gain scalability and reliability on par with the best data platforms, at a fraction of the cost. The benefits &#8211; in cost savings, flexibility, and insights &#8211; far outweigh the challenges, especially as tools and best practices in this space continue to evolve. For organizations grappling with high observability costs or data silos, this approach presents a clear path forward to a more sustainable and powerful observability strategy. <em>Happy Laking!</em></p>]]></content:encoded></item><item><title><![CDATA[Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 4]]></title><description><![CDATA[In Part 3, we explored building scalable telemetry pipelines with agents, batching, Kafka buffering, and backpressure control for resilient observability.]]></description><link>https://www.observability.how/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-4</link><guid isPermaLink="false">https://www.observability.how/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-4</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Thu, 15 May 2025 06:34:16 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/3093bf81-46a4-4c1d-94ef-b273560a5836_1472x832.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ESh0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ESh0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ESh0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ESh0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ESh0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ESh0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 4&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 4" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 4" srcset="https://substackcdn.com/image/fetch/$s_!ESh0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ESh0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ESh0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ESh0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1421c33f-aaf7-4f5a-8de9-5cb51f4361b7_1472x832.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>In Part 3, we explored building scalable telemetry pipelines with agents, batching, Kafka buffering, and backpressure control for resilient observability. Now let's bring it home with this last part of our blog series by addressing how to make the entire pipeline horizontally scalable and highly available, explore cost management and retention policies, and examine lessons learned from production deployments.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;e8d02b34-f6a6-48bc-b202-5004242c0049&quot;,&quot;caption&quot;:&quot;In Part 2, we saw that scaling observability pipelines involves specialized strategies for each telemetry signal type. For metrics, scalable architectures use distributed storage, aggregation, downsampling, etc. to handle high volumes. Traces pipelines employ sampling strategies like head-based, tail-based, and remote sa&#8230;&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 3&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-05-12T05:34:07.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a60cd8c3-4464-45ad-bc7a-e2b9997d20f4_1472x832.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-3&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843143,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>Horizontal Scaling and High Availability</h2><p>We&#8217;ve implicitly discussed scaling by adding more instances in various parts of the pipeline. Let&#8217;s summarize how to achieve horizontal scaling and ensure high availability in each layer:</p><ul><li><p><strong>Collectors/Agents:</strong>&nbsp;These are usually per node or per service already (scaled with the cluster). For centralized collectors (like a cluster of OTel collectors or Jaeger collectors), you can run them behind a load balancer or use a service discovery mechanism. They are stateless (unless doing tail sampling &#8211; then state per trace in memory, but that&#8217;s handled by partitioning). By adding more collector instances, you increase aggregate throughput. Ensure a load balancing strategy that keeps related data together if needed (e.g., hash by traceID as mentioned). For availability, run collectors in multiple zones or use a daemonset per node (so if one node dies, it only affects that node&#8217;s agent, not others).</p></li><li><p><strong>Kafka/Queue:</strong>&nbsp;When creating a Kafka-based pipeline, decide on the number of partitions such that each partition&#8217;s throughput is within the capacity of a single consumer. Kafka can scale to hundreds or thousands of partitions if needed, though extremely high partition counts can add overhead. Kafka offers built-in replication for availability &#8211; each partition is replicated to multiple brokers. For high availability, use a replication factor of 3 (or at least 2) so that a broker failure doesn&#8217;t lose data, and distribute replicas across availability zones. Consumers and producers will automatically handle broker failovers. You can also <strong>auto-balance</strong>&nbsp;partitions if a broker goes down or new brokers are added (using Kafka&#8217;s partition reassignments), keeping load evenly spread.</p></li><li><p><strong>Metrics Backend:</strong>&nbsp;Systems like Mimir or Cortex scale by running multiple instances of each component. If ingest throughput grows, add more&nbsp;<strong>ingesters</strong>&nbsp;(and possibly increase their memory or WAL persistence as needed). Use consistent hashing or shuffle sharding so that new ingesters pick up a share of series from distributors. If query load grows, add more&nbsp;<strong><a href="https://grafana.com/docs/mimir/latest/references/architecture/components/querier/?ref=observability.how">querier</a></strong>&nbsp;and&nbsp;<strong><a href="https://grafana.com/docs/mimir/latest/references/architecture/components/query-frontend/?ref=observability.how">query-frontend</a></strong>&nbsp;instances &#8211; these are stateless and easy to scale. High availability is achieved via replication (Cortex/Mimir replicating samples to multiple ingesters), plus having multiple replicas of each service behind a load balancer. Also, run these services across multiple nodes/VMs or Kubernetes pods, so a single machine failure only drops a fraction of capacity. Multi-tenancy support in these systems means one tenant&#8217;s heavy usage shouldn&#8217;t affect another&#8217;s, especially if you configure per-tenant limits and perhaps separate critical metrics into their own tenant.</p></li><li><p><strong>Trace Backend:</strong>&nbsp;If using Jaeger with Kafka + Elasticsearch, you scale the Jaeger collectors by adding more (they are stateless, reading from Kafka). Scale the Elasticsearch cluster by adding data nodes and shards if write volume increases; also ensure you have multiple Kibana or query nodes for front-end throughput. For Grafana Tempo, you scale similarly to Loki/Cortex: multiple <strong>ingesters</strong>&nbsp;to handle trace ingestion (each writes to object storage) and multiple&nbsp;<strong>queriers</strong>&nbsp;for reading. Tempo is designed to be&nbsp;<strong>highly scalable and cost-efficient</strong>&nbsp;by forgoing heavy indexing. Ensure your object storage (e.g. S3) has sufficient throughput (it usually auto-scales). Use&nbsp;<strong>overlapping deployments</strong>&nbsp;if needed for migrations &#8211; e.g. spin up a new set of collectors while the old is still running, then cut over (to avoid downtime).</p></li><li><p><strong>Log Backend:</strong>&nbsp;Elasticsearch clusters require careful scaling &#8211; monitor indexing throughput and query latency. If indexing is bottleneck, consider increasing the number of primary shards or the number of ingest nodes (which do parsing). Too many shards can hurt query performance, so strike a balance. Using&nbsp;<strong>Index Lifecycle Management</strong>, you can reduce replica count for older indices to save resources (since they&#8217;re queried less). For Loki, scaling means adding more&nbsp;<strong>ingesters</strong>&nbsp;(which handle incoming log streams and write to storage) and&nbsp;<strong>queriers</strong>&nbsp;(which fetch and filter log chunks). Loki can be scaled in a &#8220;simple scalable&#8221; mode separating write and read components that you scale independently. Both Elastic and Loki benefit from&nbsp;<strong>sharding by tenant or source</strong>&nbsp;if extremely high volume &#8211; for example, run two separate Loki clusters for two distinct environments to halve the load on each (at the cost of having two places to query). High availability: run multiple instances of each component (Elastic master nodes, ingest nodes, query nodes; Loki distributors, ingesters, etc.) so that one instance going down doesn&#8217;t stop ingestion or querying.</p></li><li><p><strong>Stream Processing:</strong>&nbsp;Flink and Spark are inherently distributed; you scale by increasing parallelism (tasks). Ensure your job can partition the data effectively (e.g. by key) to utilize parallel consumers. Flink jobs can be rescaled by taking a savepoint (snapshot state) and redeploying with more task slots. Always configure periodic checkpoints to durable storage so that if a job fails or needs to move, it can resume without data loss. For HA, deploy Flink with a standby JobManager or use Kubernetes operators that restart jobs on failure. Because Flink maintains state, it&#8217;s crucial to plan for fault recovery &#8211; e.g., Flink&#8217;s checkpointing provides exactly-once guarantees, meaning even if a node fails, on recovery the job will not skip or double-process events (as long as it can restore from the last checkpoint). This ensures your streaming analytics remain correct under failures.</p></li></ul><p>A horizontally scalable design also means&nbsp;<strong>no <a href="https://en.wikipedia.org/wiki/Single_point_of_failure?ref=observability.how">single point of failure</a> (SPOF)</strong>. Avoid having just one instance of any critical component. For example, a single log forwarder for an entire cluster is a SPOF &#8211; instead, run one per node or multiple in a load-balanced set. Use cluster modes for databases and message brokers. For each layer, consider how it can recover from node failures: if an OTel collector pod dies, do agents buffer and retry to another? If a Kafka broker dies, do producers time out and retry correctly to other brokers? Testing these failure scenarios is part of the engineering process.</p><h3><strong>Statelessness vs. Stateful Partitioning</strong></h3><p>Wherever possible, keep components stateless. Stateless components (like distributors, collectors, query frontends) can scale freely and recover easily by just restarting (no data to reload). When state is needed (like ingesters caching recent metrics, or tail-sampling buffers, or stream job state), design it so that the state is partitioned and/or backed by durable storage. Partitioning ensures that adding/removing nodes only affects a subset of data. For example, if you have 10 ingesters each with some subset of metrics series, losing one means those series need to failover to others, which the system can handle if data was replicated or can be recovered from WAL. Systems like Cortex use a gossip/consistent-hash ring to manage ingester membership. On failure, series assigned to the lost ingester get taken over by remaining ones (with maybe a brief dip in availability for those series until caught up from WAL or from the replicas). Always configure features like Mimir's&nbsp;<strong>HA tracking</strong>&nbsp;(if you have multiple Prometheus feeding it the same data) and&nbsp;<strong>Loki&#8217;s boltdb/TSDB index</strong>&nbsp;such that new ingesters can quickly load index info from shared storage on join.</p><h3><strong>Geo-Distribution</strong></h3><p>In some large organizations, they deploy pipelines per region for performance, then merge results at the query layer (federation). This avoids shipping all telemetry across the globe. However, that introduces complexity of multi-cluster management. If your use case requires global aggregation (e.g. traces spanning regions or logs from multi-region services), you&#8217;ll need a pipeline that can either handle cross-region data or replicate data to a central location. Kafka MirrorMaker or similar can sync topics across regions for a unified processing in one region at the expense of cross-region bandwidth.</p><blockquote><p>To summarize, design your pipeline so that&nbsp;<strong>every component can scale out and has a failover plan</strong>.</p></blockquote><p>Embrace&nbsp;<em>loose coupling</em>&nbsp;&#8211; components communicate via network and durable storage rather than in-memory assumptions. This way, adding resources or restarting services becomes routine. A properly scaled and load-balanced pipeline will continue running even when individual nodes crash, and will smoothly handle increasing load by consuming more resources rather than collapsing. High-volume observability pipelines at companies like Uber, Netflix, etc. are built on these principles to achieve near-linear scaling with system growth.</p><div><hr></div><h2>Cost Management and Data Retention</h2><p>While not purely a technical scaling concern, cost control is an essential aspect of running a high-volume telemetry pipeline. Unbounded data growth can lead to runaway expenses (in cloud bills for storage/CPU or on-prem hardware). Here we discuss strategies to manage costs, which often coincide with improving scalability:</p><ul><li><p><strong>Retention Policies:</strong>&nbsp;Not all telemetry needs to be kept forever. Implement sensible retention schedules: e.g., keep full-resolution data for a short period (say 7-30 days) and then drop or archive it. For metrics, you might retain 15-second data for 2 weeks, then only 5-minute averages for 3 months. Logs might be kept in hot storage for a week, then archived to cheap storage for a few months, then deleted. Traces might only be kept for a few days unless they are for important transactions. By limiting retention, you cap the storage footprint, which directly bounds cost. Ensure compliance requirements are met though &#8211; if certain logs must be retained for a year, you&#8217;ll need an archive (but possibly not in the high-cost system). Many systems support automated deletion or rollover based on age (e.g., Elasticsearch ILM, Loki retention configs, etc.).</p></li><li><p><strong>Sampling &amp; Filtering:</strong>&nbsp;The most effective cost lever is to simply ingest less data. As discussed in previous parts, <strong>trace sampling </strong>aggressively reduces trace data volume (keeping perhaps &lt;1% of all requests). This cuts storage, network, and processing costs dramatically while usually preserving the most useful information.&nbsp;<strong>Log filtering</strong>&nbsp;is equally important: do you really need every debug log from every instance? Likely not. Drop logs below a certain level in production, or use dynamic log levels to only increase verbosity when needed. Some teams filter out health-check logs or other chatty but low-value messages early in the pipeline. It&#8217;s common to discard known benign errors or redundant info. Even a simple filter like &#8220;drop all logs containing &#8216;database heartbeat&#8217;&#8221; (if that&#8217;s a noisy periodic message) can save gigabytes daily. Another approach is <strong>log sampling</strong>&nbsp;&#8211; if an error message repeats 1000 times, perhaps only store 100 of them and count the rest. We saw earlier an example of tail sampling for traces to keep all errors; similarly for logs, you might set rules to always keep certain log types (errors, warnings) but sample down the info/debug messages. Edge computing solutions can identify repetitive log patterns and only forward unique patterns plus counts, reducing volume significantly.</p></li><li><p><strong>High-Cardinality Data Guardrails:</strong>&nbsp;Ensure metrics with unbounded cardinality are controlled. Some systems let you enforce limits like &#8220;max 1000 time-series per metric name&#8221; &#8211; beyond that, drop new series. This prevents a runaway metric from OOMing the database (and incurring cost for all that memory/storage). Also watch out for label combinations that multiply out (like combining userID with URL with error code etc.). You might need to restrict combinations or explode them into separate metrics. High cardinality metrics or tags often correlate with high cost because they create more database entries and more index data. So, addressing cardinality is both a performance and a cost optimization.</p></li><li><p><strong>Tiered Storage (Hot vs Cold):</strong>&nbsp;Use expensive storage for recent, frequently-accessed data, and cheaper storage for older or infrequently accessed data. For logs, this could mean using SSD-based Elasticsearch for 7 days, and then shifting to an S3-based data lake or a compressed store for anything older. Some companies use services like AWS S3 Glacier for archival &#8211; super cheap to store, though slow to retrieve. If you implement this, also implement a process to retrieve data when needed (perhaps an automated job that can load archived logs into a cluster for analysis if an incident from last quarter needs investigation). For metrics, systems like Thanos or Mimir inherently do tiering by using object storage for older data. For traces, you might dump old traces to files in cloud storage after a few days and remove them from the fast database. This drastically cuts the cost of keeping historical data.</p></li><li><p><strong>Compression and Efficient Encoding:</strong>&nbsp;Make sure data is compressed at rest and in transit. Text logs compress 5-10x typically. Metrics use efficient encoders by default (Prometheus TSDB does delta-of-delta encoding and bit packing). Trace data (often JSON) can be heavy; using Protobuf (OTLP) and compressing (gRPC can enable gzip) saves bandwidth. Also, consider not storing duplicate fields repeatedly. For example, if every log line includes the same static metadata, Loki&#8217;s approach of labeling captures that once and not on every line saves space. In Elasticsearch, using mappings to not index certain large text fields (store only) can save index size if you rarely search by them. Also, prefer structured logs to raw text parsing &#8211; structured data can be stored more compactly (like numeric fields vs strings) and filtered without full text indexing.</p></li><li><p><strong>Optimize Query Costs:</strong>&nbsp;If you pay for query execution (like in a cloud logging service or Athena), reduce expensive queries. This is more on the usage side, but e.g. avoid running regex searches over all logs needlessly. Provide saved searches or aggregated metrics to answer common questions instead of ad-hoc expensive queries each time. Some cloud services charge by data scanned &#8211; partitioning data well (by time, by service) can limit scan sizes and thus cost.</p></li><li><p><strong>Choosing Open Source vs Managed:</strong>&nbsp;Many organizations move to open-source self-hosted solutions (Prometheus, Loki, etc.) because sending all data to a SaaS vendor is cost-prohibitive at scale (vendors often charge per GB ingested, which at TB/day is huge). Self-hosting shifts cost to your cloud or hardware spend, which can be cheaper if optimized. On the other hand, managed services might have more efficient backends or easier scaling (but you pay a premium). A hybrid approach is possible: for critical data, use a paid service with strong analytics; for raw bulk data, use open source internally. For example, you might send high-value business metrics to a SaaS analytics tool, but keep all system metrics in your own cluster.</p></li><li><p><strong>Showback/Chargeback:</strong>&nbsp;Within a large enterprise, visibility into who is generating the most telemetry can help control costs. If Team A sees that they produce 10x more logs than anyone else, they might investigate why (maybe a verbose setting left on) or chip in more for the budget. Even if you don&#8217;t actually charge teams, showing them their usage encourages optimization. It turns cost into a shared responsibility.</p></li><li><p><strong>Automated Cleanup:</strong>&nbsp;Implement auto-deletion for obsolete telemetry data. For instance, if an application is decommissioned, make sure its old metrics and logs are aged out and not kept indefinitely taking up space. The pipeline can include retention enforcement that aggressively drops data from sources that haven&#8217;t been seen in a while.</p></li></ul><blockquote><p>Ultimately,&nbsp;<strong>cost management is about smart data management</strong>&nbsp;&#8211; collecting what&#8217;s useful at a resolution that&#8217;s needed, and for only as long as it provides value.</p></blockquote><p>Every piece of data has a &#8220;diminishing value over time&#8221;: recent data is extremely valuable for debugging active issues, but months-old raw telemetry is rarely used except for compliance or audits. Tailor your pipeline to that reality by summarizing or purging old data.</p><div><hr></div><h2>Trade-Offs, Anti-Patterns, and Lessons Learned</h2><p>Designing a high-volume telemetry pipeline involves balancing trade-offs. Here are some key trade-offs and pitfalls (&#8220;anti-patterns&#8221;) to be aware of, along with lessons learned from real-world deployments:</p><h3>Trade-Offs &amp; Anti-Patterns</h3><ul><li><p><strong>Completeness vs. Cost/Performance</strong>: An overarching trade-off is how much data to collect and retain versus the cost and performance implications.&nbsp;<strong>100% data collection</strong>&nbsp;(no sampling, no filtering) maximizes visibility but is usually unsustainable at scale. Too aggressive filtering, on the other hand, might leave gaps just when you need detail. The sweet spot is to&nbsp;<strong>capture all high-value signals</strong>&nbsp;(errors, anomalies, key transactions) but aggressively downsample repetitive, low-value data. Many teams iterate on this. For example, one might start tracing at 10% sampling and realize the system can handle more, so increase to 20%. Or discover that certain log categories are rarely used and safely drop them. It&#8217;s an ongoing calibration of signal vs. noise. A good practice is to <strong>review incidents</strong>: if an incident was hard to debug due to missing data, you may decide to collect more of that type; if you never used a type of data, maybe collect less of it.</p></li><li><p><strong>Unified vs. Specialized Tools: </strong>A unified pipeline (one agent, one format) simplifies deployment and correlation, but sometimes specialized tools are better for each domain (metrics, logs, traces). One anti-pattern is trying to force one storage engine to do everything. For instance, storing high-cardinality time-series in Elasticsearch (which is not optimized for that query pattern) would both be slow and costly &#8211; a specialized TSDB is more appropriate. Conversely, using a TSDB for logs (treating logs as metrics) loses the richness of text search. The lesson is&nbsp;<strong>use the right tool for each job</strong>, but integrate them. OpenTelemetry helps unify data collection without forcing a single backend. Modern observability stacks embrace polyglot persistence while providing a cohesive user experience on top.</p></li><li><p><strong>Overlooking Bottlenecks</strong>: A pipeline is a chain; the slowest link dictates throughput. A common anti-pattern is scaling the obvious parts (like adding Kafka brokers) but missing a hidden bottleneck. Examples: a single-threaded parser that can&#8217;t handle more than X events/sec, or a database lock contention issue limiting write rate. Regularly perform end-to-end load testing or at least capacity analysis for each component. Tracing can even be applied to the pipeline itself to see where time is spent. If one component consistently has high CPU or queue backlogs, that&#8217;s your bottleneck. Also be aware of&nbsp;<strong>head-of-line blocking</strong>&nbsp;&#8211; e.g., if one very large log batch slows down a consumer thread, it might delay others (depending on the design). Solutions like parallel consumer threads or partitioning can alleviate this.</p></li><li><p><strong>Too Many Unique Dimensions</strong>: High cardinality was mentioned, but it&#8217;s worth re-emphasizing as an anti-pattern. Metrics with exploding dimensions, logs with unbounded unique values, and traces with too granular labels (like span tags that are unique per request) will strain any system. <strong>Limit uniqueness</strong>&nbsp;in what you index and aggregate on.</p></li><li><p><strong>Volume of Logs vs. Usefulness</strong>: Often, log volume grows out of habit (developers logging everything) rather than real need. An anti-pattern is treating log management as a &#8220;write-only&#8221; archive of absolutely everything. If no one ever reads 90% of those logs, you&#8217;re wasting resources. Observability is about making informed decisions on what to log. One lesson learned in many orgs: implement <strong>logging guidelines</strong>&nbsp;&#8211; e.g., logs should be actionable or informative, not debug spam; use metrics for counts rather than log each occurrence, etc. Some companies introduce a review step for adding a very high-volume log in code (because it has infrastructure cost). Culturally, shift to&nbsp;<em>&#8220;log smart, not log more.&#8221;</em></p></li><li><p><strong>Not Monitoring the Pipeline Itself</strong>: Failing to apply observability to your observability pipeline is ironically common. The pipeline should emit its own metrics: queue lengths, processing latencies, error counts, dropped events counts, CPU/memory usage, etc. Anti-pattern is treating it as a black box until something breaks. Instead, instrument the collectors, brokers, and storage with metrics (most have them &#8211; e.g., Kafka has metrics for bytes in/out, Lag, etc., Elastic has node stats, OTel Collector exports self-metrics). Build dashboards like &#8220;Telemetry Pipeline Health&#8221; showing ingestion rates vs. consumption, any backlogs, error rates in exporters, etc. Also set up alerts &#8211; e.g., alert if log queue lag &gt; 10^6 messages or if trace drop count suddenly spikes. This meta-monitoring will catch issues early (maybe before users notice missing data &#128521;). As a lesson: treat the pipeline as you would a critical production service with SLOs (e.g., 99.9% of data processed within 1 minute, etc.).</p></li><li><p><strong>No Backpressure Strategy</strong>: Another anti-pattern is not designing for overflow, leading to crashes or out-of-memory conditions. We discussed ways to handle this (queues, drop policies). Systems that lack these will eventually suffer when an upstream flood occurs. For instance, a naive log aggregator that tries to buffer everything in RAM if the database is slow will eventually OOM and lose everything. It&#8217;s better to drop some data gracefully (perhaps with an error log saying it did so) than to crash. Make sure each component in the pipeline has some limit and behavior beyond that limit. Many modern components have such controls (for example, OTel Collector&#8217;s memory_limiter, Fluent Bit&#8217;s storage.backlog.mem_limit, etc.) &#8211; use them.</p></li><li><p><strong>Reinventing the Wheel Unnecessarily</strong>: It can be tempting for very advanced teams to build custom pipeline components for absolute performance (and some have, like custom messaging systems or in-house time-series databases). But for most, this is an anti-pattern as it diverts engineering effort and may lack the robustness of community-maintained projects. You likely don&#8217;t need to write your own Kafka from scratch, or your own metrics database from scratch, unless you have truly unique requirements that existing solutions cannot meet. Leverage open source &#8211; they are battle-tested at high scale. Only go custom if you&#8217;ve clearly identified a gap that no existing tool fills and if you have the capacity to maintain it long-term.</p></li><li><p><strong>Ignoring Governance and Access Control</strong>: At enterprise scale, you must also consider who can access the data and how to prevent abuse. An anti-pattern is an open pipeline where anyone can query anything without quotas &#8211; one wild regex search could destabilize a cluster. Implement rate limits on queries, and consider multi-tenancy features of tools to isolate heavy users. Also, secure the data: logs often contain sensitive info, so your pipeline should have encryption in transit and at rest, and proper authentication/authorization for querying (especially if multi-tenant). While this is more about security/compliance, it&#8217;s a lesson learned that at scale, you need to manage usage to keep the pipeline reliable for everyone.</p></li></ul><h3><strong>Lessons Learned</strong></h3><p>Summarizing a few key lessons from teams operating large telemetry systems:</p><ul><li><p><strong>Start Simple, Then Optimize:</strong>&nbsp;It&#8217;s okay to begin with a basic pipeline (maybe one cluster for Elastic, one Prom for metrics) when volumes are low. But design with an eye for future distributed architecture. As volume grows, incrementally introduce the scalable components and test them. This avoids premature complexity but also ensures you&#8217;re not stuck when scale hits.</p></li><li><p><strong>Invest in Architecture over Hardware:</strong>&nbsp;Throwing bigger machines at the problem (vertical scaling&#128200;) hits limits fast (and cost skyrockets&#128184;). It&#8217;s better to architect for horizontal scaling earlier than to buy a huge supercomputer to run one monolithic database. The latter will become a single point of failure and a pain to replace. Clusters of smaller commodity instances are usually more cost-effective and resilient.</p></li><li><p><strong>Communication Between Teams:</strong>&nbsp;In large orgs, the producers of telemetry (application teams) and the consumers (observability team) might be different. Communicate about the impact of telemetry &#8211; e.g., if an app team suddenly enables very verbose logging, make sure they know the cost or pipeline impact. Having a feedback loop (&#8220;we saw your service&#8217;s log volume grew 5x last week, is that expected?&#8221;) can catch accidental issues. Also, share best practices with developers on how to instrument efficiently (use async spans, don&#8217;t log in tight loops, etc.).</p></li><li><p><strong>Regular Capacity Planning:</strong>&nbsp;Just as you plan capacity for your main product, do so for the telemetry pipeline. Monitor growth trends (metrics count, log size per day) and project when you&#8217;ll need more resources. Because if your pipeline becomes a bottleneck, it can hinder troubleshooting precisely when your system is under duress. Treating it with the same rigor as production capacity avoids unpleasant surprises.</p></li><li><p><strong>Keep Learning:</strong>&nbsp;The observability landscape evolves rapidly. New compression algorithms, new database technologies, and better strategies (like exemplary traces, dynamic sampling) emerge. For example, if your current trace sampling misses some issues, you might adopt new techniques like <strong>adaptive sampling</strong>&nbsp;(increasing sampling when errors rise). Or if storage cost is an issue, you might evaluate a newer log store that promises lower cost. Stay informed via community forums, conference talks, and case studies from other companies. Adopting improvements can yield big savings or capabilities.</p></li></ul><p>In essence, building a high-volume telemetry pipeline is a continual process of refinement. Start with a robust foundation, observe how it behaves, and iteratively improve reliability, efficiency, and usefulness. Avoiding the common pitfalls and learning from others&#8217; experiences will accelerate this journey.</p><div><hr></div><p>Scaling an observability pipeline to handle millions of events per second is a challenging endeavor, but by applying the right architectures and practices, it can be achieved in a sustainable way. We&#8217;ve explored how to handle metrics, traces, and logs at scale &#8211; each with their tailored storage and processing designs &#8211; and how to tie them together into a cohesive system. The themes of&nbsp;<strong>horizontal scalability, decoupling through queues, smart filtering, and careful resource management</strong>&nbsp;come up again and again.</p><p>A well-designed pipeline will ensure that no matter how much your application traffic grows or how complex your microservices become, you will maintain visibility into the system&#8217;s behavior. This means faster debugging, more reliable alerting, and ultimately higher confidence in managing large-scale systems. Just as importantly, we emphasized&nbsp;<strong>cost-awareness</strong>: it&#8217;s easy to ingest everything and drown in data (and bills), but far more effective to be selective and strategic in what you observe.</p><p>By leveraging modern open-source tools and cloud-native patterns &#8211; you can build on the lessons of industry leaders. You don&#8217;t need to reinvent the wheel; you can assemble a combination of these projects and scale them out on Kubernetes or your infrastructure of choice.</p><p>In the end, observability is an enabler for reliability. A scalable telemetry pipeline is not just an IT cost center &#8211; it&#8217;s an investment in uptime and agility. It allows engineers to quickly pinpoint issues in distributed environments and understand system behavior even under massive load. The strategies outlined in this series of posts serve as a blueprint to design and evolve your own high-volume telemetry pipeline. Take these lessons, adapt them to your context, and you&#8217;ll be well on your way to observability at scale: a pipeline that grows with your systems and continuously delivers the insights you need, when you need them. <em>Happy Observing!</em></p>]]></content:encoded></item><item><title><![CDATA[Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 3]]></title><description><![CDATA[In Part 2, we saw that scaling observability pipelines involves specialized strategies for each telemetry signal type.]]></description><link>https://www.observability.how/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-3</link><guid isPermaLink="false">https://www.observability.how/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-3</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Mon, 12 May 2025 05:34:07 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a60cd8c3-4464-45ad-bc7a-e2b9997d20f4_1472x832.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QfeP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QfeP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic 424w, https://substackcdn.com/image/fetch/$s_!QfeP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic 848w, https://substackcdn.com/image/fetch/$s_!QfeP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic 1272w, https://substackcdn.com/image/fetch/$s_!QfeP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QfeP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic" width="1456" height="823" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:823,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:228536,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://observabilityhow.substack.com/i/184843143?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QfeP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic 424w, https://substackcdn.com/image/fetch/$s_!QfeP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic 848w, https://substackcdn.com/image/fetch/$s_!QfeP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic 1272w, https://substackcdn.com/image/fetch/$s_!QfeP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4fe0d325-5f5e-4a51-97a8-46ba0d585d13_1472x832.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Data Super-Highway <em>(AI Generated)</em></figcaption></figure></div><p>In Part 2, we saw that scaling observability pipelines involves specialized strategies for each telemetry signal type. For metrics, scalable architectures use distributed storage, aggregation, downsampling, etc. to handle high volumes. Traces pipelines employ sampling strategies like head-based, tail-based, and remote sampling to manage trace volume. While for Logs, it makes sense to limit indexing to metadata fields instead of full log line.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;e3a21aa7-32da-49fd-a71b-c474839be9ec&quot;,&quot;caption&quot;:&quot;In the Part 1, we saw that a scalable pipeline architecture consists of data collection, processing, storage, and querying stages, with key design principles including horizontal scaling, stateless processing, and backpressure management. Now, let's examine specialized scaling strategies for each telemetry signal type.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-05-04T21:20:03.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e036351f-44ef-4305-9b8f-4e4d2a636ac6_1792x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-2&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843145,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Now, let's assemble these scaled-up telemetry pipelines end to end&#8212;covering ingestion, stream processing, and buffering/backpressure strategies.</p><div><hr></div><h2>Telemetry Ingestion at Scale: Collectors, Agents, and Message Buses</h2><p>The ingestion layer is the foundation of the telemetry pipeline. In a high-volume scenario, how you collect and ingest data can make or break the pipeline. Key considerations include overhead on sources, network efficiency, and ensuring no single choke point.</p><h3><strong>Agents and Collectors</strong></h3><p>As mentioned, it&#8217;s common to run lightweight&nbsp;<strong>agent daemons on each host</strong>&nbsp;(or sidecars in each pod) for each type of data: e.g. Fluent Bit for logs, OpenTelemetry Collector (in agent mode) for metrics and traces. The agent&#8217;s job is to collect data from local sources (files, OS, app SDKs) and forward it. Using agents is important at scale for a few reasons: it offloads work from the application (e.g. the app just logs to a file, the agent ships it), and it enables&nbsp;<strong>batching</strong>&nbsp;and&nbsp;<strong>compression</strong>. Batching multiple telemetry data points together dramatically improves throughput &#8211; sending 1000 spans in one payload is far more efficient than each span separately. The OpenTelemetry Collector, for instance, has a batching processor that groups spans or metrics before export. This improves network usage and reduces load on downstream systems.</p><p>Moreover, these collectors can do initial preprocessing: add uniform tags (like environment name),&nbsp;<strong>scrub sensitive data </strong>(drop PII), or&nbsp;<strong>enrich</strong>&nbsp;events (e.g. add Kubernetes pod labels to all logs and traces). Enrichment is critical in Kubernetes: the agent knows the pod name, namespace, node, etc., so adding those to every log line or span provides context needed later. Doing this at the edge saves expensive joins later.</p><p><strong><a href="https://opentelemetry.io/docs/collector/?ref=observability.how">OpenTelemetry Collector</a></strong>&nbsp;deserves a special mention as a pluggable, vendor-neutral component. It can receive metrics, logs, and traces using various protocols, apply processors (filtering, sampling, aggregation), and export to various backends. At scale, you might deploy it in a&nbsp;<strong>two-tier mode</strong>: one collector on each node (agent) and a pool of collectors as a central service (gateway). The agents feed into the gateway cluster, which then feeds storage. This two-tier approach isolates concerns and allows scaling the middle tier separately.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;b80fb6f1-4ae3-4be1-a25b-2c48b31af71f&quot;,&quot;caption&quot;:&quot;OpenTelemetry&#8217;s Collector is a vendor-neutral service that sits between your applications and observability backends. It can receive telemetry data (traces, metrics, logs), process or transform it, and export it to one or multiple destinations. In a production environment, the Collector becomes essential for building a&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Using the OpenTelemetry Collector: A Practical Guide&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-17T07:56:28.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5151a4d-0495-4388-9617-364ce63da4e5_1996x1192.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/using-the-opentelemetry-collector-a-practical-guide&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843148,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><h3><strong>Decoupling with Message Queues</strong></h3><p>To achieve resilience and smoothing of traffic, inserting a durable message queue/broker in the pipeline is a common strategy.&nbsp;<strong><a href="https://kafka.apache.org/?ref=observability.how">Apache Kafka</a></strong>&nbsp;is a popular choice due to its high throughput and durability. Kafka can handle&nbsp;<strong>millions of messages per second</strong>&nbsp;if appropriately provisioned (with enough broker nodes and partitions). By funneling telemetry through Kafka topics (e.g. a topic for logs, one for traces, etc.), you ensure that temporary spikes or downstream outages don&#8217;t cause data loss &#8211; data will queue in Kafka (up to retention limits) until consumers catch up. It also lets you&nbsp;<strong>fan-out</strong>&nbsp;consumers: for instance, one consumer group could feed data to your primary storage, another consumer group could drive a real-time analytics job in parallel, all reading from the same stream of data.</p><p>In practice, using Kafka adds operational complexity (managing a Kafka cluster) and some latency (usually a few seconds), but it significantly decouples components. Fluent Bit -&gt; Kafka -&gt; Elasticsearch is more robust than Fluent Bit -&gt; Elasticsearch directly, because if Elasticsearch slows down, Kafka can buffer whereas in direct ingestion you&#8217;d start dropping logs or backpressure into Fluent Bit. Many observability systems (Datadog, Splunk, etc.) decouple ingestion in a similar way internally, even if it&#8217;s not exposed.</p><p>Other queue technologies such as <strong><a href="https://www.rabbitmq.com/?ref=observability.how">RabbitMQ</a></strong>&nbsp;or NATS could be used for smaller-scale or low-latency needs, but Kafka is the go-to for big data streaming. Some organizations even use&nbsp;<strong><a href="https://redis.io/?ref=observability.how">Redis</a></strong>&nbsp;as a short buffer (e.g. Redis lists as a queue for metrics) when they want simplicity and are okay with data in memory/disk for short term. Custom in-memory queues might be built for ultra-low latency requirements (but then you risk losing data on crash, unless you persist to disk like Kafka does). Generally, Kafka&#8217;s combination of throughput and durability is hard to beat for telemetry pipelines.</p><h3><strong>Protocol Choices</strong></h3><p>It&#8217;s worth noting the protocols used: OpenTelemetry uses gRPC-based OTLP by default for sending data which is efficient (binary, compressed). Fluent Bit might use Fluent protocol or just write to Kafka. Some use HTTP for simplicity (like Prometheus remote write uses HTTP); at very high scale, gRPC or Kafka&#8217;s binary protocol is preferred for efficiency. The pipeline should avoid overly chatty or text-based protocols (e.g. older syslog over TCP might not cut it for huge volumes without tweaking).</p><h3><strong>Ordering and Grouping</strong></h3><p>If you require ordering (like logs in exact order per source) or grouping (all spans of trace together for tail sampling), design the ingestion to respect that. Kafka can maintain order per partition key, so choosing the key is important. For logs, you might key by a combination of source and time bucket to keep relative ordering in partitions. For traces, key by traceID ensures all spans of that trace land in one partition (and thus one consumer at a time). This aids tail sampling as discussed.</p><h3><strong>Overhead on Sources</strong></h3><p>High-volume pipelines must ensure they don&#8217;t hurt the applications. Agents should be lightweight &#8211; e.g., Fluent Bit&#8217;s footprint is small (tens of MB of memory). If using sidecar containers for collection, ensure CPU/memory requests are set appropriately to not starve the app container. One anti-pattern is putting too much work on application threads (like heavy log formatting or synchronous exports) &#8211; avoid that by shifting it to the agent. Also, consider rate limiting at the source if absolutely needed. For example, if an app suddenly floods 10x normal logs due to a bug, the agent could detect this and sample those logs rather than bringing down the whole pipeline.</p><h3><strong>Security and Multi-tenancy</strong></h3><p>In hybrid scenarios, data might traverse networks. Use encryption (TLS) on telemetry data in motion if crossing datacenter boundaries. Agents might authenticate to gateways. Multi-tenant pipelines tag data with tenant identifiers and ensure isolation down the line (some backends natively support multi-tenancy, e.g. Cortex/Mimir for metrics segregate data by tenant). Kafka can even have separate topics per tenant if needed, to isolate workloads and data access.</p><p>In essence, the ingestion layer must be&nbsp;<strong>robust, scalable, and smart</strong>: robust by not losing data during spikes (hence buffering), scalable by parallelizing inputs and using horizontal clusters, and smart by doing early drop/filter of useless data. This provides a solid feed of telemetry into the rest of the pipeline. Next, we consider if and how to do&nbsp;<strong>real-time processing on telemetry streams</strong>&nbsp;before final storage.</p><div><hr></div><h2>Real-Time Stream Processing and Enrichment</h2><p>One powerful aspect of a modern telemetry pipeline is the ability to perform real-time computations on the data in transit. Instead of just shipping raw data from A to B, organizations often insert stream processing jobs that derive insights, detect anomalies, or enrich data on the fly. At high volume, this requires distributed stream processing engines such as&nbsp;<strong><a href="https://flink.apache.org/?ref=observability.how">Apache Flink</a></strong>&nbsp;or&nbsp;<strong><a href="https://spark.apache.org/?ref=observability.how">Apache Spark</a></strong>, which are designed to handle large event streams with stateful computations.</p><h3>Use Cases for Streaming in Observability</h3><ul><li><p><strong>Enrichment:</strong>&nbsp;Join the telemetry data with other data sources to add context. For example, augment logs with cloud metadata (like looking up an instance ID to get its region or owner), or attach application version info to traces by joining on service name. While some enrichment can be done at the agent, complex ones (like a database lookup or ML model inference) might be done in a stream processor.</p></li><li><p><strong>Anomaly Detection and Alerts:</strong>&nbsp;Instead of waiting for metrics to be stored and then evaluated, a Flink job could continuously compute statistical measures or run anomaly detection algorithms (like z-scores, or even train models) on the metrics stream. This could identify unusual patterns (error rates spike, memory leak patterns in metrics) in real-time and trigger alerts or flag traces. Flink is well-suited for such event-driven applications, providing large state capacity and event-time processing for complex patterns. Typical examples are&nbsp;<strong>fraud detection, anomaly detection, and rule-based alerting on streams</strong>.</p></li><li><p><strong>Metric Extraction:</strong>&nbsp;Some logs contain metrics that aren&#8217;t emitted elsewhere (e.g. an application might log a line &#8220;computed recommendation in 123ms&#8221;). A streaming job can parse logs and emit a custom metric (like a histogram of that latency) into the metrics system, effectively turning unstructured logs into structured metrics for easier monitoring. This can be done with tools like Logstash or Vector as well, but Flink/Spark can do it at larger scale with more complex logic.</p></li><li><p><strong>Log Pattern Aggregation:</strong>&nbsp;Rather than storing millions of identical log lines, a streaming job could group them. For example, detect that an error message repeated 100,000 times in an hour and instead store one representative log with a count. Edge computing solutions or pipeline products often do &#8220;log pattern detection&#8221; upstream to reduce data. This is a form of&nbsp;<strong>pre-aggregation of logs</strong>&nbsp;that can cut down ingest load massively.</p></li><li><p><strong>Correlating Signals:</strong>&nbsp;Join different telemetry streams. For instance, join traces with logs &#8211; if you have trace IDs in logs, a Flink job could take error logs and try to find the corresponding trace, then push an alert or an enriched event (like &#8220;this error log is part of trace X which had 5 other errors&#8221;). This kind of correlation can also populate a troubleshooting knowledge base or trigger automated mitigations. Another example: correlating metrics with traces (e.g. if latency metric spikes, automatically pull sample traces from that window).</p></li></ul><p>Implementing these at scale requires an engine like Flink that can handle high event rates and maintain state with exactly-once guarantees.&nbsp;<strong>Apache Flink</strong>&nbsp;is a popular choice because it&#8217;s designed for long-running streaming jobs with strong consistency, and it can handle state keyed by event attributes (for aggregation or joins) efficiently. It can manage very large state and exactly-once processing, making it suitable for heavy streaming tasks like anomaly detection or real-time metrics computation.&nbsp;<strong>Apache Spark Streaming</strong> is another, though it traditionally micro-batches data (with very small batches) and may have slightly higher latencies; still, it can process large throughput and integrates with the Spark ecosystem for machine learning models, etc.</p><div class="pullquote"><p>Imagine a pipeline where all logs go to Kafka. A Flink job reads the logs, does a regex to categorize error messages, and maintains a count per error pattern per service per minute. It then emits a metric (service, error_pattern -&gt; count) into a metrics backend or sends an alert if the count exceeds a threshold. At the same time, the raw logs also flow to storage (maybe Loki). In this way, you&#8217;ve offloaded counting and alerting from the heavy log search later &#8211; operators get an alert &#8220;Error X occurred 5000 times in service Y in 1 minute&#8221; immediately, with perhaps a link to one example log or trace. This is much faster than waiting to notice in a dashboard or manually search logs, and it reduced the problem to analyzing aggregated metrics rather than countless log lines.</p></div><h3><strong>Placement in Pipeline</strong></h3><p>Streaming processors usually subscribe to the message bus (Kafka topics) where telemetry flows. For example, you can have a Kafka consumer in Flink reading the &#8220;logs&#8221; topic, performing transformations, and then outputting to another Kafka topic or directly to storage/alerts. Some systems use event streaming frameworks like&nbsp;<strong>Apache Pulsar</strong>&nbsp;or <strong>AWS Kinesis</strong>&nbsp;similarly to Kafka &#8211; Flink can consume from those as well. If using an agent-to-collector direct pipeline without Kafka, you can still fork data to a stream processor via a collector that has multiple exporters (one to storage, one to an analytics service).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fpj-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fpj-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png 424w, https://substackcdn.com/image/fetch/$s_!fpj-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png 848w, https://substackcdn.com/image/fetch/$s_!fpj-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png 1272w, https://substackcdn.com/image/fetch/$s_!fpj-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fpj-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png" width="2000" height="1057" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1057,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 3&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 3" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 3" srcset="https://substackcdn.com/image/fetch/$s_!fpj-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png 424w, https://substackcdn.com/image/fetch/$s_!fpj-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png 848w, https://substackcdn.com/image/fetch/$s_!fpj-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png 1272w, https://substackcdn.com/image/fetch/$s_!fpj-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7732958f-4a30-4307-ac80-af84448b42bd_2000x1057.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">High-level illustration of a Telemetry Pipeline</figcaption></figure></div><p>One must be mindful that adding streaming jobs can add processing load and possibly latency. If the requirement is real-time (&lt;1s) detection, Flink can achieve sub-second latency with tuned pipelines, but typically expect a couple seconds end-to-end. For many monitoring cases (which often tolerate a few seconds delay), this is fine.</p><h3><strong>Resource Considerations</strong></h3><p>Running Flink at scale means provisioning a Flink cluster with enough parallel tasks to handle the input rate. You partition the stream (say by key) and Flink parallelism maps to Kafka partitions usually. This needs maintenance and monitoring itself (metrics for job lag, checkpoint duration, etc., which ironically you might feed into the same telemetry pipeline!). It&#8217;s advanced but powerful. If adopting this, ensure backpressure in the Flink job doesn&#8217;t block the main pipeline. Ideally, because Kafka decouples, if Flink is slow the Kafka topic will accumulate some lag, but that&#8217;s okay as long as within retention. You would alert on the lag and scale Flink or investigate.</p><p>In conclusion, real-time stream processing is an optional but valuable component in a high-volume telemetry pipeline for&nbsp;<strong>deriving immediate insights and reducing data</strong>. It leverages big data stream processors (Flink, Spark) similarly to how one would in other big data domains. The main caution is complexity &#8211; operating these systems and writing stream processing jobs requires expertise, and one must always weigh if the benefit (e.g. slightly faster detection, lower storage usage) is worth the operational cost. Many large organizations find that for certain use cases (like anti-fraud, or automated incident response), streaming analytics in the observability pipeline is indeed worth it.</p><h2><strong>Queuing, Buffering, and Backpressure Management</strong></h2><p>In any high-volume pipeline,&nbsp;<strong>backpressure</strong>&nbsp;&#8211; what happens when one part of the system can&#8217;t keep up with the incoming data &#8211; is a critical aspect. A well-designed telemetry pipeline should handle temporary slowdowns gracefully via queuing and buffering, rather than crashing or blocking upstream components.</p><p>We&#8217;ve already touched on the primary buffering mechanism:&nbsp;<strong>persistent queues like Kafka</strong>. By writing telemetry events to Kafka (with sufficient retention and disk space), you create a durable buffer. If, say, the log indexing service goes down for a bit, the logs pile up in Kafka and can be consumed later once it&#8217;s back (albeit with increased latency). Kafka decouples throughput differences: producers can continue at their own pace, and consumers process as fast as they can, with Kafka&#8217;s logs absorbing the difference. Kafka&#8217;s design of persistent log with sequential writes allows it to handle high volumes with durability &#8211; that&#8217;s why it&#8217;s widely used for backpressure handling. In essence, adding a queue means&nbsp;<em>trading memory for time</em>: you use storage (memory/disk in the queue) to hold data until the system can catch up, instead of dropping data or exerting backpressure on producers.</p><h3><strong>In-memory vs On-disk Buffers</strong></h3><p>On smaller scales or within components, in-memory buffers are used. For example, the OpenTelemetry Collector has a queue (by default, bounded memory) for each exporter pipeline. If the backend is slow, the collector&#8217;s queue starts filling. Once it hits a high-water mark, the collector can either drop data or apply backpressure upstream. The OTel Collector also has a&nbsp;<strong>memory limiter</strong>&nbsp;that can trigger once memory is near capacity, which will start shedding load (dropping new data) to protect the process. Some components (like Fluentd) use file buffering &#8211; Fluentd can spill to disk so that it doesn&#8217;t drop logs if the output is unavailable; it will retry later. This is a form of backpressure absorption (disk is the buffer). The drawback is if the outage is long or throughput is very high, buffers can exhaust (disk fills up, memory exhausted). Thus sizing buffers and setting retention limits is important (e.g., keep at most 1 hour of data buffered, after which start dropping oldest).</p><h3><strong>Backpressure vs Dropping</strong></h3><p>There are two ways when saturated: exert backpressure upstream (i.e., make producers slow down) or drop data. In observability, dropping data is often acceptable (missing some telemetry might be better than causing an outage of the app). For metrics, losing a couple data points usually just shows as a gap. For logs and traces, dropping means you lose some insight but the system stays up. On the other hand, if you propagate backpressure to the applications (e.g. a trace SDK blocking a request thread because the exporter queue is full), that can impact production traffic &#8211; usually not acceptable. Therefore, telemetry pipelines prefer an &#8220;eventually drop&#8221; strategy under extreme overload rather than slowing the source. This is why many telemetry systems implement&nbsp;<strong>dropping policies</strong>: e.g. &#8220;if my span queue is full, start sampling more aggressively (dropping spans)&#8221;. An example is an OpenTelemetry Collector under backpressure will shed load by dropping new spans to ensure it doesn&#8217;t OOM. It&#8217;s a deliberate trade-off: you lose visibility rather than risk system stability.</p><p>However, a degree of backpressure signalling can be useful in less critical parts. For example, Fluent Bit might intentionally not acknowledge log reads if the forwarder is behind, causing a container runtime&#8217;s log driver to apply backpressure (preventing log file from growing infinitely). This might slow the application&#8217;s logging (which typically is non-blocking anyway if writing to a file). Or Kafka producers can be configured with&nbsp;acks=all&nbsp;and limited in-flight requests, so if brokers are slow, the producers will wait &#8211; this effectively paces the ingestion to what the cluster can handle. This is fine as long as it doesn&#8217;t directly impact end-user response times (it might just mean logs are slightly delayed).</p><h3><strong>Horizontal Scaling to Avoid Backpressure</strong></h3><p>The primary solution to backpressure is to scale out the bottleneck. If your Kafka consumer (log indexer) can&#8217;t keep up, add more consumers (and likely more Kafka partitions to parallelize). If one Elasticsearch node is maxed on ingest, add more nodes (shards) to split load. Essentially every stage should be scalable so that the system can adapt to higher throughput rather than just queue forever. Monitoring plays a role: you should watch queue lengths and consumer lags. For example, monitor Kafka lag &#8211; if it&#8217;s growing consistently, that&#8217;s a red flag that consumption can&#8217;t keep up with production. Similarly, monitor the CPU of your ingesters or memory of your collectors to spot bottlenecks early.</p><h3><strong>Backpressure in Streaming Jobs</strong></h3><p>If you use streaming processors like Flink, they have built-in backpressure signaling &#8211; if a sink is slow, it will propagate back to slow down ingestion reading from Kafka. This means data accumulates in Kafka (as intended). Flink metrics will show this as increasing checkpoint durations or source idle time. You&#8217;d then act by scaling the Flink job or fixing the slow sink.</p><h3><strong>Graceful Degradation</strong></h3><p>Some pipelines implement graceful degradation under extreme load. For instance, dynamically raise the sampling rate (reduce trace volume) if the tracing backend is falling behind, or drop all debug-level logs when the system is in &#8220;overload mode&#8221;. These require feedback mechanisms and are complex but can save the day. A simpler version is having hard caps &#8211; e.g., if the logging rate exceeds X MB/s, start dropping non-critical logs.</p><div class="pullquote"><p>Suppose a spike occurs and your log volume doubles for 5 minutes (maybe a bug causing a flood of warnings). Your pipeline: Fluent Bit -&gt; Kafka -&gt; Elasticsearch. What happens? Fluent Bit will push to Kafka as fast as it can. Kafka brokers, if not sized for this, might start to see high disk IO. But likely they handle it by writing to disk (using available retention headroom). The consumers reading into Elasticsearch might fall behind because Elasticsearch can index at only the original rate. Kafka&#8217;s lag grows. After the 5 minutes, log rate returns to normal. Now Elasticsearch consumers continue to work through the backlog (maybe for the next 30 minutes) until the lag returns to zero. No data was lost, just delayed. If another spike comes and the lag hasn&#8217;t cleared, you might accumulate more. If Kafka&#8217;s retention (say 1 day or a set byte size) is exceeded, then oldest messages (which might not be processed yet) will start dropping. That sets an upper bound on how much burst you can handle without loss.</p></div><p>From above example, key backpressure management points:&nbsp;<strong>sizing</strong>&nbsp;(Kafka had enough spare capacity),&nbsp;<strong>monitoring</strong>&nbsp;(know your lag), and possibly&nbsp;<strong>alerts</strong>&nbsp;(if lag &gt; certain threshold, alert to scale or investigate).</p><p>In scenarios without Kafka, say OTel Collector direct to backend, you&#8217;d rely on its internal queue. If backend is slow, the queue fills and then it starts dropping. That&#8217;s fine if brief, but if persistent, you&#8217;ll lose data. Therefore, many prefer an external queue for anything mission-critical.</p><p>In short,&nbsp;<strong>buffering and backpressure management</strong>&nbsp;ensure your pipeline remains&nbsp;<strong>robust under sudden load spikes or downstream slowness</strong>. Use persistent queues for big stages, tune in-memory buffers for smaller ones, and prefer dropping telemetry data over causing application interference when push comes to shove. And always keep an eye on those queues!</p><div><hr></div><p>In&nbsp;<strong>Part 4</strong>, we&#8217;ll address how to make the entire pipeline horizontally scalable and highly available, explore cost management and retention policies, and examine lessons learned from production deployments. <em>Happy Flinking!</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;76ccf2a7-aea0-4131-8a03-db58bac93192&quot;,&quot;caption&quot;:&quot;In Part 3, we explored building scalable telemetry pipelines with agents, batching, Kafka buffering, and backpressure control for resilient observability. Now let's bring it home with this last part of our blog series by addressing how to make the entire pipeline horizontally scalable and highly available, explore cost management and retention policies,&#8230;&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 4&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-05-15T06:34:16.000Z&quot;,&quot;cover_image&quot;:&quot;https://www.observability.how/content/images/2025/05/scaling-observability-4.jpg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-4&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843140,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Groundcover Secures $35M to Challenge Observability Giants]]></title><description><![CDATA[In a significant shake-up within the observability space, Israeli startup Groundcover recently announced a $35 million Series B funding round, led by Zeev Ventures, bringing their total funding to $60 million.]]></description><link>https://www.observability.how/p/groundcover-secures-35m-to-challenge-observability-giants</link><guid isPermaLink="false">https://www.observability.how/p/groundcover-secures-35m-to-challenge-observability-giants</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Mon, 12 May 2025 05:30:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/503cd208-bb00-4836-986d-84c53e6be71c_1395x585.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!m1fs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!m1fs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png 424w, https://substackcdn.com/image/fetch/$s_!m1fs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png 848w, https://substackcdn.com/image/fetch/$s_!m1fs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png 1272w, https://substackcdn.com/image/fetch/$s_!m1fs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!m1fs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Groundcover Secures $35M to Challenge Observability Giants&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Groundcover Secures $35M to Challenge Observability Giants" title="Groundcover Secures $35M to Challenge Observability Giants" srcset="https://substackcdn.com/image/fetch/$s_!m1fs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png 424w, https://substackcdn.com/image/fetch/$s_!m1fs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png 848w, https://substackcdn.com/image/fetch/$s_!m1fs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png 1272w, https://substackcdn.com/image/fetch/$s_!m1fs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffde97d-210f-4ee2-a47e-0c1723647209_1395x585.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><p>In a significant shake-up within the observability space, Israeli startup <a href="https://www.groundcover.com/?ref=observability.how">Groundcover</a> recently announced a <a href="https://techfundingnews.com/exclusive-israeli-groundcover-grabs-35m-to-redefine-cloud-monitoring-with-its-next-gen-platform-challenging-datadogs-dominance/?ref=observability.how">$35 million Series B funding round</a>, led by Zeev Ventures, bringing their total funding to $60 million. This latest funding underscores the industry's strong appetite for modern, streamlined observability solutions designed for cloud-native ecosystems.</p><h2><strong>Why Groundcover?</strong></h2><p>Groundcover addresses two pressing challenges in observability: the complexity of instrumenting applications and the unpredictable costs associated with data volume-based pricing models.&nbsp;By leveraging <a href="https://ebpf.io/?ref=observability.how">eBPF</a> (extended Berkeley Packet Filter) technology, Groundcover provides deep, comprehensive visibility into infrastructure, applications, and network interactions without requiring intrusive changes or additional coding. This dramatically simplifies deployment and usage, particularly in complex, Kubernetes-driven environments.</p><p>A notable standout in Groundcover's offering is its "Bring Your Own Cloud" (BYOC) approach. Unlike legacy vendors like Datadog and New Relic, which typically manage customer data within their own infrastructure, Groundcover enables customers to maintain full control and ownership of their observability data within their own cloud environments. This model ensures enhanced data privacy, compliance, and security&#8212;critical considerations for enterprises operating in highly regulated industries or with stringent data governance requirements.</p><h2><strong>Differentiation from Datadogs of the world!</strong></h2><p>While well-established platforms offer comprehensive observability solutions, Groundcover distinguishes itself in several key areas:</p><ul><li><p><strong>Deployment and Setup</strong>: Groundcover boasts a user-friendly interface with an &#8220;Ease of Setup&#8221; <a href="https://www.g2.com/compare/dynatrace-vs-groundcover-vs-datadog?ref=observability.how">rating of 9.2</a>, compared to Datadog's and Dynatrace&#8217;s 8.4. &nbsp;&nbsp;</p></li><li><p><strong>Performance Monitoring</strong>: Users have rated Groundcover&#8217;s performance monitoring capabilities at <a href="https://www.g2.com/compare/dynatrace-vs-groundcover-vs-datadog?ref=observability.how">9.4</a>, indicating robust insights into application performance.&nbsp;&nbsp;</p></li><li><p><strong>Cost Structure</strong>: Groundcover&#8217;s pricing model is based on the number of nodes, offering predictable costs, unlike the volume-based pricing of some competitors.&nbsp;&nbsp;</p></li><li><p><strong>Kubernetes-Centric Insights</strong>: Designed with cloud-native architectures in mind, Groundcover provides detailed visibility into Kubernetes environments, including workloads, nodes, pods, and events.&nbsp;&nbsp;</p></li></ul><h2><strong>Industry Adoption</strong></h2><p>Groundcover&#8217;s approach has resonated with organizations seeking efficient and scalable observability solutions. For instance, a leading cloud security firm <a href="https://www.groundcover.com/customer-stories/cloud-security-leader-replaces-datadog-with-groundcover?ref=observability.how">replaced Datadog with Groundcover</a> to enhance Kubernetes monitoring, achieving comprehensive coverage across development, staging, and production clusters while realizing significant cost savings.&nbsp;&nbsp;</p><div><hr></div><p>Groundcover&#8217;s recent funding underscores a growing demand for observability tools that align with the needs of modern, cloud-native infrastructures. By addressing common pain points such as complex instrumentation and unpredictable costs, Groundcover positions itself as a compelling alternative to legacy observability vendors.&nbsp;</p><blockquote><p><em>For more insights into observability trends and tools, stay tuned to <a href="https://www.observability.how/">Observability.how</a>.</em></p></blockquote>]]></content:encoded></item><item><title><![CDATA[Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2]]></title><description><![CDATA[In the Part 1, we saw that a scalable pipeline architecture consists of data collection, processing, storage, and querying stages, with key design principles including horizontal scaling, stateless processing, and backpressure management.]]></description><link>https://www.observability.how/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-2</link><guid isPermaLink="false">https://www.observability.how/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-2</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Sun, 04 May 2025 21:20:03 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e036351f-44ef-4305-9b8f-4e4d2a636ac6_1792x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EkCv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EkCv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png 424w, https://substackcdn.com/image/fetch/$s_!EkCv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png 848w, https://substackcdn.com/image/fetch/$s_!EkCv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!EkCv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EkCv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" srcset="https://substackcdn.com/image/fetch/$s_!EkCv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png 424w, https://substackcdn.com/image/fetch/$s_!EkCv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png 848w, https://substackcdn.com/image/fetch/$s_!EkCv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!EkCv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0dfc00d9-8fb3-495d-8400-030de98a3397_1792x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>In the Part 1, we saw that a scalable pipeline architecture consists of data collection, processing, storage, and querying stages, with key design principles including horizontal scaling, stateless processing, and backpressure management. Now, let's examine specialized scaling strategies for each telemetry signal type.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;97b56e85-9b04-4804-b839-6f06fda40b6d&quot;,&quot;caption&quot;:&quot;Building observability in large-scale, cloud-native systems requires collecting telemetry data (metrics, traces, and logs) at extremely high volumes. Modern platforms like Kubernetes can generate millions of metrics, traces, and log events per second&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 1&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-28T05:50:41.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6fbcbdee-0101-4d9c-92af-30d7869dbbb2_1472x832.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-1&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843146,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>Scaling Metrics Pipelines</h2><p>Metrics are the bread-and-butter of monitoring, and at scale they present unique challenges. A single Kubernetes cluster can easily produce&nbsp;<strong>millions of metric samples per second</strong>&nbsp;(from container stats, application metrics, etc.), and enterprises often want to retain metrics for long periods (months or years) for trend analysis. The two big issues are&nbsp;<strong>throughput</strong>&nbsp;(ingesting and storing the metric samples) and&nbsp;<strong>cardinality</strong>&nbsp;(the number of unique time-series).</p><h3>Collection</h3><p>In cloud-native setups, metrics collection is often done via&nbsp;<strong>Prometheus</strong>-style scraping: each service or node exposes an HTTP endpoint with its metrics, and a Prometheus server (or multiple) scrapes these periodically (e.g. every 15s). At very high scale, a single Prometheus instance is insufficient &#8211; it has a limit on samples per second it can scrape and store before performance degrades. Solutions include sharding the scrape load across multiple Prometheus servers or using an agent like the OpenTelemetry Collector to push metrics. Many large deployments switch to a <strong>&#8220;pull into push&#8221; model</strong>: Prometheus scrapes locally and then&nbsp;<strong>remote-writes</strong>&nbsp;the data to a scalable backend. The backend, such as&nbsp;<strong>Grafana Mimir or Cortex</strong>, is a distributed time-series database that can handle far more data than a single Prometheus instance.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;41955529-466b-41db-8e9c-941cc4531d14&quot;,&quot;caption&quot;:&quot;OpenTelemetry&#8217;s Collector is a vendor-neutral service that sits between your applications and observability backends. It can receive telemetry data (traces, metrics, logs), process or transform it, and export it to one or multiple destinations. In a production environment, the Collector becomes essential for building a&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Using the OpenTelemetry Collector: A Practical Guide&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-17T07:56:28.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5151a4d-0495-4388-9617-364ce63da4e5_1996x1192.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/using-the-opentelemetry-collector-a-practical-guide&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843148,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><h3>Distributed Metric Storage</h3><p>Cortex and its successor Grafana Mimir were designed to make Prometheus horizontally scalable and multi-tenant. They break the work into microservices (often called&nbsp;<strong>distributors, ingesters, queriers, etc.</strong>). For example, Grafana Mimir&#8217;s architecture has a <strong>write path</strong>&nbsp;where incoming metric samples are routed by a distributor to a set of <strong>ingesters</strong>, which buffer and batch data into storage. Each ingester handles a subset of series (using hashing to divide series among ingesters) and writes data in efficient chunks. Data is replicated for reliability &#8211; by default, each time-series is replicated to three ingesters. The ingesters periodically flush data to long-term storage (such as an object store like S3, storing data in blocks, often using TSDB format). A&nbsp;<strong>compactor</strong>&nbsp;service later deduplicates and compacts these blocks. On the&nbsp;<strong>read path</strong>, query frontend nodes split queries by time, cache results, and load-balance queries to querier nodes which retrieve data from both ingesters (for recent in-memory data) and long-term storage via store-gateway nodes.</p><p>The result is a system where you can linearly scale metric ingestion by adding more ingesters (and CPU/memory) and scale query capacity by adding more queriers. Grafana Mimir, for instance, has demonstrated the ability to&nbsp;<strong><a href="https://grafana.com/blog/2022/04/08/how-we-scaled-our-new-prometheus-tsdb-grafana-mimir-to-1-billion-active-series/?ref=observability.how">scale to 1 billion active series and 50 million samples per second ingestion</a></strong>&nbsp;in benchmarking (using a huge cluster of 7000 CPU cores and 30+ TB RAM). While few need that extreme, this shows that with the right architecture, metric pipelines can push the limits of volume. Cortex/Mimir also enforce per-tenant limits to prevent any single team from overloading the system (e.g. cap number of series to avoid unbounded cardinality).</p><p>Other scalable metric systems exist as well:&nbsp;<strong><a href="https://thanos.io/?ref=observability.how">Thanos</a></strong>, which federates Prometheus servers by storing historical data in object storage and querying across instances, or&nbsp;<strong><a href="https://victoriametrics.com/?ref=observability.how">VictoriaMetrics</a></strong>, a high-performance time-series database known for efficiency. Whether using these or a hosted solution (like <a href="https://aws.amazon.com/prometheus/?ref=observability.how">AWS Managed Prometheus</a>), the key strategies are similar:&nbsp;<strong>horizontally partition metrics</strong>&nbsp;and use distributed storage.</p><h3>Aggregation and Downsampling</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mpPA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mpPA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png 424w, https://substackcdn.com/image/fetch/$s_!mpPA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png 848w, https://substackcdn.com/image/fetch/$s_!mpPA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png 1272w, https://substackcdn.com/image/fetch/$s_!mpPA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mpPA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png" width="500" height="410" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a16c2820-b007-4381-a168-835dcac25383_500x410.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:410,&quot;width&quot;:500,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" srcset="https://substackcdn.com/image/fetch/$s_!mpPA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png 424w, https://substackcdn.com/image/fetch/$s_!mpPA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png 848w, https://substackcdn.com/image/fetch/$s_!mpPA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png 1272w, https://substackcdn.com/image/fetch/$s_!mpPA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16c2820-b007-4381-a168-835dcac25383_500x410.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>An important technique for metrics is pre-aggregation and downsampling. Not every raw metric needs to be stored at full resolution forever. Often, we aggregate at source &#8211; for example, an app might pre-compute count/minute or P90 latency to reduce the number of data points sent. Or the pipeline (via a collector or streaming job) might aggregate metrics from multiple instances (sum of all instances&#8217; metrics) to reduce data points.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!scA5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!scA5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png 424w, https://substackcdn.com/image/fetch/$s_!scA5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png 848w, https://substackcdn.com/image/fetch/$s_!scA5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png 1272w, https://substackcdn.com/image/fetch/$s_!scA5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!scA5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png" width="591" height="74" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:74,&quot;width&quot;:591,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" srcset="https://substackcdn.com/image/fetch/$s_!scA5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png 424w, https://substackcdn.com/image/fetch/$s_!scA5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png 848w, https://substackcdn.com/image/fetch/$s_!scA5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png 1272w, https://substackcdn.com/image/fetch/$s_!scA5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b2c116-cfe7-4f28-91be-c31b7cf034e8_591x74.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Metrics Downsampling</figcaption></figure></div><p>Additionally, after storing high-resolution data for a short period, older data can be downsampled (e.g. store 5-minute averages instead of 15-second data beyond 30 days). Systems like Mimir support recording rules or downsampling jobs to accomplish this. This significantly cuts storage needs while preserving long-term trends.</p><h3>Metric Cardinality control</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nSdY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nSdY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png 424w, https://substackcdn.com/image/fetch/$s_!nSdY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png 848w, https://substackcdn.com/image/fetch/$s_!nSdY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png 1272w, https://substackcdn.com/image/fetch/$s_!nSdY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nSdY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png" width="720" height="246" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:246,&quot;width&quot;:720,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" srcset="https://substackcdn.com/image/fetch/$s_!nSdY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png 424w, https://substackcdn.com/image/fetch/$s_!nSdY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png 848w, https://substackcdn.com/image/fetch/$s_!nSdY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png 1272w, https://substackcdn.com/image/fetch/$s_!nSdY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0e4e86e-c851-45e4-b610-f3dae034186f_720x246.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Metric Cardinality</figcaption></figure></div><p>High-cardinality metrics (e.g. a metric labeled with userId or requestID) can blow up the number of time-series and choke the pipeline. Large organizations implement guidelines and sometimes automated checks to&nbsp;<strong>limit metric labels</strong>. Some metric backends allow dropping or relabeling metrics that exceed cardinality thresholds. At scale, you might also utilize hierarchical metrics (aggregating by service, not by individual IDs) and use exemplars or tracing for the per-ID detail instead.</p><p>In summary, a scalable metrics pipeline in a Kubernetes/hybrid environment might look like: an&nbsp;<strong>agent or sidecar on each node</strong>&nbsp;(Prometheus or OTel Collector) scraping local metrics, forwarding to a central&nbsp;<strong>metrics gateway</strong>&nbsp;(like a Cortex/Mimir distributor cluster) which writes to a&nbsp;<strong>distributed TSDB</strong>. The system is tuned to handle bursts (by batching samples), and you apply aggregation/sampling on metrics where possible. The metric store is configured for replication and long-term retention by offloading old data to cheap storage (e.g. S3). With this approach, companies can retain even millions of series of metrics cost-effectively. The trade-off is complexity: you now operate a complex distributed system for metrics, but it&#8217;s necessary once you outgrow a single-node Prometheus.</p><div><hr></div><h2><strong>Scaling Traces Pipelines</strong></h2><p>Distributed tracing provides deep insights but is notorious for volume explosion. In a microservices architecture, a single user request might generate tens or hundreds of spans. Capturing every trace from every request at a large scale (say, thousands of requests per second) can overwhelm storage and network. Thus, <strong>sampling</strong>&nbsp;is a core strategy in high-volume tracing.</p><h3>Trace Sampling Strategies</h3><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GRPW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GRPW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png 424w, https://substackcdn.com/image/fetch/$s_!GRPW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png 848w, https://substackcdn.com/image/fetch/$s_!GRPW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png 1272w, https://substackcdn.com/image/fetch/$s_!GRPW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GRPW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png" width="197" height="194" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/973485fb-6593-47cb-b706-35e0a4876e33_197x194.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:194,&quot;width&quot;:197,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" srcset="https://substackcdn.com/image/fetch/$s_!GRPW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png 424w, https://substackcdn.com/image/fetch/$s_!GRPW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png 848w, https://substackcdn.com/image/fetch/$s_!GRPW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png 1272w, https://substackcdn.com/image/fetch/$s_!GRPW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F973485fb-6593-47cb-b706-35e0a4876e33_197x194.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Trace Sampling</figcaption></figure></div><p>There are a few common sampling strategies in use:</p><ul><li><p><strong>Head-Based (Probabilistic) Sampling:</strong>&nbsp;Decide whether to sample a trace at the start of the trace (when the first span begins). This is usually a random probability (e.g. sample 1% of traces) or based on some simple criteria on the root span. Once the decision is made on the root span, that decision propagates to all spans in that trace (so you either keep the entire trace or drop it). Head-based sampling is&nbsp;<strong>simple and scalable</strong>&nbsp;&#8211; it&#8217;s implemented in the tracing SDKs, so unwanted traces are never even sent out by applications. It&#8217;s like judging a book by its cover: very fast but potentially &#8220;shallow&#8221;. The downside is you might drop interesting traces (e.g. ones with errors) just by random chance, since the decision can&#8217;t consider what hasn&#8217;t happened yet. However, head sampling has minimal overhead and works well with parallel collectors (no need to coordinate). Many organizations run with a low probabilistic sample rate globally (like 0.1% of requests) as a baseline.</p></li><li><p><strong>Tail-Based Sampling:</strong>&nbsp;Decide whether to keep a trace&nbsp;<strong>after it has completed</strong>, i.e. after collecting all spans. This is like reading the entire book then deciding if it was interesting. Tail-based sampling allows much smarter decisions &#8211; for example, &#8220;keep all traces that had an error or a 5xx status code&#8221; or &#8220;keep 10% of traces for VIP customers and 1% of others&#8221;. You can implement rich policies: sample 100% of slow requests, or a higher rate for certain critical services, etc. The OpenTelemetry Collector&#8217;s tail-sampling processor supports rules on trace attributes, error flags, latency, and more. The&nbsp;<strong>trade-off</strong>&nbsp;is that tail sampling is resource-intensive: you must ingest&nbsp;<em>all spans</em>&nbsp;(at least buffering them) and then discard traces you don&#8217;t need. This puts overhead on the applications (they must emit every trace) and on the collectors/backends which have to hold a lot in memory. Implementing tail sampling in a distributed collector cluster requires careful design: typically a first layer of collectors does &#8220;span routing&#8221; to ensure all spans of a trace go to the same process (often using consistent hashing on trace ID), then a second layer actually applies the sampling decision. This two-layer approach adds complexity and network hops, and the buffering (usually spans are held for a few seconds) can strain memory. Therefore, many organizations only use tail sampling for specific high-value traces (like error traces) or in lower-volume environments.</p></li><li><p><strong>Remote or Dynamic Sampling:</strong>&nbsp;A form of head-based sampling where the decision policy is centrally controlled and can change on the fly. Jaeger, for instance, supports remote sampling configurations &#8211; services poll a central config to get sampling rates per endpoint or operation. This allows adjusting sampling without redeploying apps; for example, during an incident you might temporarily increase sampling to get more traces for debugging. Remote sampling is essentially still head sampling (the app makes the call), but it&#8217;s &#8220;smart head sampling.&#8221; Many large deployments use this to manage sampling strategies centrally.</p></li></ul><p>In practice,&nbsp;<strong>large-scale tracing</strong>&nbsp;pipelines often use a combination: heavy head-based probabilistic sampling to cut down volume (e.g. 90% of traces dropped), plus tail-based sampling in the collector to ensure certain categories are always kept (like error traces or extreme latency outliers). The combination yields a representative set of traces without overloading the system with every single request.</p><h3>Ingestion and Transport for Traces</h3><p>On the collection side, the common pattern is deploying&nbsp;<strong>OpenTelemetry SDKs</strong>&nbsp;in applications which export spans to a local agent (like an OpenTelemetry Collector or a Jaeger Agent as a sidecar/daemonset). The agent/collector batches spans and sends them to a central trace collector cluster. Using an agent on each host helps by batching and compressing data, and it can tag spans with metadata (like host name, cluster, etc.). The central collectors (which might be an OpenTelemetry Collector cluster or Jaeger collectors) then handle the data pipeline &#8211; possibly doing tail-sampling, transformations, and writing to storage. Because trace data can burst (a spike in traffic yields a spike in spans), organizations often&nbsp;<strong>buffer trace data in a message queue</strong>&nbsp;such as Kafka. In fact, Jaeger has optional support for using Kafka as the transport between agents and collectors (spans go into Kafka, and collectors consume from Kafka). Kafka decouples the ingestion from processing, providing durability and the ability to replay or handle spikes (more on Kafka in Part 3).</p><h3>Trace Storage Backends</h3><p>Storing traces efficiently is tricky. Traditional backends used by Jaeger and Zipkin include Cassandra or Elasticsearch for indexing spans. However, at cloud scale, these can be expensive and operationally complex. For instance, Elasticsearch can index trace data for rich search, but with large ES cluster the <strong>costs compound as you store more data</strong>, and are complex to manage. A newer approach exemplified by&nbsp;<strong><a href="https://grafana.com/docs/tempo/latest/operations/architecture/?ref=observability.how">Grafana Tempo</a></strong>&nbsp;(and similar ideas in AWS X-Ray) is to&nbsp;<strong>avoid heavy indexing </strong>and instead store trace data as cheap as possible. Grafana Tempo is an open-source,&nbsp;<strong>high-volume tracing backend that allows 100% sampling</strong>&nbsp;by requiring only object storage (like S3 or GCS) as its database. Tempo does minimal indexing &#8211; typically just an ID to find a trace &#8211; which means it cannot query traces by arbitrary tags, only by trace ID or via external hints. This design allows Tempo to <a href="https://grafana.com/go/webinar/getting-started-with-tracing-tempo-apac/?ref=observability.how">&#8220;hit massive scale without a difficult-to-manage Elasticsearch or Cassandra cluster&#8221;</a>. In other words, you could ingest millions of spans/sec and store all of them cheaply, but you need another way to find interesting traces (such as linking from metrics or logs). Grafana uses <strong>exemplars</strong>&nbsp;&#8211; when a metric has an anomaly, an exemplar (a sample trace ID) is recorded &#8211; to jump from metrics to traces, thereby mitigating the need for full-text trace search.</p><p>Other organizations use a similar concept of splitting storage: e.g. store recent traces in a fast index (Elasticsearch) but archive older traces to cheap storage (like a data lake) without indexes. The choice often comes down to use case: Do you need to search traces by user ID or error message frequently (then you need indexing and will incur more cost)? Or is it sufficient to sample many traces and use metrics to point you to relevant ones? At extreme scale, many opt for the latter approach due to cost.</p><h3>Additional Considerations</h3><p>Key techniques include&nbsp;<strong>sharding by trace ID</strong>&nbsp;(so different collectors handle different sets of traces, ensuring all spans of a trace go to one shard) and&nbsp;<strong>scaling horizontally</strong>&nbsp;both the collectors and storage nodes. A challenge with horizontal scaling is maintaining ordering for tail sampling (the aforementioned need for routing spans). OpenTelemetry&#8217;s collector has a&nbsp;<em><a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/e0646e1c227019fc90576f566ef005b44e572f7d/exporter/loadbalancingexporter/README.md?ref=observability.how">load-balancing exporter</a></em>&nbsp;that can consistently hash traceIDs to collector instances. This allows adding more collector instances as needed to increase throughput, without mixing spans from one trace across them.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!44lS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!44lS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png 424w, https://substackcdn.com/image/fetch/$s_!44lS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png 848w, https://substackcdn.com/image/fetch/$s_!44lS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png 1272w, https://substackcdn.com/image/fetch/$s_!44lS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!44lS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png" width="533" height="279" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:279,&quot;width&quot;:533,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" srcset="https://substackcdn.com/image/fetch/$s_!44lS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png 424w, https://substackcdn.com/image/fetch/$s_!44lS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png 848w, https://substackcdn.com/image/fetch/$s_!44lS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png 1272w, https://substackcdn.com/image/fetch/$s_!44lS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F153128cb-f66b-4a46-93b8-ce5587689f8f_533x279.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Sharding by Trace ID</figcaption></figure></div><p>Additionally, the pipeline must avoid overwhelming apps. Tracing can add overhead in the application (serialization, network calls to send spans). Good practice is to make these&nbsp;<strong>non-blocking and low priority</strong>&nbsp;&#8211; e.g. use asynchronous exports and never slow down the business logic if the tracing pipeline is slow. If the pipeline backs up, the collector or SDK should start dropping spans rather than causing backpressure on the application threads (thus trading completeness for resiliency). This ties into backpressure management which we&#8217;ll discuss in Part 3.</p><p>In summary, a scalable tracing pipeline for millions of spans uses aggressive sampling up front, distributed collectors (often with Kafka in between), and a storage solution that is designed for high write throughput. It might store only sampled traces or use a two-tier approach (e.g. all traces for a short window, then downsampled for longer-term). Trace IDs are propagated everywhere (including in logs and metrics as labels) to allow correlation. The pipeline also often provides ways to get the &#8220;best of both worlds&#8221; &#8211; for example, head sample 1% of everything, but tail sample 100% of traces that are errors or have certain characteristics. That way, you drastically cut volume but still catch the important stuff. The trade-off here is that you might not have every single user&#8217;s trace, but you have enough data to diagnose issues, which is the point of observability after all.</p><div><hr></div><h2><strong>Scaling Log Pipelines</strong></h2><p>Logs often account for the highest volume of telemetry data in large systems. Every application instance can emit multiple log lines per request or per second, leading to a firehose of unstructured data. Unlike metrics (which are numeric) or traces (which are structured spans), logs are semi-structured text and require indexing to query effectively (e.g. full-text search for error keywords). Scaling a log pipeline means handling huge ingest rates, indexing or storing efficiently, and managing retention.</p><h3>Log Ingestion and Sharding</h3><p>In Kubernetes, the de facto approach is using a&nbsp;<strong>node-level log agent</strong>&nbsp;(like Fluent Bit, Fluentd, or OpenTelemetry Collector) deployed as a DaemonSet. This agent tails the container runtime&#8217;s log files (or reads from stdout via logging driver) for all pods on the node. The agent labels each log line with metadata (pod name, namespace, etc.) and then forwards logs to a central system. Fluent Bit is a popular choice because it&#8217;s written in C with low memory overhead, capable of handling high log volumes with minimal CPU. Fluentd (in Ruby/C) is heavier but has a richer plugin ecosystem. The pipeline typically&nbsp;<strong>streams logs into a message queue or directly to a storage backend</strong>. A common pattern is&nbsp;<strong>Logs -&gt; Fluent Bit -&gt; Kafka -&gt; [processing] -&gt; storage</strong>. Kafka, again, is used as a buffer to decouple and handle burstiness.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WJ5t!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WJ5t!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png 424w, https://substackcdn.com/image/fetch/$s_!WJ5t!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png 848w, https://substackcdn.com/image/fetch/$s_!WJ5t!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png 1272w, https://substackcdn.com/image/fetch/$s_!WJ5t!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WJ5t!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png" width="847" height="200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:200,&quot;width&quot;:847,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2" srcset="https://substackcdn.com/image/fetch/$s_!WJ5t!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png 424w, https://substackcdn.com/image/fetch/$s_!WJ5t!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png 848w, https://substackcdn.com/image/fetch/$s_!WJ5t!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png 1272w, https://substackcdn.com/image/fetch/$s_!WJ5t!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c3ba6d3-b05b-46b8-8326-843f53e2472b_847x200.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Sample Logs Pipeline</figcaption></figure></div><p>To scale ingestion, logs are usually partitioned by some key. If using Kafka, logs can be partitioned by an attribute (for example, by service name or by pod) ensuring the load is spread across Kafka brokers and across consumer instances later. If sending directly to an indexer like Elasticsearch, multiple ingest nodes can be behind a load balancer &#8211; each agent can hash or round-robin to different ingest endpoints. At very high rates, intermediate aggregators (Fluentd instances aggregating multiple Fluent Bit streams) might be introduced for hierarchical scaling.</p><h3><strong>Log Storage Solutions</strong></h3><p>The traditional solution is the&nbsp;<strong>ELK stack</strong>&nbsp;(Elasticsearch for storage/index, Logstash for processing (or Fluentd as an alternative), and Kibana for UI). Elasticsearch provides powerful full-text indexing and search on logs, which is incredibly useful (you can query on any field, do free-text search, aggregations, etc.). However, Elasticsearch can be&nbsp;<strong>expensive and challenging to scale</strong>&nbsp;to multi-terabyte/day log volumes. As logs grow, Elasticsearch clusters require many nodes, lots of IO and memory, and careful index management (sharding, replicas, index rotations). Many teams found that &#8220;free&#8221; ELK isn&#8217;t free at scale &#8211;&nbsp;<em><a href="https://www.chaossearch.io/blog/switching-from-the-elk-stack-elasticsearch-costs?ref=observability.how">&#8220;the underlying infrastructure of Elasticsearch is complex and costly, and those costs only compound as you scale and store more data&#8221;</a></em>. As data grows, the cluster needs frequent tuning and may still suffer from long query times or high storage costs (since each log is stored along with its index, which can be 2-3x the raw data size).</p><p>Because of this, newer approaches have emerged:</p><ul><li><p><strong>Schemaless Log Databases (Loki):</strong>&nbsp;Grafana Loki is a horizontally-scalable, highly available log system designed to reduce cost by&nbsp;<strong>limiting indexing</strong>. Loki takes inspiration from Prometheus: it treats logs as time-series with labels. It indexes only the labels (metadata like source, service, pod, etc.) and not the full text of the log line. The actual log messages are stored in compressed chunks in object storage, much like metric data. This means queries in Loki typically require specifying labels to narrow down log streams (e.g. app=X, pod=Y) and optionally a text filter which will be applied by scanning the chunks. Loki&#8217;s minimal indexing yields huge cost savings: it&nbsp;<strong>uses minimal indexing, compressed storage, and LogQL for fast queries</strong>. Loki&#8217;s architecture is again microservices: distributors, ingesters, queriers, etc., similar to Cortex/Mimir. It&#8217;s designed to be scaled out easily and to store logs cheaply. The trade-off: you need to plan what labels to index (because if you need to search by something not indexed, queries devolve to brute-force scans). For many observability use cases (where you know the service/pod and time range you want to inspect), Loki works extremely well and at a fraction of the cost of full-text indexing. Loki essentially shifts the problem to <strong>&#8220;index metadata, but not message content&#8221;</strong> &#8211; you might not want to use it if you frequently search logs for arbitrary substrings without context.</p></li><li><p><strong>Columnar Analytics Databases (ClickHouse):</strong>&nbsp;Some organizations repurpose big-data analytic databases for logs. ClickHouse, for example, is a columnar store that excels at aggregating large datasets. Logs can be structured (e.g. in JSON) and inserted into ClickHouse tables partitioned by date, service, etc. ClickHouse can&nbsp;<strong>compress data extremely well</strong>&nbsp;and uses column indexes (like skip indices and bloom filters) to speed up queries. It doesn&#8217;t automatically index every word like Elasticsearch, but if you structure your data, it can query certain fields very fast. In benchmarks, ClickHouse has shown much lower storage usage and faster aggregated queries compared to Elasticsearch. This makes it attractive for log analytics use cases where logs can be treated more like structured events (for example, counting errors, filtering by user ID, etc.). The downside is you may lose some of the flexible search capabilities unless you specifically index certain text fields.</p></li><li><p><strong>Data Lake and Query-on-demand:</strong>&nbsp;For long-term retention at minimal cost, some pipelines send a copy of logs to cloud storage (S3, Hadoop, etc.) in compressed form (possibly in JSON or Parquet format) and use query engines like Amazon Athena, Apache Drill, or <a href="https://trino.io/?ref=observability.how">Trino</a> to search them when needed. This is very cheap to store and only incurs cost or time when queries run. It&#8217;s not real-time (queries are slower), but for compliance or rarely accessed logs, this works well in tandem with a hot store. For instance, you might keep 7 days of logs in Elasticsearch for quick searches, but archive older logs to S3 and only query them via Athena when needed. This tiered storage approach is often used to keep costs manageable.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;baf37c32-9c09-40ef-aa5f-d15898f5a703&quot;,&quot;caption&quot;:&quot;Observability &#8211; encompassing logs, metrics, and traces &#8211; is the nervous system of modern IT operations. But it comes at a cost. As cloud-native applications and microservices proliferate, the volume of telemetry data has exploded. Companies using traditional SaaS observability platforms (Datadog, New Relic, Splunk, etc.) often face&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Building an In-House Observability Platform with a Data Lake (AWS S3 + Apache Iceberg)&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-05-16T20:01:25.000Z&quot;,&quot;cover_image&quot;:&quot;https://www.observability.how/content/images/2025/05/Observability-Platform-with-a-Data-Lake-2.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/building-an-in-house-observability-platform-with-a-data-lake&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843139,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></li></ul><h3><strong>Index Sharding and Retention</strong></h3><p>If using a system like Elasticsearch/OpenSearch, careful&nbsp;<strong>sharding strategy</strong>&nbsp;is essential. Typically logs are indexed by time (daily indices), and you can shard by an entity (like service or customer) if needed to parallelize writes. Setting the right number of shards per index and using rollover indices (to keep shard sizes ideal) is necessary to avoid hot spots. Also, use&nbsp;<strong>Index Lifecycle Management (ILM)</strong>: e.g. keep data in hot nodes for a few days, then move to warm nodes (cheaper storage), then cold, and eventually delete or snapshot. Many large ELK users have scripts or ILM policies to drop indices older than X days or move them to slower disks.</p><h3><strong>Pre-processing and Filtering</strong></h3><p>A huge factor in log pipeline scalability is filtering out noise&nbsp;<strong>before indexing</strong>. For example, you might drop debug logs in production or only sample logs from very chatty components. Tools like Fluent Bit/Fluentd allow rules to drop or route logs based on content or source. Some companies implement dynamic log sampling &#8211; if a particular log message is very repetitive (e.g. a certain warning spewing thousands of times), they sample it down. Edge computing or on-agent processing can convert logs to metrics (count occurrences of a log instead of sending every line) for certain cases. One approach is converting the bulk of logs into patterns or metrics to reduce volume, while still forwarding a subset of raw logs for deeper analysis. By reducing what goes into the expensive storage, you scale further.</p><p>In summary, a scalable log pipeline likely uses&nbsp;agents like Fluent Bit&nbsp;on each host, streams logs into a&nbsp;durable buffer (Kafka), and then has a&nbsp;consumer that indexes or stores logs. For indexing, one might run an&nbsp;<strong>Elasticsearch cluster with appropriate sharding and retention</strong>, but as scale grows, consider switching to or supplementing with&nbsp;<strong>Grafana Loki for cost efficiency</strong>&nbsp;or&nbsp;<strong>ClickHouse for high-performance queries on structured logs</strong>. Logs can also be&nbsp;<strong>tiered</strong>: e.g. recent logs in Loki (cheap and scalable, good for known queries), with a portion in Elastic for full-text search, and older logs archived. The pipeline must be tuned to avoid losing logs under peak load: use disk buffering in Fluentd/Fluent Bit (so if the network or Kafka is slow, logs spool to disk temporarily), and monitor pipeline health (e.g. monitor Kafka lag or Fluentd buffer fill level). Horizontal scaling is achieved by adding more consumers or more Kafka partitions, and by splitting logs by categories (for example, one pipeline for application logs, another for infrastructure logs, to isolate them).</p><p>The major&nbsp;<strong>trade-off in logs</strong>&nbsp;is query power vs cost: Full indexing (ELK) gives greatest query flexibility but can become prohibitively costly at scale; limited indexing (Loki) or no indexing (just store and grep) is far cheaper but needs more effort to find things. Many large orgs find a balance &#8211; e.g., index only error and warning logs fully, but store info/debug logs in cheaper form. Or index only certain fields. These nuances help scale practically.</p><div><hr></div><p>In&nbsp;<strong>Part 3</strong>, we&#8217;ll discuss how you can assemble these scaled-up telemetry pipelines end to end&#8212;covering ingestion, stream processing, buffering/backpressure strategies, high availability, cost management, and key lessons learned in real-world deployments. <em>Happy Pipelining!</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;e6021129-d8dc-49d3-b631-0a3898135271&quot;,&quot;caption&quot;:&quot;In Part 2, we saw that scaling observability pipelines involves specialized strategies for each telemetry signal type. For metrics, scalable architectures use distributed storage, aggregation, downsampling, etc. to handle high volumes. Traces pipelines employ sampling strategies like head-based, tail-based, and remote sampling to manage trace volume. Wh&#8230;&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 3&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-05-12T05:34:07.000Z&quot;,&quot;cover_image&quot;:&quot;https://www.observability.how/content/images/2025/05/scaling-observability-3.jpg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-3&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843143,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 1]]></title><description><![CDATA[Building observability in large-scale, cloud-native systems requires collecting telemetry data (metrics, traces, and logs) at extremely high volumes.]]></description><link>https://www.observability.how/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-1</link><guid isPermaLink="false">https://www.observability.how/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-1</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Mon, 28 Apr 2025 05:50:41 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/6fbcbdee-0101-4d9c-92af-30d7869dbbb2_1472x832.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6Iv2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6Iv2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6Iv2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6Iv2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6Iv2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6Iv2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 1&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 1" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 1" srcset="https://substackcdn.com/image/fetch/$s_!6Iv2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6Iv2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6Iv2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6Iv2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc9a524ab-04c0-4111-9781-108db0dc3529_1472x832.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Building observability in large-scale, cloud-native systems requires collecting <strong>telemetry data</strong>&nbsp;(metrics, traces, and logs) at extremely high volumes. Modern platforms like Kubernetes can generate&nbsp;<strong>millions of metrics, traces, and log events per second</strong>, and enterprises often must handle this flood of telemetry across hybrid environments (on-premises and cloud). Designing a telemetry pipeline that scales to these volumes is challenging but essential for reliable monitoring and troubleshooting. This 4-part blog series dives deep into how senior engineers and architects can design a high-volume observability pipeline. We&#8217;ll explore each telemetry signal type, discuss architectural patterns for scaling them, and examine techniques used in production at large organizations &#8211; from&nbsp;<strong>trace sampling strategies</strong>&nbsp;to&nbsp;<strong>metrics aggregation and remote storage</strong>&nbsp;to&nbsp;<strong>log sharding and retention</strong>. We&#8217;ll also cover the&nbsp;<strong>ingestion layer</strong>&nbsp;(collectors, agents, Kafka), <strong>real-time stream processing</strong>&nbsp;for enrichment,&nbsp;<strong>buffering and backpressure</strong>, horizontal scaling approaches, cost-control measures, and lessons learned (including trade-offs and anti-patterns to avoid).</p><p>The goal is to provide a practical guide to scaling observability pipelines to&nbsp;millions of events per second &#8211; without breaking the bank or losing critical visibility.</p><div><hr></div><h2><strong>Telemetry Signals at Scale</strong></h2><p>High-volume observability pipelines must ingest and process three primary telemetry signals, often called the &#8220;three pillars&#8221; of observability:&nbsp;<strong>metrics, traces, and logs</strong>.</p><p></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;175b2f19-950b-47a3-bd1a-5ca5125f46d5&quot;,&quot;caption&quot;:&quot;Imagine you&#8217;re a detective for software systems. Late one night, an alert goes off: something is wrong with your application. But what is wrong? In a complex microservices environment, finding the culprit can feel like searching for a needle in a haystack. This is where&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;What is Observability? &#8211; Metrics, Logs, and Traces Demystified&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-13T06:03:38.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2eea1394-f04e-4824-86f2-a5ec578abfba_2000x1333.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/what-is-observability-metrics-logs-and-traces-demystified&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843152,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p></p><p>Each signal has distinct characteristics and scaling challenges:</p><ul><li><p><strong>Metrics</strong>&nbsp;&#8211; Numeric time-series data (e.g. CPU usage, request count) sampled at intervals. Metrics are high-frequency and used for monitoring trends and alerting. At scale, metrics may involve millions of distinct time-series (unique combinations of metric name and labels) and extremely high ingestion rates. The challenge is handling high write throughput and queries across massive time-series datasets while controlling cardinality.</p></li><li><p><strong>Traces</strong>&nbsp;&#8211; Distributed traces follow a single request as it propagates through microservices, consisting of many timestamped spans. Traces provide detailed, per-request insight but storing every trace is typically infeasible at scale. High-volume systems may produce <strong>millions of spans per second</strong>, requiring careful&nbsp;<strong>sampling</strong>&nbsp;and efficient storage (e.g. indexing only certain fields). The challenge is capturing enough traces to be useful (especially error traces) while dropping or summarizing the rest to limit overhead.</p></li><li><p><strong>Logs</strong>&nbsp;&#8211; Immutable, text-based event records. Logs contain rich detail (error messages, stack traces, etc.) but are produced in huge volumes, especially in verbose or debug modes. Large organizations might ingest&nbsp;<strong>terabytes of log data per day</strong>, which strains storage and indexing systems. The key challenge is&nbsp;<strong>ingesting and indexing logs efficiently</strong>&nbsp;(or using alternative approaches to full indexing) and managing retention/cost, since logs can accumulate quickly.</p></li></ul><p>In cloud-native, containerized environments, telemetry data is highly&nbsp;<strong>dynamic and distributed</strong>. Kubernetes&nbsp;spin up and down containers, causing metric series churn and high log volumes from short-lived pods. A pipeline must handle <strong>ephemeral sources</strong>&nbsp;and multi-tenant data (e.g. multiple teams or services) without losing data or context. In hybrid environments, the pipeline should aggregate data from on-premises datacenters and multiple clouds, providing a unified view.</p><p><strong>Key scaling challenges</strong>&nbsp;across these signals include throughput (events per second), data volume (storage and retention), data correlation (linking traces with logs/metrics), and system bottlenecks (ensuring one hot service&#8217;s telemetry doesn&#8217;t overwhelm the pipeline). We&#8217;ll address these by examining specialized strategies for each signal type and general architectural patterns for high-volume pipelines.</p><div><hr></div><h2><strong>High-Level Pipeline Architecture and Design Principles</strong></h2><p>Let&#8217;s outline the overall architecture of a scalable observability pipeline. At a high level, such a pipeline consists of several stages:</p><p><strong>1 &#8211; Data Collection (Ingestion)</strong>: Telemetry is generated by applications, infrastructure, and services. It&#8217;s collected by agents or libraries (e.g. instrumentation SDKs for traces, exporters for metrics, log forwarders) and sent into the pipeline. In a robust design, a&nbsp;<strong><a href="https://www.observability.how/using-the-opentelemetry-collector-a-practical-guide/">unified collector</a></strong>&nbsp;can receive all three signals, or specialized collectors handle each. The goal is to reliably get data off of sources (pods, VMs, devices) and into a processing system without overwhelming the sources.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;a43f62e8-e127-4d49-b89a-137a979a6687&quot;,&quot;caption&quot;:&quot;OpenTelemetry&#8217;s Collector is a vendor-neutral service that sits between your applications and observability backends. It can receive telemetry data (traces, metrics, logs), process or transform it, and export it to one or multiple destinations. In a production environment, the Collector becomes essential for building a&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Using the OpenTelemetry Collector: A Practical Guide&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-17T07:56:28.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5151a4d-0495-4388-9617-364ce63da4e5_1996x1192.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/using-the-opentelemetry-collector-a-practical-guide&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843148,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p><strong>2 &#8211; Data Processing and Buffering</strong>: Once inside the pipeline, telemetry may be filtered, aggregated, sampled, or enriched. This stage often involves&nbsp;<strong>stream processors or intermediate buffers</strong>. Examples: an OpenTelemetry Collector applying sampling or adding metadata to traces; a streaming job (Apache Flink/Spark) performing real-time analytics on logs; a Kafka cluster buffering bursts of log events. Processing nodes should be stateless or partitioned for horizontal scaling, and buffering is used to absorb spikes and decouple producers from consumers.</p><p><strong>3 &#8211; Storage and Indexing</strong>: After processing, telemetry is routed to storage backends optimized for each data type: a time-series database for metrics, a trace store for distributed traces, and a log indexing system or data lake for logs. These backends must be&nbsp;<strong>distributed and scalable</strong>&nbsp;to handle continuous high write rates and support queries. Examples include <a href="https://grafana.com/oss/mimir/?ref=observability.how">Mimir</a> for metrics, Jaeger-supported <a href="https://www.jaegertracing.io/docs/2.5/storage/?ref=observability.how">backends</a> or <a href="https://grafana.com/oss/tempo/?ref=observability.how">Tempo</a> for traces, and <a href="https://www.elastic.co/elasticsearch?ref=observability.how">Elasticsearch</a>/<a href="https://opensearch.org/?ref=observability.how">OpenSearch</a>, or <a href="https://clickhouse.com/?ref=observability.how">ClickHouse</a>/<a href="https://grafana.com/oss/loki/?ref=observability.how">Loki</a> for logs. Data may be stored with replication for high availability and possibly tiered (hot vs cold).</p><p><strong>4 &#8211; Query and Visualization</strong>: The end-users (developers, SREs, analysts) query this telemetry via tools like <a href="https://grafana.com/grafana/?ref=observability.how">Grafana</a> dashboards (for metrics), trace viewers, or log search interfaces. While this is outside the ingestion pipeline itself, the pipeline&#8217;s design heavily influences query performance. (We&#8217;ll focus on the pipeline internals rather than UI, but it&#8217;s important to ensure the pipeline delivers data in a query-friendly form).</p><p>Crucial&nbsp;<strong>design principles</strong>&nbsp;for scaling at each stage include&nbsp;<strong>horizontal scaling, stateless processing, and backpressure management</strong>. Horizontal scaling means any component (collectors, queue brokers, storage nodes) can be scaled out (add more instances) to increase capacity, with work partitioned among them. This typically requires stateless workers or consistent hashing of data (so, for example, all metrics for a given series go to the same shard). Stateless or loosely stateful processing makes rolling upgrades and scaling easier. Backpressure management means if any consumer lags (e.g. the database is slow to ingest), the pipeline can buffer data or throttle input rather than crash or lose data unexpectedly.</p><p>The pipeline architecture should accommodate different collection methods while maintaining a&nbsp;<strong>decoupled, scalable core</strong>&nbsp;with common infrastructure like message queues or processing frameworks to handle the load.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GYM9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GYM9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png 424w, https://substackcdn.com/image/fetch/$s_!GYM9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png 848w, https://substackcdn.com/image/fetch/$s_!GYM9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png 1272w, https://substackcdn.com/image/fetch/$s_!GYM9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GYM9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png" width="2000" height="1057" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1057,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 1&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 1" title="Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 1" srcset="https://substackcdn.com/image/fetch/$s_!GYM9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png 424w, https://substackcdn.com/image/fetch/$s_!GYM9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png 848w, https://substackcdn.com/image/fetch/$s_!GYM9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png 1272w, https://substackcdn.com/image/fetch/$s_!GYM9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7060fcc5-8551-44f1-b8fe-9a55a59f202a_2000x1057.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">High-level illustration of a Telemetry Pipeline</figcaption></figure></div><div><hr></div><p>With the high-level picture in mind, let&#8217;s break down how to scale each telemetry signal type in <strong>Part 2</strong>. <em>Happy Scaling!</em></p><p></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;6439bf20-54a0-496d-95fa-f7df8ec4dc0c&quot;,&quot;caption&quot;:&quot;In the Part 1, we saw that a scalable pipeline architecture consists of data collection, processing, storage, and querying stages, with key design principles including horizontal scaling, stateless processing, and backpressure management. Now, let's examine specialized scaling strategies for each telemetry signal type.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Scaling Observability: Designing a High-Volume Telemetry Pipeline - Part 2&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-05-04T21:20:03.000Z&quot;,&quot;cover_image&quot;:&quot;https://www.observability.how/content/images/2025/05/scaling-observability-2.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/scaling-observability-designing-a-high-volume-telemetry-pipeline-part-2&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843145,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Building Your First Observability Stack with Open‑Source Tools]]></title><description><![CDATA[Goal: Spin up Prometheus+Alertmanager, Loki+Promtail, Jaeger, and Grafana with a single docker&#8209;compose.yml, then watch a tiny Java HTTP service emit metrics, logs, and traces&#8212;all in less than an hour.]]></description><link>https://www.observability.how/p/building-your-first-observability-stack-with-open-source-tools</link><guid isPermaLink="false">https://www.observability.how/p/building-your-first-observability-stack-with-open-source-tools</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Sun, 27 Apr 2025 19:51:17 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/5f6f0b4a-10d9-4384-8365-993bd3f038a6_1475x858.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><strong>Goal: </strong>Spin up Prometheus+Alertmanager, Loki+Promtail, Jaeger, and Grafana with a single docker&#8209;compose.yml, then watch a tiny Java HTTP service emit metrics, logs, and traces&#8212;all in less than an hour.</p></blockquote><div><hr></div><h2>Why this post?</h2><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DJVb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DJVb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png 424w, https://substackcdn.com/image/fetch/$s_!DJVb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png 848w, https://substackcdn.com/image/fetch/$s_!DJVb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png 1272w, https://substackcdn.com/image/fetch/$s_!DJVb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DJVb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" title="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" srcset="https://substackcdn.com/image/fetch/$s_!DJVb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png 424w, https://substackcdn.com/image/fetch/$s_!DJVb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png 848w, https://substackcdn.com/image/fetch/$s_!DJVb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png 1272w, https://substackcdn.com/image/fetch/$s_!DJVb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7b208df-e350-46d5-b3f6-8e2dab5cecd6_1475x858.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>You keep hearing that &#8220;<strong>observability &#8800; monitoring</strong>&#8221; and that you need <strong>metrics, logs, and traces</strong>&nbsp;working together. But SaaS bills and steep learning curves can be buzz&#8209;kills. This guide is a&nbsp;<em>hands&#8209;on</em>&nbsp;shortcut: everything runs locally in Docker, so you can poke around, break things, and learn risk&#8209;free.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;bbf8ab94-2840-4ef7-9189-87f8f08e6b22&quot;,&quot;caption&quot;:&quot;Imagine you&#8217;re a detective for software systems. Late one night, an alert goes off: something is wrong with your application. But what is wrong? In a complex microservices environment, finding the culprit can feel like searching for a needle in a haystack. This is where&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;What is Observability? &#8211; Metrics, Logs, and Traces Demystified&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-13T06:03:38.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2eea1394-f04e-4824-86f2-a5ec578abfba_2000x1333.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/what-is-observability-metrics-logs-and-traces-demystified&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843152,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>Prerequisites</h2><ul><li><p>Docker&#8239;&amp;&#8239;docker&#8209;compose installed</p></li><li><p>Basic&nbsp;<code>docker compose up</code>&nbsp;/&nbsp;<code>docker compose down</code>&nbsp;familiarity</p></li><li><p>JDK&#8239;21+ and Maven</p></li></ul><div><hr></div><h2>1 &#8211; Scaffold a Tiny Java Service</h2><p>Create a folder&nbsp;<strong><code>tiny-app/</code></strong></p><pre><code>mkdir tiny-app &amp;&amp; cd tiny-app
</code></pre><h3>1.1 <code>pom.xml</code></h3><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569385\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-pom-xml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-maven-pom  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;pom.xml content, created by jigarkb on 07:53AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;pom.xml\&quot;>\n        <tr>\n          <td id=\&quot;file-pom-xml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>&amp;lt;?<span class=\&quot;pl-ent\&quot;>xml</span><span class=\&quot;pl-e\&quot;> version</span>=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>1.0<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span><span class=\&quot;pl-e\&quot;> encoding</span>=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>UTF-8<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span>?&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>&amp;lt;<span class=\&quot;pl-ent\&quot;>project</span> <span class=\&quot;pl-e\&quot;>xmlns</span>=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>http://maven.apache.org/POM/4.0.0<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>         <span class=\&quot;pl-e\&quot;>xmlns</span><span class=\&quot;pl-e\&quot;>:</span><span class=\&quot;pl-e\&quot;>xsi</span>=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>http://www.w3.org/2001/XMLSchema-instance<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>         <span class=\&quot;pl-e\&quot;>xsi</span><span class=\&quot;pl-e\&quot;>:</span><span class=\&quot;pl-e\&quot;>schemaLocation</span>=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;<span class=\&quot;pl-ent\&quot;>modelVersion</span>&amp;gt;4.0.0&amp;lt;/<span class=\&quot;pl-ent\&quot;>modelVersion</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;how.observability&amp;lt;/<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;tiny-app&amp;lt;/<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;1.0-SNAPSHOT&amp;lt;/<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;<span class=\&quot;pl-ent\&quot;>properties</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>maven</span>.compiler.source&amp;gt;21&amp;lt;/<span class=\&quot;pl-ent\&quot;>maven</span>.compiler.source&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>maven</span>.compiler.target&amp;gt;21&amp;lt;/<span class=\&quot;pl-ent\&quot;>maven</span>.compiler.target&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>project</span>.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/<span class=\&quot;pl-ent\&quot;>project</span>.build.sourceEncoding&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>micrometer</span>.version&amp;gt;1.14.6&amp;lt;/<span class=\&quot;pl-ent\&quot;>micrometer</span>.version&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>javalin</span>.version&amp;gt;6.6.0&amp;lt;/<span class=\&quot;pl-ent\&quot;>javalin</span>.version&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>slf4j-simple</span>.version&amp;gt;2.0.17&amp;lt;/<span class=\&quot;pl-ent\&quot;>slf4j-simple</span>.version&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>maven-shade-plugin</span>.version&amp;gt;3.6.0&amp;lt;/<span class=\&quot;pl-ent\&quot;>maven-shade-plugin</span>.version&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;/<span class=\&quot;pl-ent\&quot;>properties</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;<span class=\&quot;pl-ent\&quot;>dependencies</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>&amp;lt;!--</span> Minimal embedded HTTP server <span class=\&quot;pl-c\&quot;>--&amp;gt;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>dependency</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;io.javalin&amp;lt;/<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;javalin&amp;lt;/<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;<span class=\&quot;pl-smi\&quot;>${javalin.version}</span>&amp;lt;/<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;/<span class=\&quot;pl-ent\&quot;>dependency</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>&amp;lt;!--</span> Micrometer core + Prometheus registry <span class=\&quot;pl-c\&quot;>--&amp;gt;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>dependency</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;io.micrometer&amp;lt;/<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;micrometer-core&amp;lt;/<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;<span class=\&quot;pl-smi\&quot;>${micrometer.version}</span>&amp;lt;/<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;/<span class=\&quot;pl-ent\&quot;>dependency</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L34\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;34\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC34\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>dependency</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L35\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;35\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC35\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;io.micrometer&amp;lt;/<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L36\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;36\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC36\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;micrometer-registry-prometheus&amp;lt;/<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L37\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;37\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC37\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;<span class=\&quot;pl-smi\&quot;>${micrometer.version}</span>&amp;lt;/<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L38\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;38\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC38\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;/<span class=\&quot;pl-ent\&quot;>dependency</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L39\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;39\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC39\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L40\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;40\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC40\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>&amp;lt;!--</span> SLF4J for logs <span class=\&quot;pl-c\&quot;>--&amp;gt;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L41\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;41\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC41\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>dependency</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L42\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;42\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC42\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;org.slf4j&amp;lt;/<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L43\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;43\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC43\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;slf4j-simple&amp;lt;/<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L44\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;44\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC44\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;<span class=\&quot;pl-smi\&quot;>${slf4j-simple.version}</span>&amp;lt;/<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L45\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;45\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC45\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;/<span class=\&quot;pl-ent\&quot;>dependency</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L46\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;46\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC46\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;/<span class=\&quot;pl-ent\&quot;>dependencies</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L47\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;47\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC47\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L48\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;48\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC48\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;<span class=\&quot;pl-ent\&quot;>build</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L49\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;49\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC49\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;<span class=\&quot;pl-ent\&quot;>plugins</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L50\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;50\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC50\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;<span class=\&quot;pl-ent\&quot;>plugin</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L51\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;51\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC51\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                &amp;lt;<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;org.apache.maven.plugins&amp;lt;/<span class=\&quot;pl-ent\&quot;>groupId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L52\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;52\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC52\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                &amp;lt;<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;maven-shade-plugin&amp;lt;/<span class=\&quot;pl-ent\&quot;>artifactId</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L53\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;53\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC53\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                &amp;lt;<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;<span class=\&quot;pl-smi\&quot;>${maven-shade-plugin.version}</span>&amp;lt;/<span class=\&quot;pl-ent\&quot;>version</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L54\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;54\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC54\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                &amp;lt;<span class=\&quot;pl-ent\&quot;>executions</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L55\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;55\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC55\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    &amp;lt;<span class=\&quot;pl-ent\&quot;>execution</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L56\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;56\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC56\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                        &amp;lt;<span class=\&quot;pl-ent\&quot;>phase</span>&amp;gt;package&amp;lt;/<span class=\&quot;pl-ent\&quot;>phase</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L57\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;57\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC57\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                        &amp;lt;<span class=\&quot;pl-ent\&quot;>goals</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L58\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;58\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC58\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                            &amp;lt;<span class=\&quot;pl-ent\&quot;>goal</span>&amp;gt;shade&amp;lt;/<span class=\&quot;pl-ent\&quot;>goal</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L59\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;59\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC59\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                        &amp;lt;/<span class=\&quot;pl-ent\&quot;>goals</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L60\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;60\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC60\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                        &amp;lt;<span class=\&quot;pl-ent\&quot;>configuration</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L61\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;61\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC61\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                            &amp;lt;<span class=\&quot;pl-ent\&quot;>transformers</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L62\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;62\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC62\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                                &amp;lt;<span class=\&quot;pl-ent\&quot;>transformer</span> <span class=\&quot;pl-e\&quot;>implementation</span>=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>org.apache.maven.plugins.shade.resource.ManifestResourceTransformer<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L63\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;63\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC63\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                                    &amp;lt;<span class=\&quot;pl-ent\&quot;>mainClass</span>&amp;gt;how.observability.TinyApp&amp;lt;/<span class=\&quot;pl-ent\&quot;>mainClass</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L64\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;64\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC64\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                                &amp;lt;/<span class=\&quot;pl-ent\&quot;>transformer</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L65\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;65\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC65\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                            &amp;lt;/<span class=\&quot;pl-ent\&quot;>transformers</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L66\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;66\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC66\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                        &amp;lt;/<span class=\&quot;pl-ent\&quot;>configuration</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L67\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;67\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC67\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    &amp;lt;/<span class=\&quot;pl-ent\&quot;>execution</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L68\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;68\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC68\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                &amp;lt;/<span class=\&quot;pl-ent\&quot;>executions</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L69\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;69\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC69\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            &amp;lt;/<span class=\&quot;pl-ent\&quot;>plugin</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L70\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;70\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC70\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        &amp;lt;/<span class=\&quot;pl-ent\&quot;>plugins</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L71\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;71\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC71\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    &amp;lt;/<span class=\&quot;pl-ent\&quot;>build</span>&amp;gt;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-pom-xml-L72\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;72\&quot;></td>\n          <td id=\&quot;file-pom-xml-LC72\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>&amp;lt;/<span class=\&quot;pl-ent\&quot;>project</span>&amp;gt;</td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/d45ff58f67bc59d9fde554e4a94f7d6e/raw/91015786507ae8db0c195c1d26bce20fb0787b87/pom.xml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/d45ff58f67bc59d9fde554e4a94f7d6e#file-pom-xml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          pom.xml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569385" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-pom-xml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-maven-pom  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="pom.xml">
        <tbody><tr>
          <td id="file-pom-xml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-pom-xml-LC1" class="blob-code blob-code-inner js-file-line">&lt;?<span class="pl-ent">xml</span><span class="pl-e"> version</span>=<span class="pl-s"><span class="pl-pds">"</span>1.0<span class="pl-pds">"</span></span><span class="pl-e"> encoding</span>=<span class="pl-s"><span class="pl-pds">"</span>UTF-8<span class="pl-pds">"</span></span>?&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-pom-xml-LC2" class="blob-code blob-code-inner js-file-line">&lt;<span class="pl-ent">project</span> <span class="pl-e">xmlns</span>=<span class="pl-s"><span class="pl-pds">"</span>http://maven.apache.org/POM/4.0.0<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-pom-xml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-pom-xml-LC3" class="blob-code blob-code-inner js-file-line">         <span class="pl-e">xmlns</span><span class="pl-e">:</span><span class="pl-e">xsi</span>=<span class="pl-s"><span class="pl-pds">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-pom-xml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-pom-xml-LC4" class="blob-code blob-code-inner js-file-line">         <span class="pl-e">xsi</span><span class="pl-e">:</span><span class="pl-e">schemaLocation</span>=<span class="pl-s"><span class="pl-pds">"</span>http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd<span class="pl-pds">"</span></span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-pom-xml-LC5" class="blob-code blob-code-inner js-file-line">    &lt;<span class="pl-ent">modelVersion</span>&gt;4.0.0&lt;/<span class="pl-ent">modelVersion</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-pom-xml-LC6" class="blob-code blob-code-inner js-file-line">    &lt;<span class="pl-ent">groupId</span>&gt;how.observability&lt;/<span class="pl-ent">groupId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-pom-xml-LC7" class="blob-code blob-code-inner js-file-line">    &lt;<span class="pl-ent">artifactId</span>&gt;tiny-app&lt;/<span class="pl-ent">artifactId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-pom-xml-LC8" class="blob-code blob-code-inner js-file-line">    &lt;<span class="pl-ent">version</span>&gt;1.0-SNAPSHOT&lt;/<span class="pl-ent">version</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-pom-xml-LC9" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-pom-xml-LC10" class="blob-code blob-code-inner js-file-line">    &lt;<span class="pl-ent">properties</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-pom-xml-LC11" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">maven</span>.compiler.source&gt;21&lt;/<span class="pl-ent">maven</span>.compiler.source&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-pom-xml-LC12" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">maven</span>.compiler.target&gt;21&lt;/<span class="pl-ent">maven</span>.compiler.target&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-pom-xml-LC13" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">project</span>.build.sourceEncoding&gt;UTF-8&lt;/<span class="pl-ent">project</span>.build.sourceEncoding&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-pom-xml-LC14" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">micrometer</span>.version&gt;1.14.6&lt;/<span class="pl-ent">micrometer</span>.version&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-pom-xml-LC15" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">javalin</span>.version&gt;6.6.0&lt;/<span class="pl-ent">javalin</span>.version&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-pom-xml-LC16" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">slf4j-simple</span>.version&gt;2.0.17&lt;/<span class="pl-ent">slf4j-simple</span>.version&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-pom-xml-LC17" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">maven-shade-plugin</span>.version&gt;3.6.0&lt;/<span class="pl-ent">maven-shade-plugin</span>.version&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-pom-xml-LC18" class="blob-code blob-code-inner js-file-line">    &lt;/<span class="pl-ent">properties</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-pom-xml-LC19" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-pom-xml-LC20" class="blob-code blob-code-inner js-file-line">    &lt;<span class="pl-ent">dependencies</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-pom-xml-LC21" class="blob-code blob-code-inner js-file-line">        <span class="pl-c"><span class="pl-c">&lt;!--</span> Minimal embedded HTTP server <span class="pl-c">--&gt;</span></span></td>
        </tr>
        <tr>
          <td id="file-pom-xml-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-pom-xml-LC22" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">dependency</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-pom-xml-LC23" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">groupId</span>&gt;io.javalin&lt;/<span class="pl-ent">groupId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-pom-xml-LC24" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">artifactId</span>&gt;javalin&lt;/<span class="pl-ent">artifactId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-pom-xml-LC25" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">version</span>&gt;<span class="pl-smi">${javalin.version}</span>&lt;/<span class="pl-ent">version</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-pom-xml-LC26" class="blob-code blob-code-inner js-file-line">        &lt;/<span class="pl-ent">dependency</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-pom-xml-LC27" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-pom-xml-LC28" class="blob-code blob-code-inner js-file-line">        <span class="pl-c"><span class="pl-c">&lt;!--</span> Micrometer core + Prometheus registry <span class="pl-c">--&gt;</span></span></td>
        </tr>
        <tr>
          <td id="file-pom-xml-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-pom-xml-LC29" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">dependency</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-pom-xml-LC30" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">groupId</span>&gt;io.micrometer&lt;/<span class="pl-ent">groupId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-pom-xml-LC31" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">artifactId</span>&gt;micrometer-core&lt;/<span class="pl-ent">artifactId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-pom-xml-LC32" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">version</span>&gt;<span class="pl-smi">${micrometer.version}</span>&lt;/<span class="pl-ent">version</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-pom-xml-LC33" class="blob-code blob-code-inner js-file-line">        &lt;/<span class="pl-ent">dependency</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-pom-xml-LC34" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">dependency</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-pom-xml-LC35" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">groupId</span>&gt;io.micrometer&lt;/<span class="pl-ent">groupId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
          <td id="file-pom-xml-LC36" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">artifactId</span>&gt;micrometer-registry-prometheus&lt;/<span class="pl-ent">artifactId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L37" class="blob-num js-line-number js-blob-rnum" data-line-number="37"></td>
          <td id="file-pom-xml-LC37" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">version</span>&gt;<span class="pl-smi">${micrometer.version}</span>&lt;/<span class="pl-ent">version</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L38" class="blob-num js-line-number js-blob-rnum" data-line-number="38"></td>
          <td id="file-pom-xml-LC38" class="blob-code blob-code-inner js-file-line">        &lt;/<span class="pl-ent">dependency</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L39" class="blob-num js-line-number js-blob-rnum" data-line-number="39"></td>
          <td id="file-pom-xml-LC39" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L40" class="blob-num js-line-number js-blob-rnum" data-line-number="40"></td>
          <td id="file-pom-xml-LC40" class="blob-code blob-code-inner js-file-line">        <span class="pl-c"><span class="pl-c">&lt;!--</span> SLF4J for logs <span class="pl-c">--&gt;</span></span></td>
        </tr>
        <tr>
          <td id="file-pom-xml-L41" class="blob-num js-line-number js-blob-rnum" data-line-number="41"></td>
          <td id="file-pom-xml-LC41" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">dependency</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L42" class="blob-num js-line-number js-blob-rnum" data-line-number="42"></td>
          <td id="file-pom-xml-LC42" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">groupId</span>&gt;org.slf4j&lt;/<span class="pl-ent">groupId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L43" class="blob-num js-line-number js-blob-rnum" data-line-number="43"></td>
          <td id="file-pom-xml-LC43" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">artifactId</span>&gt;slf4j-simple&lt;/<span class="pl-ent">artifactId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L44" class="blob-num js-line-number js-blob-rnum" data-line-number="44"></td>
          <td id="file-pom-xml-LC44" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">version</span>&gt;<span class="pl-smi">${slf4j-simple.version}</span>&lt;/<span class="pl-ent">version</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L45" class="blob-num js-line-number js-blob-rnum" data-line-number="45"></td>
          <td id="file-pom-xml-LC45" class="blob-code blob-code-inner js-file-line">        &lt;/<span class="pl-ent">dependency</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L46" class="blob-num js-line-number js-blob-rnum" data-line-number="46"></td>
          <td id="file-pom-xml-LC46" class="blob-code blob-code-inner js-file-line">    &lt;/<span class="pl-ent">dependencies</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L47" class="blob-num js-line-number js-blob-rnum" data-line-number="47"></td>
          <td id="file-pom-xml-LC47" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L48" class="blob-num js-line-number js-blob-rnum" data-line-number="48"></td>
          <td id="file-pom-xml-LC48" class="blob-code blob-code-inner js-file-line">    &lt;<span class="pl-ent">build</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L49" class="blob-num js-line-number js-blob-rnum" data-line-number="49"></td>
          <td id="file-pom-xml-LC49" class="blob-code blob-code-inner js-file-line">        &lt;<span class="pl-ent">plugins</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L50" class="blob-num js-line-number js-blob-rnum" data-line-number="50"></td>
          <td id="file-pom-xml-LC50" class="blob-code blob-code-inner js-file-line">            &lt;<span class="pl-ent">plugin</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L51" class="blob-num js-line-number js-blob-rnum" data-line-number="51"></td>
          <td id="file-pom-xml-LC51" class="blob-code blob-code-inner js-file-line">                &lt;<span class="pl-ent">groupId</span>&gt;org.apache.maven.plugins&lt;/<span class="pl-ent">groupId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L52" class="blob-num js-line-number js-blob-rnum" data-line-number="52"></td>
          <td id="file-pom-xml-LC52" class="blob-code blob-code-inner js-file-line">                &lt;<span class="pl-ent">artifactId</span>&gt;maven-shade-plugin&lt;/<span class="pl-ent">artifactId</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L53" class="blob-num js-line-number js-blob-rnum" data-line-number="53"></td>
          <td id="file-pom-xml-LC53" class="blob-code blob-code-inner js-file-line">                &lt;<span class="pl-ent">version</span>&gt;<span class="pl-smi">${maven-shade-plugin.version}</span>&lt;/<span class="pl-ent">version</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L54" class="blob-num js-line-number js-blob-rnum" data-line-number="54"></td>
          <td id="file-pom-xml-LC54" class="blob-code blob-code-inner js-file-line">                &lt;<span class="pl-ent">executions</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L55" class="blob-num js-line-number js-blob-rnum" data-line-number="55"></td>
          <td id="file-pom-xml-LC55" class="blob-code blob-code-inner js-file-line">                    &lt;<span class="pl-ent">execution</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L56" class="blob-num js-line-number js-blob-rnum" data-line-number="56"></td>
          <td id="file-pom-xml-LC56" class="blob-code blob-code-inner js-file-line">                        &lt;<span class="pl-ent">phase</span>&gt;package&lt;/<span class="pl-ent">phase</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L57" class="blob-num js-line-number js-blob-rnum" data-line-number="57"></td>
          <td id="file-pom-xml-LC57" class="blob-code blob-code-inner js-file-line">                        &lt;<span class="pl-ent">goals</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L58" class="blob-num js-line-number js-blob-rnum" data-line-number="58"></td>
          <td id="file-pom-xml-LC58" class="blob-code blob-code-inner js-file-line">                            &lt;<span class="pl-ent">goal</span>&gt;shade&lt;/<span class="pl-ent">goal</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L59" class="blob-num js-line-number js-blob-rnum" data-line-number="59"></td>
          <td id="file-pom-xml-LC59" class="blob-code blob-code-inner js-file-line">                        &lt;/<span class="pl-ent">goals</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L60" class="blob-num js-line-number js-blob-rnum" data-line-number="60"></td>
          <td id="file-pom-xml-LC60" class="blob-code blob-code-inner js-file-line">                        &lt;<span class="pl-ent">configuration</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L61" class="blob-num js-line-number js-blob-rnum" data-line-number="61"></td>
          <td id="file-pom-xml-LC61" class="blob-code blob-code-inner js-file-line">                            &lt;<span class="pl-ent">transformers</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L62" class="blob-num js-line-number js-blob-rnum" data-line-number="62"></td>
          <td id="file-pom-xml-LC62" class="blob-code blob-code-inner js-file-line">                                &lt;<span class="pl-ent">transformer</span> <span class="pl-e">implementation</span>=<span class="pl-s"><span class="pl-pds">"</span>org.apache.maven.plugins.shade.resource.ManifestResourceTransformer<span class="pl-pds">"</span></span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L63" class="blob-num js-line-number js-blob-rnum" data-line-number="63"></td>
          <td id="file-pom-xml-LC63" class="blob-code blob-code-inner js-file-line">                                    &lt;<span class="pl-ent">mainClass</span>&gt;how.observability.TinyApp&lt;/<span class="pl-ent">mainClass</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L64" class="blob-num js-line-number js-blob-rnum" data-line-number="64"></td>
          <td id="file-pom-xml-LC64" class="blob-code blob-code-inner js-file-line">                                &lt;/<span class="pl-ent">transformer</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L65" class="blob-num js-line-number js-blob-rnum" data-line-number="65"></td>
          <td id="file-pom-xml-LC65" class="blob-code blob-code-inner js-file-line">                            &lt;/<span class="pl-ent">transformers</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L66" class="blob-num js-line-number js-blob-rnum" data-line-number="66"></td>
          <td id="file-pom-xml-LC66" class="blob-code blob-code-inner js-file-line">                        &lt;/<span class="pl-ent">configuration</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L67" class="blob-num js-line-number js-blob-rnum" data-line-number="67"></td>
          <td id="file-pom-xml-LC67" class="blob-code blob-code-inner js-file-line">                    &lt;/<span class="pl-ent">execution</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L68" class="blob-num js-line-number js-blob-rnum" data-line-number="68"></td>
          <td id="file-pom-xml-LC68" class="blob-code blob-code-inner js-file-line">                &lt;/<span class="pl-ent">executions</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L69" class="blob-num js-line-number js-blob-rnum" data-line-number="69"></td>
          <td id="file-pom-xml-LC69" class="blob-code blob-code-inner js-file-line">            &lt;/<span class="pl-ent">plugin</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L70" class="blob-num js-line-number js-blob-rnum" data-line-number="70"></td>
          <td id="file-pom-xml-LC70" class="blob-code blob-code-inner js-file-line">        &lt;/<span class="pl-ent">plugins</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L71" class="blob-num js-line-number js-blob-rnum" data-line-number="71"></td>
          <td id="file-pom-xml-LC71" class="blob-code blob-code-inner js-file-line">    &lt;/<span class="pl-ent">build</span>&gt;</td>
        </tr>
        <tr>
          <td id="file-pom-xml-L72" class="blob-num js-line-number js-blob-rnum" data-line-number="72"></td>
          <td id="file-pom-xml-LC72" class="blob-code blob-code-inner js-file-line">&lt;/<span class="pl-ent">project</span>&gt;</td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/d45ff58f67bc59d9fde554e4a94f7d6e/raw/91015786507ae8db0c195c1d26bce20fb0787b87/pom.xml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/d45ff58f67bc59d9fde554e4a94f7d6e#file-pom-xml" class="Link--inTextBlock">
          pom.xml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><h3>1.2 <code>TinyApp.java</code></h3><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569405\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-tinyapp-java\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-java  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;TinyApp.java content, created by jigarkb on 07:54AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;TinyApp.java\&quot;>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>package</span> <span class=pl-s1>how</span>.<span class=pl-s1>observability</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>javalin</span>.<span class=pl-s1>Javalin</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>micrometer</span>.<span class=pl-s1>core</span>.<span class=pl-s1>instrument</span>.<span class=pl-s1>Counter</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>micrometer</span>.<span class=pl-s1>core</span>.<span class=pl-s1>instrument</span>.<span class=pl-s1>Metrics</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>micrometer</span>.<span class=pl-s1>prometheusmetrics</span>.<span class=pl-s1>PrometheusConfig</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>micrometer</span>.<span class=pl-s1>prometheusmetrics</span>.<span class=pl-s1>PrometheusMeterRegistry</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>org</span>.<span class=pl-s1>slf4j</span>.<span class=pl-s1>Logger</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>org</span>.<span class=pl-s1>slf4j</span>.<span class=pl-s1>LoggerFactory</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>public</span> <span class=pl-k>class</span> <span class=pl-smi>TinyApp</span> {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=pl-k>public</span> <span class=pl-k>static</span> <span class=pl-smi>void</span> <span class=pl-en>main</span>(<span class=pl-smi>String</span>[] <span class=pl-s1>args</span>) {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>Logger</span> <span class=pl-s1>log</span> = <span class=pl-smi>LoggerFactory</span>.<span class=pl-en>getLogger</span>(<span class=pl-smi>TinyApp</span>.<span class=pl-k>class</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>PrometheusMeterRegistry</span> <span class=pl-s1>prometheus</span> = <span class=pl-k>new</span> <span class=pl-smi>PrometheusMeterRegistry</span>(<span class=pl-smi>PrometheusConfig</span>.<span class=pl-c1>DEFAULT</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>Metrics</span>.<span class=pl-en>addRegistry</span>(<span class=pl-s1>prometheus</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>Counter</span> <span class=pl-s1>hits</span> = <span class=pl-smi>Counter</span>.<span class=pl-en>builder</span>(<span class=pl-s>&amp;quot;tiny_hits_total&amp;quot;</span>)</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>description</span>(<span class=pl-s>&amp;quot;Total hello hits&amp;quot;</span>)</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>register</span>(<span class=pl-s1>prometheus</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>Javalin</span> <span class=pl-s1>app</span> = <span class=pl-smi>Javalin</span>.<span class=pl-en>create</span>()</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>get</span>(<span class=pl-s>&amp;quot;/hello&amp;quot;</span>, <span class=pl-s1>ctx</span> -&amp;gt; {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    <span class=pl-s1>hits</span>.<span class=pl-en>increment</span>();</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    <span class=pl-s1>log</span>.<span class=pl-en>info</span>(<span class=pl-s>&amp;quot;Handled /hello for {}&amp;quot;</span>, <span class=pl-s1>ctx</span>.<span class=pl-en>ip</span>());</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    <span class=pl-s1>ctx</span>.<span class=pl-en>result</span>(<span class=pl-s>&amp;quot;Hello &amp;quot;</span> + <span class=pl-s1>ctx</span>.<span class=pl-en>ip</span>());</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                })</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>get</span>(<span class=pl-s>&amp;quot;/metrics&amp;quot;</span>, <span class=pl-s1>ctx</span> -&amp;gt; <span class=pl-s1>ctx</span>.<span class=pl-en>result</span>(<span class=pl-s1>prometheus</span>.<span class=pl-en>scrape</span>()))</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>start</span>(<span class=pl-c1>8080</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-s1>log</span>.<span class=pl-en>info</span>(<span class=pl-s>&amp;quot;Tiny app started at http://localhost:8080&amp;quot;</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    }</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-tinyapp-java-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-tinyapp-java-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>}</td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/1416d8b447dc4471f795fec0ae824e41/raw/d96b8a7c3aba06c68ffaa2524c2bfb9fa7cefeba/TinyApp.java\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/1416d8b447dc4471f795fec0ae824e41#file-tinyapp-java\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          TinyApp.java\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569405" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-tinyapp-java" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-java  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="TinyApp.java">
        <tbody><tr>
          <td id="file-tinyapp-java-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-tinyapp-java-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-k">package</span> <span class="pl-s1">how</span>.<span class="pl-s1">observability</span>;</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-tinyapp-java-LC2" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-tinyapp-java-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">javalin</span>.<span class="pl-s1">Javalin</span>;</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-tinyapp-java-LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">micrometer</span>.<span class="pl-s1">core</span>.<span class="pl-s1">instrument</span>.<span class="pl-s1">Counter</span>;</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-tinyapp-java-LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">micrometer</span>.<span class="pl-s1">core</span>.<span class="pl-s1">instrument</span>.<span class="pl-s1">Metrics</span>;</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-tinyapp-java-LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">micrometer</span>.<span class="pl-s1">prometheusmetrics</span>.<span class="pl-s1">PrometheusConfig</span>;</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-tinyapp-java-LC7" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">micrometer</span>.<span class="pl-s1">prometheusmetrics</span>.<span class="pl-s1">PrometheusMeterRegistry</span>;</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-tinyapp-java-LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">org</span>.<span class="pl-s1">slf4j</span>.<span class="pl-s1">Logger</span>;</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-tinyapp-java-LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">org</span>.<span class="pl-s1">slf4j</span>.<span class="pl-s1">LoggerFactory</span>;</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-tinyapp-java-LC10" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-tinyapp-java-LC11" class="blob-code blob-code-inner js-file-line"><span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">TinyApp</span> {</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-tinyapp-java-LC12" class="blob-code blob-code-inner js-file-line">    <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-smi">void</span> <span class="pl-en">main</span>(<span class="pl-smi">String</span>[] <span class="pl-s1">args</span>) {</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-tinyapp-java-LC13" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">Logger</span> <span class="pl-s1">log</span> = <span class="pl-smi">LoggerFactory</span>.<span class="pl-en">getLogger</span>(<span class="pl-smi">TinyApp</span>.<span class="pl-k">class</span>);</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-tinyapp-java-LC14" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-tinyapp-java-LC15" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">PrometheusMeterRegistry</span> <span class="pl-s1">prometheus</span> = <span class="pl-k">new</span> <span class="pl-smi">PrometheusMeterRegistry</span>(<span class="pl-smi">PrometheusConfig</span>.<span class="pl-c1">DEFAULT</span>);</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-tinyapp-java-LC16" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">Metrics</span>.<span class="pl-en">addRegistry</span>(<span class="pl-s1">prometheus</span>);</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-tinyapp-java-LC17" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-tinyapp-java-LC18" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">Counter</span> <span class="pl-s1">hits</span> = <span class="pl-smi">Counter</span>.<span class="pl-en">builder</span>(<span class="pl-s">"tiny_hits_total"</span>)</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-tinyapp-java-LC19" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">description</span>(<span class="pl-s">"Total hello hits"</span>)</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-tinyapp-java-LC20" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">register</span>(<span class="pl-s1">prometheus</span>);</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-tinyapp-java-LC21" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-tinyapp-java-LC22" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">Javalin</span> <span class="pl-s1">app</span> = <span class="pl-smi">Javalin</span>.<span class="pl-en">create</span>()</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-tinyapp-java-LC23" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">get</span>(<span class="pl-s">"/hello"</span>, <span class="pl-s1">ctx</span> -&gt; {</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-tinyapp-java-LC24" class="blob-code blob-code-inner js-file-line">                    <span class="pl-s1">hits</span>.<span class="pl-en">increment</span>();</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-tinyapp-java-LC25" class="blob-code blob-code-inner js-file-line">                    <span class="pl-s1">log</span>.<span class="pl-en">info</span>(<span class="pl-s">"Handled /hello for {}"</span>, <span class="pl-s1">ctx</span>.<span class="pl-en">ip</span>());</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-tinyapp-java-LC26" class="blob-code blob-code-inner js-file-line">                    <span class="pl-s1">ctx</span>.<span class="pl-en">result</span>(<span class="pl-s">"Hello "</span> + <span class="pl-s1">ctx</span>.<span class="pl-en">ip</span>());</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-tinyapp-java-LC27" class="blob-code blob-code-inner js-file-line">                })</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-tinyapp-java-LC28" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">get</span>(<span class="pl-s">"/metrics"</span>, <span class="pl-s1">ctx</span> -&gt; <span class="pl-s1">ctx</span>.<span class="pl-en">result</span>(<span class="pl-s1">prometheus</span>.<span class="pl-en">scrape</span>()))</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-tinyapp-java-LC29" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">start</span>(<span class="pl-c1">8080</span>);</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-tinyapp-java-LC30" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-tinyapp-java-LC31" class="blob-code blob-code-inner js-file-line">        <span class="pl-s1">log</span>.<span class="pl-en">info</span>(<span class="pl-s">"Tiny app started at http://localhost:8080"</span>);</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-tinyapp-java-LC32" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-tinyapp-java-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-tinyapp-java-LC33" class="blob-code blob-code-inner js-file-line">}</td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/1416d8b447dc4471f795fec0ae824e41/raw/d96b8a7c3aba06c68ffaa2524c2bfb9fa7cefeba/TinyApp.java" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/1416d8b447dc4471f795fec0ae824e41#file-tinyapp-java" class="Link--inTextBlock">
          TinyApp.java
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><h3>1.3 <code>Dockerfile</code></h3><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569413\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-dockerfile\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-dockerfile  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;Dockerfile content, created by jigarkb on 07:55AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;Dockerfile\&quot;>\n        <tr>\n          <td id=\&quot;file-dockerfile-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>FROM</span> maven:3.9.9-eclipse-temurin-21 AS build</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>WORKDIR</span> /build</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>COPY</span> pom.xml .</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>RUN</span> mvn -q dependency:go-offline</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>COPY</span> src ./src</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>RUN</span> mvn -q package -DskipTests</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>FROM</span> eclipse-temurin:21-jre</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>WORKDIR</span> /app</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>COPY</span> --from=build /build/target/tiny-app-1.0-SNAPSHOT.jar app.jar</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Grab the OpenTelemetry Java agent</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>ADD</span> https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.15.0/opentelemetry-javaagent.jar /otel.jar</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>ENV</span> OTEL_SERVICE_NAME=tiny-app</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>ENV</span> OTEL_TRACES_EXPORTER=otlp</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>ENV</span> OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>ENV</span> OTEL_METRICS_EXPORTER=none</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>ENV</span> OTEL_LOGS_EXPORTER=none</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>EXPOSE</span> 8080</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-dockerfile-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-dockerfile-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>ENTRYPOINT</span> [<span class=\&quot;pl-s\&quot;>&amp;quot;java&amp;quot;</span>,<span class=\&quot;pl-s\&quot;>&amp;quot;-javaagent:/otel.jar&amp;quot;</span>,<span class=\&quot;pl-s\&quot;>&amp;quot;-jar&amp;quot;</span>,<span class=\&quot;pl-s\&quot;>&amp;quot;app.jar&amp;quot;</span>]</td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/fb1b890c942bd7cbc932d64a0663feb9/raw/a9b1a344c4cc56f1fbee419dffdb7f6b194fe010/Dockerfile\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/fb1b890c942bd7cbc932d64a0663feb9#file-dockerfile\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          Dockerfile\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569413" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-dockerfile" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-dockerfile  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="Dockerfile">
        <tbody><tr>
          <td id="file-dockerfile-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-dockerfile-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-k">FROM</span> maven:3.9.9-eclipse-temurin-21 AS build</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-dockerfile-LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-k">WORKDIR</span> /build</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-dockerfile-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-k">COPY</span> pom.xml .</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-dockerfile-LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-k">RUN</span> mvn -q dependency:go-offline</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-dockerfile-LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-k">COPY</span> src ./src</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-dockerfile-LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-k">RUN</span> mvn -q package -DskipTests</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-dockerfile-LC7" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-dockerfile-LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-k">FROM</span> eclipse-temurin:21-jre</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-dockerfile-LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-k">WORKDIR</span> /app</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-dockerfile-LC10" class="blob-code blob-code-inner js-file-line"><span class="pl-k">COPY</span> --from=build /build/target/tiny-app-1.0-SNAPSHOT.jar app.jar</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-dockerfile-LC11" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">#</span> Grab the OpenTelemetry Java agent</span></td>
        </tr>
        <tr>
          <td id="file-dockerfile-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-dockerfile-LC12" class="blob-code blob-code-inner js-file-line"><span class="pl-k">ADD</span> https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.15.0/opentelemetry-javaagent.jar /otel.jar</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-dockerfile-LC13" class="blob-code blob-code-inner js-file-line"><span class="pl-k">ENV</span> OTEL_SERVICE_NAME=tiny-app</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-dockerfile-LC14" class="blob-code blob-code-inner js-file-line"><span class="pl-k">ENV</span> OTEL_TRACES_EXPORTER=otlp</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-dockerfile-LC15" class="blob-code blob-code-inner js-file-line"><span class="pl-k">ENV</span> OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-dockerfile-LC16" class="blob-code blob-code-inner js-file-line"><span class="pl-k">ENV</span> OTEL_METRICS_EXPORTER=none</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-dockerfile-LC17" class="blob-code blob-code-inner js-file-line"><span class="pl-k">ENV</span> OTEL_LOGS_EXPORTER=none</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-dockerfile-LC18" class="blob-code blob-code-inner js-file-line"><span class="pl-k">EXPOSE</span> 8080</td>
        </tr>
        <tr>
          <td id="file-dockerfile-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-dockerfile-LC19" class="blob-code blob-code-inner js-file-line"><span class="pl-k">ENTRYPOINT</span> [<span class="pl-s">"java"</span>,<span class="pl-s">"-javaagent:/otel.jar"</span>,<span class="pl-s">"-jar"</span>,<span class="pl-s">"app.jar"</span>]</td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/fb1b890c942bd7cbc932d64a0663feb9/raw/a9b1a344c4cc56f1fbee419dffdb7f6b194fe010/Dockerfile" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/fb1b890c942bd7cbc932d64a0663feb9#file-dockerfile" class="Link--inTextBlock">
          Dockerfile
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><p>Build it:</p><pre><code>docker build -t tiny-app:latest .</code></pre><div><hr></div><h2>2 &#8211; Prometheus&#8239;(+&#8239;Alertmanager) Config</h2><h3>2.1 <code>prometheus.yaml</code></h3><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569425\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-prometheus-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;prometheus.yaml content, created by jigarkb on 07:55AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;prometheus.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>global</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>scrape_interval</span>: <span class=\&quot;pl-c1\&quot;>15s</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>scrape_configs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  - <span class=\&quot;pl-ent\&quot;>job_name</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;#39;</span>tiny-app<span class=\&quot;pl-pds\&quot;>&amp;#39;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>metrics_path</span>: <span class=\&quot;pl-s\&quot;>/metrics</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>static_configs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>targets</span>: <span class=\&quot;pl-s\&quot;>[&amp;#39;tiny-app:8080&amp;#39;]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>alerting</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>alertmanagers</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    - <span class=\&quot;pl-ent\&quot;>static_configs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        - <span class=\&quot;pl-ent\&quot;>targets</span>: <span class=\&quot;pl-s\&quot;>[&amp;#39;alertmanager:9093&amp;#39;]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>rule_files</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-prometheus-yaml-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-prometheus-yaml-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  - <span class=\&quot;pl-s\&quot;>alert_rules.yaml</span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/a5c1ec1f9c5b3a6cc118eb755ce0f16a/raw/65547aadc15e406f6efc4aeb78bfd47e1379cef9/prometheus.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/a5c1ec1f9c5b3a6cc118eb755ce0f16a#file-prometheus-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          prometheus.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569425" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-prometheus-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="prometheus.yaml">
        <tbody><tr>
          <td id="file-prometheus-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-prometheus-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">global</span>:</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-prometheus-yaml-LC2" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">scrape_interval</span>: <span class="pl-c1">15s</span></td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-prometheus-yaml-LC3" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-prometheus-yaml-LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">scrape_configs</span>:</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-prometheus-yaml-LC5" class="blob-code blob-code-inner js-file-line">  - <span class="pl-ent">job_name</span>: <span class="pl-s"><span class="pl-pds">'</span>tiny-app<span class="pl-pds">'</span></span></td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-prometheus-yaml-LC6" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">metrics_path</span>: <span class="pl-s">/metrics</span></td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-prometheus-yaml-LC7" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">static_configs</span>:</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-prometheus-yaml-LC8" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">targets</span>: <span class="pl-s">['tiny-app:8080']</span></td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-prometheus-yaml-LC9" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-prometheus-yaml-LC10" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">alerting</span>:</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-prometheus-yaml-LC11" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">alertmanagers</span>:</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-prometheus-yaml-LC12" class="blob-code blob-code-inner js-file-line">    - <span class="pl-ent">static_configs</span>:</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-prometheus-yaml-LC13" class="blob-code blob-code-inner js-file-line">        - <span class="pl-ent">targets</span>: <span class="pl-s">['alertmanager:9093']</span></td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-prometheus-yaml-LC14" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-prometheus-yaml-LC15" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">rule_files</span>:</td>
        </tr>
        <tr>
          <td id="file-prometheus-yaml-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-prometheus-yaml-LC16" class="blob-code blob-code-inner js-file-line">  - <span class="pl-s">alert_rules.yaml</span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/a5c1ec1f9c5b3a6cc118eb755ce0f16a/raw/65547aadc15e406f6efc4aeb78bfd47e1379cef9/prometheus.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/a5c1ec1f9c5b3a6cc118eb755ce0f16a#file-prometheus-yaml" class="Link--inTextBlock">
          prometheus.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><h3>2.2 <code>alert-rules.yaml</code></h3><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569439\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-alert-rules-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;alert-rules.yaml content, created by jigarkb on 07:56AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;alert-rules.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>groups</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>tiny.rules</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>rules</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>alert</span>: <span class=\&quot;pl-s\&quot;>HighRequestRate</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>expr</span>: <span class=\&quot;pl-s\&quot;>rate(tiny_hits_total[1m]) &amp;gt; 5</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>for</span>: <span class=\&quot;pl-c1\&quot;>1m</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>labels</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>severity</span>: <span class=\&quot;pl-s\&quot;>warning</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>annotations</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>summary</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>High request rate on tiny-app<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alert-rules-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-alert-rules-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>description</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>Request rate &amp;gt;5 RPS for 1 min.<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/9d33fa49adef44efcd15bc484632b49f/raw/f48dbeb6c96a62862e0a5d802c864c4bc01b2319/alert-rules.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/9d33fa49adef44efcd15bc484632b49f#file-alert-rules-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          alert-rules.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569439" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-alert-rules-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="alert-rules.yaml">
        <tbody><tr>
          <td id="file-alert-rules-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-alert-rules-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">groups</span>:</td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-alert-rules-yaml-LC2" class="blob-code blob-code-inner js-file-line">  - <span class="pl-ent">name</span>: <span class="pl-s">tiny.rules</span></td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-alert-rules-yaml-LC3" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">rules</span>:</td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-alert-rules-yaml-LC4" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">alert</span>: <span class="pl-s">HighRequestRate</span></td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-alert-rules-yaml-LC5" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">expr</span>: <span class="pl-s">rate(tiny_hits_total[1m]) &gt; 5</span></td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-alert-rules-yaml-LC6" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">for</span>: <span class="pl-c1">1m</span></td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-alert-rules-yaml-LC7" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">labels</span>:</td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-alert-rules-yaml-LC8" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">severity</span>: <span class="pl-s">warning</span></td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-alert-rules-yaml-LC9" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">annotations</span>:</td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-alert-rules-yaml-LC10" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">summary</span>: <span class="pl-s"><span class="pl-pds">"</span>High request rate on tiny-app<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-alert-rules-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-alert-rules-yaml-LC11" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">description</span>: <span class="pl-s"><span class="pl-pds">"</span>Request rate &gt;5 RPS for 1 min.<span class="pl-pds">"</span></span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/9d33fa49adef44efcd15bc484632b49f/raw/f48dbeb6c96a62862e0a5d802c864c4bc01b2319/alert-rules.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/9d33fa49adef44efcd15bc484632b49f#file-alert-rules-yaml" class="Link--inTextBlock">
          alert-rules.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><h3>2.3 <code>alertmanager.yaml</code></h3><p>We&#8217;ll use a throw&#8209;away &#8220;alert&#8209;logger&#8221; container that simply prints POST bodies to stdout so you can observe alerts without email/SMS.</p><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569449\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-alertmanager-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;alertmanager.yaml content, created by jigarkb on 07:57AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;alertmanager.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-alertmanager-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-alertmanager-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>route</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alertmanager-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-alertmanager-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>receiver</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;#39;</span>log<span class=\&quot;pl-pds\&quot;>&amp;#39;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alertmanager-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-alertmanager-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>receivers</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alertmanager-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-alertmanager-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;#39;</span>log<span class=\&quot;pl-pds\&quot;>&amp;#39;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alertmanager-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-alertmanager-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>webhook_configs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-alertmanager-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-alertmanager-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>url</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;#39;</span>http://alert-logger:5678<span class=\&quot;pl-pds\&quot;>&amp;#39;</span></span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/4409ba853588990ab064b85b017c5a09/raw/b48dd3c830feda32e0212c48e373427defb0af38/alertmanager.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/4409ba853588990ab064b85b017c5a09#file-alertmanager-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          alertmanager.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569449" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-alertmanager-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="alertmanager.yaml">
        <tbody><tr>
          <td id="file-alertmanager-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-alertmanager-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">route</span>:</td>
        </tr>
        <tr>
          <td id="file-alertmanager-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-alertmanager-yaml-LC2" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">receiver</span>: <span class="pl-s"><span class="pl-pds">'</span>log<span class="pl-pds">'</span></span></td>
        </tr>
        <tr>
          <td id="file-alertmanager-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-alertmanager-yaml-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">receivers</span>:</td>
        </tr>
        <tr>
          <td id="file-alertmanager-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-alertmanager-yaml-LC4" class="blob-code blob-code-inner js-file-line">  - <span class="pl-ent">name</span>: <span class="pl-s"><span class="pl-pds">'</span>log<span class="pl-pds">'</span></span></td>
        </tr>
        <tr>
          <td id="file-alertmanager-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-alertmanager-yaml-LC5" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">webhook_configs</span>:</td>
        </tr>
        <tr>
          <td id="file-alertmanager-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-alertmanager-yaml-LC6" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">url</span>: <span class="pl-s"><span class="pl-pds">'</span>http://alert-logger:5678<span class="pl-pds">'</span></span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/4409ba853588990ab064b85b017c5a09/raw/b48dd3c830feda32e0212c48e373427defb0af38/alertmanager.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/4409ba853588990ab064b85b017c5a09#file-alertmanager-yaml" class="Link--inTextBlock">
          alertmanager.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><div><hr></div><h2>3 &#8211; Loki &amp; Promtail Config</h2><h3>3.1 <code>loki.yaml</code></h3><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569459\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-loki-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;loki.yaml content, created by jigarkb on 07:57AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;loki.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>auth_enabled</span>: <span class=\&quot;pl-c1\&quot;>false</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>server</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>http_listen_port</span>: <span class=\&quot;pl-c1\&quot;>3100</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>grpc_listen_port</span>: <span class=\&quot;pl-c1\&quot;>9096</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>log_level</span>: <span class=\&quot;pl-s\&quot;>debug</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>grpc_server_max_concurrent_streams</span>: <span class=\&quot;pl-c1\&quot;>1000</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>common</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>instance_addr</span>: <span class=\&quot;pl-s\&quot;>127.0.0.1</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>path_prefix</span>: <span class=\&quot;pl-s\&quot;>/tmp/loki</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>storage</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>filesystem</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>chunks_directory</span>: <span class=\&quot;pl-s\&quot;>/tmp/loki/chunks</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>rules_directory</span>: <span class=\&quot;pl-s\&quot;>/tmp/loki/rules</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>replication_factor</span>: <span class=\&quot;pl-c1\&quot;>1</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>ring</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>kvstore</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>store</span>: <span class=\&quot;pl-s\&quot;>inmemory</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>query_range</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>results_cache</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>cache</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>embedded_cache</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>enabled</span>: <span class=\&quot;pl-c1\&quot;>true</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>max_size_mb</span>: <span class=\&quot;pl-c1\&quot;>100</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>limits_config</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>metric_aggregation_enabled</span>: <span class=\&quot;pl-c1\&quot;>true</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>schema_config</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>configs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    - <span class=\&quot;pl-ent\&quot;>from</span>: <span class=\&quot;pl-c1\&quot;>2020-10-24</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L34\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;34\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC34\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>store</span>: <span class=\&quot;pl-s\&quot;>tsdb</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L35\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;35\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC35\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>object_store</span>: <span class=\&quot;pl-s\&quot;>filesystem</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L36\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;36\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC36\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>schema</span>: <span class=\&quot;pl-c1\&quot;>v13</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L37\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;37\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC37\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>index</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L38\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;38\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC38\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>prefix</span>: <span class=\&quot;pl-s\&quot;>index_</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L39\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;39\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC39\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>period</span>: <span class=\&quot;pl-c1\&quot;>24h</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L40\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;40\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC40\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L41\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;41\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC41\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>pattern_ingester</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L42\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;42\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC42\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>enabled</span>: <span class=\&quot;pl-c1\&quot;>true</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L43\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;43\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC43\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>metric_aggregation</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L44\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;44\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC44\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>loki_address</span>: <span class=\&quot;pl-s\&quot;>localhost:3100</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L45\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;45\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC45\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L46\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;46\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC46\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>ruler</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L47\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;47\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC47\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>alertmanager_url</span>: <span class=\&quot;pl-s\&quot;>http://alertmanager:9093</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L48\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;48\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC48\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L49\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;49\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC49\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>frontend</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L50\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;50\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC50\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>encoding</span>: <span class=\&quot;pl-s\&quot;>protobuf</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L51\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;51\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC51\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L52\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;52\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC52\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>analytics</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-loki-yaml-L53\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;53\&quot;></td>\n          <td id=\&quot;file-loki-yaml-LC53\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>reporting_enabled</span>: <span class=\&quot;pl-c1\&quot;>false</span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/732c2db7bf4438be5d8ef45468489988/raw/c8f7118dc8ffc9a4ae2ccfd217a7720ed239390c/loki.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/732c2db7bf4438be5d8ef45468489988#file-loki-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          loki.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569459" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-loki-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="loki.yaml">
        <tbody><tr>
          <td id="file-loki-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-loki-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">auth_enabled</span>: <span class="pl-c1">false</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-loki-yaml-LC2" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-loki-yaml-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">server</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-loki-yaml-LC4" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">http_listen_port</span>: <span class="pl-c1">3100</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-loki-yaml-LC5" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">grpc_listen_port</span>: <span class="pl-c1">9096</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-loki-yaml-LC6" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">log_level</span>: <span class="pl-s">debug</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-loki-yaml-LC7" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">grpc_server_max_concurrent_streams</span>: <span class="pl-c1">1000</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-loki-yaml-LC8" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-loki-yaml-LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">common</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-loki-yaml-LC10" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">instance_addr</span>: <span class="pl-s">127.0.0.1</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-loki-yaml-LC11" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">path_prefix</span>: <span class="pl-s">/tmp/loki</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-loki-yaml-LC12" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">storage</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-loki-yaml-LC13" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">filesystem</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-loki-yaml-LC14" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">chunks_directory</span>: <span class="pl-s">/tmp/loki/chunks</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-loki-yaml-LC15" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">rules_directory</span>: <span class="pl-s">/tmp/loki/rules</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-loki-yaml-LC16" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">replication_factor</span>: <span class="pl-c1">1</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-loki-yaml-LC17" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">ring</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-loki-yaml-LC18" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">kvstore</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-loki-yaml-LC19" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">store</span>: <span class="pl-s">inmemory</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-loki-yaml-LC20" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-loki-yaml-LC21" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">query_range</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-loki-yaml-LC22" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">results_cache</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-loki-yaml-LC23" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">cache</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-loki-yaml-LC24" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">embedded_cache</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-loki-yaml-LC25" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">enabled</span>: <span class="pl-c1">true</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-loki-yaml-LC26" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">max_size_mb</span>: <span class="pl-c1">100</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-loki-yaml-LC27" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-loki-yaml-LC28" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">limits_config</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-loki-yaml-LC29" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">metric_aggregation_enabled</span>: <span class="pl-c1">true</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-loki-yaml-LC30" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-loki-yaml-LC31" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">schema_config</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-loki-yaml-LC32" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">configs</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-loki-yaml-LC33" class="blob-code blob-code-inner js-file-line">    - <span class="pl-ent">from</span>: <span class="pl-c1">2020-10-24</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-loki-yaml-LC34" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">store</span>: <span class="pl-s">tsdb</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-loki-yaml-LC35" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">object_store</span>: <span class="pl-s">filesystem</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
          <td id="file-loki-yaml-LC36" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">schema</span>: <span class="pl-c1">v13</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L37" class="blob-num js-line-number js-blob-rnum" data-line-number="37"></td>
          <td id="file-loki-yaml-LC37" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">index</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L38" class="blob-num js-line-number js-blob-rnum" data-line-number="38"></td>
          <td id="file-loki-yaml-LC38" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">prefix</span>: <span class="pl-s">index_</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L39" class="blob-num js-line-number js-blob-rnum" data-line-number="39"></td>
          <td id="file-loki-yaml-LC39" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">period</span>: <span class="pl-c1">24h</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L40" class="blob-num js-line-number js-blob-rnum" data-line-number="40"></td>
          <td id="file-loki-yaml-LC40" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L41" class="blob-num js-line-number js-blob-rnum" data-line-number="41"></td>
          <td id="file-loki-yaml-LC41" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">pattern_ingester</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L42" class="blob-num js-line-number js-blob-rnum" data-line-number="42"></td>
          <td id="file-loki-yaml-LC42" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">enabled</span>: <span class="pl-c1">true</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L43" class="blob-num js-line-number js-blob-rnum" data-line-number="43"></td>
          <td id="file-loki-yaml-LC43" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">metric_aggregation</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L44" class="blob-num js-line-number js-blob-rnum" data-line-number="44"></td>
          <td id="file-loki-yaml-LC44" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">loki_address</span>: <span class="pl-s">localhost:3100</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L45" class="blob-num js-line-number js-blob-rnum" data-line-number="45"></td>
          <td id="file-loki-yaml-LC45" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L46" class="blob-num js-line-number js-blob-rnum" data-line-number="46"></td>
          <td id="file-loki-yaml-LC46" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">ruler</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L47" class="blob-num js-line-number js-blob-rnum" data-line-number="47"></td>
          <td id="file-loki-yaml-LC47" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">alertmanager_url</span>: <span class="pl-s">http://alertmanager:9093</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L48" class="blob-num js-line-number js-blob-rnum" data-line-number="48"></td>
          <td id="file-loki-yaml-LC48" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L49" class="blob-num js-line-number js-blob-rnum" data-line-number="49"></td>
          <td id="file-loki-yaml-LC49" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">frontend</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L50" class="blob-num js-line-number js-blob-rnum" data-line-number="50"></td>
          <td id="file-loki-yaml-LC50" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">encoding</span>: <span class="pl-s">protobuf</span></td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L51" class="blob-num js-line-number js-blob-rnum" data-line-number="51"></td>
          <td id="file-loki-yaml-LC51" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L52" class="blob-num js-line-number js-blob-rnum" data-line-number="52"></td>
          <td id="file-loki-yaml-LC52" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">analytics</span>:</td>
        </tr>
        <tr>
          <td id="file-loki-yaml-L53" class="blob-num js-line-number js-blob-rnum" data-line-number="53"></td>
          <td id="file-loki-yaml-LC53" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">reporting_enabled</span>: <span class="pl-c1">false</span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/732c2db7bf4438be5d8ef45468489988/raw/c8f7118dc8ffc9a4ae2ccfd217a7720ed239390c/loki.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/732c2db7bf4438be5d8ef45468489988#file-loki-yaml" class="Link--inTextBlock">
          loki.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><h3>3.2 <code>promtail.yaml</code></h3><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569466\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-promtail-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;promtail.yaml content, created by jigarkb on 07:58AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;promtail.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>server</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>http_listen_port</span>: <span class=\&quot;pl-c1\&quot;>9080</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>grpc_listen_port</span>: <span class=\&quot;pl-c1\&quot;>0</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>positions</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>filename</span>: <span class=\&quot;pl-s\&quot;>/tmp/positions.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>clients</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  - <span class=\&quot;pl-ent\&quot;>url</span>: <span class=\&quot;pl-s\&quot;>http://loki:3100/loki/api/v1/push</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>scrape_configs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  - <span class=\&quot;pl-ent\&quot;>job_name</span>: <span class=\&quot;pl-s\&quot;>container_logs</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>docker_sd_configs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>host</span>: <span class=\&quot;pl-s\&quot;>unix:///var/run/docker.sock</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>refresh_interval</span>: <span class=\&quot;pl-c1\&quot;>5s</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>relabel_configs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>source_labels</span>: <span class=\&quot;pl-s\&quot;>[ &amp;#39;__meta_docker_container_name&amp;#39; ]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>regex</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;#39;</span>/(.*)<span class=\&quot;pl-pds\&quot;>&amp;#39;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-promtail-yaml-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-promtail-yaml-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>target_label</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;#39;</span>container<span class=\&quot;pl-pds\&quot;>&amp;#39;</span></span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/914e3f391966d9fd43689e2c31e4ca51/raw/1140aa34ae5d5d7b14329fd57eaa6d8c64a2feb7/promtail.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/914e3f391966d9fd43689e2c31e4ca51#file-promtail-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          promtail.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569466" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-promtail-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="promtail.yaml">
        <tbody><tr>
          <td id="file-promtail-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-promtail-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">server</span>:</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-promtail-yaml-LC2" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">http_listen_port</span>: <span class="pl-c1">9080</span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-promtail-yaml-LC3" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">grpc_listen_port</span>: <span class="pl-c1">0</span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-promtail-yaml-LC4" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-promtail-yaml-LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">positions</span>:</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-promtail-yaml-LC6" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">filename</span>: <span class="pl-s">/tmp/positions.yaml</span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-promtail-yaml-LC7" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-promtail-yaml-LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">clients</span>:</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-promtail-yaml-LC9" class="blob-code blob-code-inner js-file-line">  - <span class="pl-ent">url</span>: <span class="pl-s">http://loki:3100/loki/api/v1/push</span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-promtail-yaml-LC10" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-promtail-yaml-LC11" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">scrape_configs</span>:</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-promtail-yaml-LC12" class="blob-code blob-code-inner js-file-line">  - <span class="pl-ent">job_name</span>: <span class="pl-s">container_logs</span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-promtail-yaml-LC13" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">docker_sd_configs</span>:</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-promtail-yaml-LC14" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">host</span>: <span class="pl-s">unix:///var/run/docker.sock</span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-promtail-yaml-LC15" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">refresh_interval</span>: <span class="pl-c1">5s</span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-promtail-yaml-LC16" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">relabel_configs</span>:</td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-promtail-yaml-LC17" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">source_labels</span>: <span class="pl-s">[ '__meta_docker_container_name' ]</span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-promtail-yaml-LC18" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">regex</span>: <span class="pl-s"><span class="pl-pds">'</span>/(.*)<span class="pl-pds">'</span></span></td>
        </tr>
        <tr>
          <td id="file-promtail-yaml-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-promtail-yaml-LC19" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">target_label</span>: <span class="pl-s"><span class="pl-pds">'</span>container<span class="pl-pds">'</span></span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/914e3f391966d9fd43689e2c31e4ca51/raw/1140aa34ae5d5d7b14329fd57eaa6d8c64a2feb7/promtail.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/914e3f391966d9fd43689e2c31e4ca51#file-promtail-yaml" class="Link--inTextBlock">
          promtail.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><h2>4 &#8211; Docker Compose Config</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bnR9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bnR9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg 424w, https://substackcdn.com/image/fetch/$s_!bnR9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg 848w, https://substackcdn.com/image/fetch/$s_!bnR9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg 1272w, https://substackcdn.com/image/fetch/$s_!bnR9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bnR9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg" width="1476" height="390" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:390,&quot;width&quot;:1476,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" title="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" srcset="https://substackcdn.com/image/fetch/$s_!bnR9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg 424w, https://substackcdn.com/image/fetch/$s_!bnR9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg 848w, https://substackcdn.com/image/fetch/$s_!bnR9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg 1272w, https://substackcdn.com/image/fetch/$s_!bnR9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F468336cc-3550-4573-99ea-4e106d3195a3_1476x391.svg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569475\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-docker-compose-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;docker-compose.yaml content, created by jigarkb on 07:58AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;docker-compose.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>services</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> -------------- Observability back&#8209;end stack --------------</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>prometheus</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>prom/prometheus:v3.3.0</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>volumes</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;>./prometheus.yaml:/etc/prometheus/prometheus.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;>./alert-rules.yaml:/etc/prometheus/alert_rules.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>9090:9090<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>command</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>--config.file=/etc/prometheus/prometheus.yaml<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>alertmanager</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>prom/alertmanager:v0.28.1</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>volumes</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;>./alertmanager.yaml:/etc/alertmanager/alertmanager.yml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>ports</span>: </td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>9093:9093<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>loki</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>grafana/loki:3.5.0</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>3100:3100<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>volumes</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;>./loki.yaml:/etc/loki/local-config.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>command</span>: <span class=\&quot;pl-s\&quot;>-config.file=/etc/loki/local-config.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>promtail</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>grafana/promtail:3.5.0</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>volumes</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;>/var/run/docker.sock:/var/run/docker.sock</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;>./promtail.yaml:/etc/promtail/config.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;>/var/lib/docker/containers:/var/log/containers:ro</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L34\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;34\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC34\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>command</span>: <span class=\&quot;pl-s\&quot;>-config.file=/etc/promtail/config.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L35\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;35\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC35\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L36\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;36\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC36\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>jaeger</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L37\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;37\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC37\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>jaegertracing/all-in-one:1.68.0</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L38\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;38\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC38\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>environment</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L39\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;39\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC39\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>COLLECTOR_OTLP_ENABLED</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>true<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L40\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;40\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC40\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L41\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;41\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC41\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>16686:16686<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span>   <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> UI</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L42\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;42\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC42\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>4318:4318<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span>     <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> OTLP HTTP</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L43\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;43\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC43\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L44\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;44\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC44\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>grafana</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L45\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;45\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC45\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>grafana/grafana:11.6.1</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L46\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;46\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC46\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>depends_on</span>: <span class=\&quot;pl-s\&quot;>[prometheus, loki, jaeger]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L47\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;47\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC47\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L48\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;48\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC48\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>3000:3000<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L49\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;49\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC49\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>environment</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L50\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;50\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC50\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>GF_SECURITY_ADMIN_PASSWORD</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>admin<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L51\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;51\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC51\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>volumes</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L52\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;52\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC52\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;>grafana-data:/var/lib/grafana</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L53\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;53\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC53\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L54\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;54\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC54\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> -------------- Tiny application --------------</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L55\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;55\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC55\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>tiny-app</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L56\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;56\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC56\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>tiny-app:latest</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L57\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;57\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC57\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>build</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L58\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;58\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC58\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>context</span>: <span class=\&quot;pl-s\&quot;>./tiny-app</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L59\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;59\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC59\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>depends_on</span>: <span class=\&quot;pl-s\&quot;>[jaeger]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L60\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;60\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC60\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L61\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;61\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC61\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>8080:8080<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L62\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;62\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC62\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>labels</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L63\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;63\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC63\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>logging</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>promtail<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L64\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;64\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC64\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L65\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;65\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC65\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> -------------- Alert sink for Tiny stack --------------</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L66\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;66\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC66\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>alert-logger</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L67\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;67\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC67\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>mendhak/http-https-echo:36</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L68\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;68\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC68\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>environment</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L69\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;69\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC69\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>HTTP_PORT</span>: <span class=\&quot;pl-c1\&quot;>5678</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L70\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;70\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC70\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L71\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;71\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC71\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>5678:5678<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L72\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;72\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC72\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L73\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;73\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC73\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>volumes</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-docker-compose-yaml-L74\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;74\&quot;></td>\n          <td id=\&quot;file-docker-compose-yaml-LC74\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>grafana-data</span>: <span class=\&quot;pl-s\&quot;>{}</span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/fc3b18a0ed1f2878bc3565090d2edd81/raw/d07bb05f320bd88b5ed64032f7699465a57eab01/docker-compose.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/fc3b18a0ed1f2878bc3565090d2edd81#file-docker-compose-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          docker-compose.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569475" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-docker-compose-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="docker-compose.yaml">
        <tbody><tr>
          <td id="file-docker-compose-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-docker-compose-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">services</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-docker-compose-yaml-LC2" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> -------------- Observability back&#8209;end stack --------------</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-docker-compose-yaml-LC3" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">prometheus</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-docker-compose-yaml-LC4" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">image</span>: <span class="pl-s">prom/prometheus:v3.3.0</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-docker-compose-yaml-LC5" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">volumes</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-docker-compose-yaml-LC6" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s">./prometheus.yaml:/etc/prometheus/prometheus.yaml</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-docker-compose-yaml-LC7" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s">./alert-rules.yaml:/etc/prometheus/alert_rules.yaml</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-docker-compose-yaml-LC8" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-docker-compose-yaml-LC9" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>9090:9090<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-docker-compose-yaml-LC10" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">command</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-docker-compose-yaml-LC11" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>--config.file=/etc/prometheus/prometheus.yaml<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-docker-compose-yaml-LC12" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-docker-compose-yaml-LC13" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">alertmanager</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-docker-compose-yaml-LC14" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">image</span>: <span class="pl-s">prom/alertmanager:v0.28.1</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-docker-compose-yaml-LC15" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">volumes</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-docker-compose-yaml-LC16" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s">./alertmanager.yaml:/etc/alertmanager/alertmanager.yml</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-docker-compose-yaml-LC17" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">ports</span>: </td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-docker-compose-yaml-LC18" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>9093:9093<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-docker-compose-yaml-LC19" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-docker-compose-yaml-LC20" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">loki</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-docker-compose-yaml-LC21" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">image</span>: <span class="pl-s">grafana/loki:3.5.0</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-docker-compose-yaml-LC22" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-docker-compose-yaml-LC23" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>3100:3100<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-docker-compose-yaml-LC24" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">volumes</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-docker-compose-yaml-LC25" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s">./loki.yaml:/etc/loki/local-config.yaml</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-docker-compose-yaml-LC26" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">command</span>: <span class="pl-s">-config.file=/etc/loki/local-config.yaml</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-docker-compose-yaml-LC27" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-docker-compose-yaml-LC28" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">promtail</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-docker-compose-yaml-LC29" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">image</span>: <span class="pl-s">grafana/promtail:3.5.0</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-docker-compose-yaml-LC30" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">volumes</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-docker-compose-yaml-LC31" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s">/var/run/docker.sock:/var/run/docker.sock</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-docker-compose-yaml-LC32" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s">./promtail.yaml:/etc/promtail/config.yaml</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-docker-compose-yaml-LC33" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s">/var/lib/docker/containers:/var/log/containers:ro</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-docker-compose-yaml-LC34" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">command</span>: <span class="pl-s">-config.file=/etc/promtail/config.yaml</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-docker-compose-yaml-LC35" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
          <td id="file-docker-compose-yaml-LC36" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">jaeger</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L37" class="blob-num js-line-number js-blob-rnum" data-line-number="37"></td>
          <td id="file-docker-compose-yaml-LC37" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">image</span>: <span class="pl-s">jaegertracing/all-in-one:1.68.0</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L38" class="blob-num js-line-number js-blob-rnum" data-line-number="38"></td>
          <td id="file-docker-compose-yaml-LC38" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">environment</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L39" class="blob-num js-line-number js-blob-rnum" data-line-number="39"></td>
          <td id="file-docker-compose-yaml-LC39" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">COLLECTOR_OTLP_ENABLED</span>: <span class="pl-s"><span class="pl-pds">"</span>true<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L40" class="blob-num js-line-number js-blob-rnum" data-line-number="40"></td>
          <td id="file-docker-compose-yaml-LC40" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L41" class="blob-num js-line-number js-blob-rnum" data-line-number="41"></td>
          <td id="file-docker-compose-yaml-LC41" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>16686:16686<span class="pl-pds">"</span></span>   <span class="pl-c"><span class="pl-c">#</span> UI</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L42" class="blob-num js-line-number js-blob-rnum" data-line-number="42"></td>
          <td id="file-docker-compose-yaml-LC42" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>4318:4318<span class="pl-pds">"</span></span>     <span class="pl-c"><span class="pl-c">#</span> OTLP HTTP</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L43" class="blob-num js-line-number js-blob-rnum" data-line-number="43"></td>
          <td id="file-docker-compose-yaml-LC43" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L44" class="blob-num js-line-number js-blob-rnum" data-line-number="44"></td>
          <td id="file-docker-compose-yaml-LC44" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">grafana</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L45" class="blob-num js-line-number js-blob-rnum" data-line-number="45"></td>
          <td id="file-docker-compose-yaml-LC45" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">image</span>: <span class="pl-s">grafana/grafana:11.6.1</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L46" class="blob-num js-line-number js-blob-rnum" data-line-number="46"></td>
          <td id="file-docker-compose-yaml-LC46" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">depends_on</span>: <span class="pl-s">[prometheus, loki, jaeger]</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L47" class="blob-num js-line-number js-blob-rnum" data-line-number="47"></td>
          <td id="file-docker-compose-yaml-LC47" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L48" class="blob-num js-line-number js-blob-rnum" data-line-number="48"></td>
          <td id="file-docker-compose-yaml-LC48" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>3000:3000<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L49" class="blob-num js-line-number js-blob-rnum" data-line-number="49"></td>
          <td id="file-docker-compose-yaml-LC49" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">environment</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L50" class="blob-num js-line-number js-blob-rnum" data-line-number="50"></td>
          <td id="file-docker-compose-yaml-LC50" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">GF_SECURITY_ADMIN_PASSWORD</span>: <span class="pl-s"><span class="pl-pds">"</span>admin<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L51" class="blob-num js-line-number js-blob-rnum" data-line-number="51"></td>
          <td id="file-docker-compose-yaml-LC51" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">volumes</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L52" class="blob-num js-line-number js-blob-rnum" data-line-number="52"></td>
          <td id="file-docker-compose-yaml-LC52" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s">grafana-data:/var/lib/grafana</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L53" class="blob-num js-line-number js-blob-rnum" data-line-number="53"></td>
          <td id="file-docker-compose-yaml-LC53" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L54" class="blob-num js-line-number js-blob-rnum" data-line-number="54"></td>
          <td id="file-docker-compose-yaml-LC54" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> -------------- Tiny application --------------</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L55" class="blob-num js-line-number js-blob-rnum" data-line-number="55"></td>
          <td id="file-docker-compose-yaml-LC55" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">tiny-app</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L56" class="blob-num js-line-number js-blob-rnum" data-line-number="56"></td>
          <td id="file-docker-compose-yaml-LC56" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">image</span>: <span class="pl-s">tiny-app:latest</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L57" class="blob-num js-line-number js-blob-rnum" data-line-number="57"></td>
          <td id="file-docker-compose-yaml-LC57" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">build</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L58" class="blob-num js-line-number js-blob-rnum" data-line-number="58"></td>
          <td id="file-docker-compose-yaml-LC58" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">context</span>: <span class="pl-s">./tiny-app</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L59" class="blob-num js-line-number js-blob-rnum" data-line-number="59"></td>
          <td id="file-docker-compose-yaml-LC59" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">depends_on</span>: <span class="pl-s">[jaeger]</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L60" class="blob-num js-line-number js-blob-rnum" data-line-number="60"></td>
          <td id="file-docker-compose-yaml-LC60" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L61" class="blob-num js-line-number js-blob-rnum" data-line-number="61"></td>
          <td id="file-docker-compose-yaml-LC61" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>8080:8080<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L62" class="blob-num js-line-number js-blob-rnum" data-line-number="62"></td>
          <td id="file-docker-compose-yaml-LC62" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">labels</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L63" class="blob-num js-line-number js-blob-rnum" data-line-number="63"></td>
          <td id="file-docker-compose-yaml-LC63" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">logging</span>: <span class="pl-s"><span class="pl-pds">"</span>promtail<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L64" class="blob-num js-line-number js-blob-rnum" data-line-number="64"></td>
          <td id="file-docker-compose-yaml-LC64" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L65" class="blob-num js-line-number js-blob-rnum" data-line-number="65"></td>
          <td id="file-docker-compose-yaml-LC65" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> -------------- Alert sink for Tiny stack --------------</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L66" class="blob-num js-line-number js-blob-rnum" data-line-number="66"></td>
          <td id="file-docker-compose-yaml-LC66" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">alert-logger</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L67" class="blob-num js-line-number js-blob-rnum" data-line-number="67"></td>
          <td id="file-docker-compose-yaml-LC67" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">image</span>: <span class="pl-s">mendhak/http-https-echo:36</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L68" class="blob-num js-line-number js-blob-rnum" data-line-number="68"></td>
          <td id="file-docker-compose-yaml-LC68" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">environment</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L69" class="blob-num js-line-number js-blob-rnum" data-line-number="69"></td>
          <td id="file-docker-compose-yaml-LC69" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">HTTP_PORT</span>: <span class="pl-c1">5678</span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L70" class="blob-num js-line-number js-blob-rnum" data-line-number="70"></td>
          <td id="file-docker-compose-yaml-LC70" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L71" class="blob-num js-line-number js-blob-rnum" data-line-number="71"></td>
          <td id="file-docker-compose-yaml-LC71" class="blob-code blob-code-inner js-file-line">      - <span class="pl-s"><span class="pl-pds">"</span>5678:5678<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L72" class="blob-num js-line-number js-blob-rnum" data-line-number="72"></td>
          <td id="file-docker-compose-yaml-LC72" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L73" class="blob-num js-line-number js-blob-rnum" data-line-number="73"></td>
          <td id="file-docker-compose-yaml-LC73" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">volumes</span>:</td>
        </tr>
        <tr>
          <td id="file-docker-compose-yaml-L74" class="blob-num js-line-number js-blob-rnum" data-line-number="74"></td>
          <td id="file-docker-compose-yaml-LC74" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">grafana-data</span>: <span class="pl-s">{}</span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/fc3b18a0ed1f2878bc3565090d2edd81/raw/d07bb05f320bd88b5ed64032f7699465a57eab01/docker-compose.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/fc3b18a0ed1f2878bc3565090d2edd81#file-docker-compose-yaml" class="Link--inTextBlock">
          docker-compose.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><h2>5 &#8211; Fire It Up!</h2><pre><code>docker compose up -d</code></pre><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3wUJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3wUJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png 424w, https://substackcdn.com/image/fetch/$s_!3wUJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png 848w, https://substackcdn.com/image/fetch/$s_!3wUJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png 1272w, https://substackcdn.com/image/fetch/$s_!3wUJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3wUJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png" width="2000" height="471" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b099547c-3747-499d-9034-9cdab0166311_2000x471.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:471,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" title="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" srcset="https://substackcdn.com/image/fetch/$s_!3wUJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png 424w, https://substackcdn.com/image/fetch/$s_!3wUJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png 848w, https://substackcdn.com/image/fetch/$s_!3wUJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png 1272w, https://substackcdn.com/image/fetch/$s_!3wUJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb099547c-3747-499d-9034-9cdab0166311_2000x471.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Give it ~30&#8239;seconds. Hit the demo app:</p><pre><code>curl http://localhost:8080/hello
ab -n 200 -c 20 http://localhost:8080/hello   # generate some load
</code></pre><p>You should see &#8220;Hello&#8221; responses and, in the container logs,&nbsp;<code>Handled /hello &#8230;</code>&nbsp;log lines (Promtail picks them up).</p><h2>6&#8239;&#8211;&#8239;Exploring the Data</h2><h3>6.1 Grafana Login</h3><ul><li><p>Browser &#8594;&nbsp;<code>http://localhost:3000</code><br><em>User</em>:&nbsp;<code>admin</code>&#8195;<em>Password</em>:&nbsp;<code>admin</code></p></li></ul><p>Hit&nbsp;<em>Connections &#8594; Data Sources &#8594; Add&nbsp;new data source</em> and select each</p><ul><li><p><strong>Prometheus</strong>&nbsp;url &#8594; <em>http://prometheus:9090</em></p></li><li><p><strong>Loki</strong>&nbsp;url &#8594; <em>http://loki:3100</em></p></li><li><p><strong>Jaeger</strong>&nbsp;url &#8594; <em>http://jaeger:16686</em></p></li></ul><h3>6.2 Quick Dashboards</h3><p><strong>Metrics panel:</strong> Choose the Prometheus data source with below query.</p><pre><code>rate(tiny_hits_total[1m])
</code></pre><p><strong>Logs panel:</strong> Choose the Loki data source with below query.</p><pre><code>{service_name="tiny-observability-stack-tiny-app-1"}</code></pre><p><strong>Traces panel:</strong> Choose the Jaeger data source and click &#8220;Search&#8221; pick&nbsp;<code>tiny-app</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NPwE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NPwE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png 424w, https://substackcdn.com/image/fetch/$s_!NPwE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png 848w, https://substackcdn.com/image/fetch/$s_!NPwE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png 1272w, https://substackcdn.com/image/fetch/$s_!NPwE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NPwE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png" width="2000" height="1808" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1808,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" title="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" srcset="https://substackcdn.com/image/fetch/$s_!NPwE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png 424w, https://substackcdn.com/image/fetch/$s_!NPwE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png 848w, https://substackcdn.com/image/fetch/$s_!NPwE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png 1272w, https://substackcdn.com/image/fetch/$s_!NPwE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21cfa674-3324-482e-bad6-ab86f349ad20_2828x2556.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Three pillars, one pane of glass.</em></figcaption></figure></div><h3>6.3 Alert in Action</h3><p>Keep hammering&nbsp;<code>/hello</code>&nbsp;(e.g.,&nbsp;<code>ab</code>&nbsp;above). When&nbsp;<code>rate(demo_hits_total)</code>&nbsp;exceeds <strong>5 RPS</strong>&nbsp;for &gt;&#8239;1&#8239;minute, Prometheus fires&nbsp;<strong>HighRequestRate</strong>. Check:</p><pre><code>docker compose logs alert-logger
</code></pre><p>You should see a POST with JSON alert payload &#128079;.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!o5ow!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!o5ow!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png 424w, https://substackcdn.com/image/fetch/$s_!o5ow!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png 848w, https://substackcdn.com/image/fetch/$s_!o5ow!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png 1272w, https://substackcdn.com/image/fetch/$s_!o5ow!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!o5ow!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png" width="2000" height="1549" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1549,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" title="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" srcset="https://substackcdn.com/image/fetch/$s_!o5ow!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png 424w, https://substackcdn.com/image/fetch/$s_!o5ow!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png 848w, https://substackcdn.com/image/fetch/$s_!o5ow!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png 1272w, https://substackcdn.com/image/fetch/$s_!o5ow!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32718e23-2895-4b66-baf4-aa6188a0b6ae_2000x1549.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Grafana also lists it under <em>Alerting &#8594; Alert rules</em>. (Feel free to wire Alertmanager to Slack/email later.)</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Tj19!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Tj19!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png 424w, https://substackcdn.com/image/fetch/$s_!Tj19!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png 848w, https://substackcdn.com/image/fetch/$s_!Tj19!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png 1272w, https://substackcdn.com/image/fetch/$s_!Tj19!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Tj19!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png" width="2000" height="1126" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1126,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" title="Building&#8239;Your&#8239;First&#8239;Observability&#8239;Stack&#8239;with&#8239;Open&#8209;Source&#8239;Tools" srcset="https://substackcdn.com/image/fetch/$s_!Tj19!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png 424w, https://substackcdn.com/image/fetch/$s_!Tj19!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png 848w, https://substackcdn.com/image/fetch/$s_!Tj19!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png 1272w, https://substackcdn.com/image/fetch/$s_!Tj19!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c2338c0-0f49-4fca-97b0-ba22c7edb797_2000x1126.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2>7&#8239;&#8211;&#8239;Under the Hood: What Just Happened?</h2><ul><li><p><strong>OpenTelemetry Java agent</strong>&nbsp;auto&#8209;instrumented Javalin, captured HTTP spans, and exported via OTLP &#8594; <strong>Jaeger</strong>.</p></li><li><p><strong>Micrometer</strong>&nbsp;registers&nbsp;<code>/metrics</code>, <strong>Prometheus</strong> pulls every 15&#8239;s.</p></li><li><p><strong>Promtail</strong>&nbsp;tails container stdout, ships to Loki.</p></li><li><p><strong>Grafana</strong> unifies everything, and&nbsp;Prometheus<strong> Alertmanager</strong>&nbsp;paged us.</p></li></ul><div><hr></div><h2>8&#8239;&#8211;&#8239;Where to Go from Here<br></h2><p><strong>Next Step | Why it&#8217;s Cool  | Link</strong> <br>Create a&nbsp;<strong>service map</strong>&nbsp;in Grafana with Tempo traces | See cross&#8209;service flow | <a href="https://grafana.com/docs/tempo/latest/?ref=observability.how">Tempo docs</a> <br>Add&nbsp;<strong>Prometheus remote&#8209;write</strong>&nbsp;to a cloud TSDB for long&#8209;term storage | Keep metrics for &gt;30&#8239;days | <a href="https://prometheus.io/docs/introduction/overview/?ref=observability.how">Prometheus docs</a> <br>Enable&nbsp;<strong>Loki ruler</strong>&nbsp;for log&#8209;based alerts | Catch error patterns | <a href="https://grafana.com/docs/loki/latest/alert/?ref=observability.how">Loki alerts</a> <br>Try&nbsp;<strong>Grafana k6</strong>&nbsp;to load&#8209;test and visualize in same stack | Unified perf testing | <a href="https://grafana.com/docs/k6/latest/?ref=observability.how">k6 docs</a> <br>Swap&nbsp;<strong>Docker</strong>&nbsp;for&nbsp;<strong>Kubernetes</strong>&nbsp;| Closer to prod reality | e.g. <a href="https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack?ref=observability.how">kube-prometheus-stack</a></p><div><hr></div><h2>9&#8239;&#8211;&#8239;Wrap&#8209;Up</h2><p>You just:</p><ol><li><p>Built a tiny Java service</p></li><li><p>Containerized it with auto&#8209;instrumentation</p></li><li><p>Launched Prometheus&#8239;+&#8239;Alertmanager, Loki&#8239;+&#8239;Promtail, Jaeger, and Grafana in one shot</p></li><li><p>Watched live metrics, logs, traces, and an alert&#8212;<strong>all open source, no credit card, ~200&#8239;lines of YAML</strong>.</p></li></ol><p>Pat yourself on the back &#128079;. From here, you can iterate: add more apps, define SLOs, integrate CI/CD. Remember: observability isn&#8217;t a destination; it&#8217;s a practice. But now you&#8217;ve got a solid&nbsp;<em>starter toolbox</em>&#8212;happy hacking!</p><div><hr></div><p><strong>Source code:</strong>&nbsp;<a href="https://github.com/ObservabilityHow/tiny-observability-stack?ref=observability.how">https://github.com/ObservabilityHow/tiny-observability-stack</a></p>]]></content:encoded></item><item><title><![CDATA[Using the OpenTelemetry Collector: A Practical Guide]]></title><description><![CDATA[OpenTelemetry&#8217;s Collector is a vendor-neutral service that sits between your applications and observability backends.]]></description><link>https://www.observability.how/p/using-the-opentelemetry-collector-a-practical-guide</link><guid isPermaLink="false">https://www.observability.how/p/using-the-opentelemetry-collector-a-practical-guide</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Thu, 17 Apr 2025 07:56:28 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d5151a4d-0495-4388-9617-364ce63da4e5_1996x1192.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8XlL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8XlL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png 424w, https://substackcdn.com/image/fetch/$s_!8XlL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png 848w, https://substackcdn.com/image/fetch/$s_!8XlL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png 1272w, https://substackcdn.com/image/fetch/$s_!8XlL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8XlL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Using the OpenTelemetry Collector: A Practical Guide&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Using the OpenTelemetry Collector: A Practical Guide" title="Using the OpenTelemetry Collector: A Practical Guide" srcset="https://substackcdn.com/image/fetch/$s_!8XlL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png 424w, https://substackcdn.com/image/fetch/$s_!8XlL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png 848w, https://substackcdn.com/image/fetch/$s_!8XlL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png 1272w, https://substackcdn.com/image/fetch/$s_!8XlL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bfb17d9-6817-424e-9988-8c5dc557f873_1996x1192.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>OpenTelemetry&#8217;s Collector is a vendor-neutral service that sits between your applications and observability backends. It can receive telemetry data (traces, metrics, logs), process or transform it, and export it to one or multiple destinations. In a production environment, the Collector becomes essential for building a&nbsp;<strong>flexible and resilient observability pipeline</strong>. Rather than having your apps send data directly to a vendor, you send it to the Collector. This decouples your instrumentation from any specific backend, helping prevent vendor lock-in. It also enables powerful features like&nbsp;<strong>batching and retrying exports</strong>&nbsp;to handle network glitches, ensuring reliable delivery of telemetry even during outages. The Collector can filter sensitive information (e.g. removing API keys in traces) before it leaves your environment, improving security compliance. By consolidating traces, metrics, and logs through one pipeline, it reduces the need for multiple agents and lowers complexity. In short, the OpenTelemetry Collector is&nbsp;<strong>essential for production-grade observability</strong>&nbsp;because it provides flexibility, reliability, and control over your telemetry data.</p><p></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;af876ebd-ff7b-4134-9ebd-97d813026fdf&quot;,&quot;caption&quot;:&quot;OpenTelemetry (OTel) has quickly become a cornerstone of modern observability. If you&#8217;re a developer or engineer looking to instrument your applications for better insight, this beginner&#8217;s guide is for you. I&#8217;ll explain what OpenTelemetry is, why it matters, and walk through a step-by-step tutorial to instrument a simple Java app with basic traces and m&#8230;&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Getting Started with OpenTelemetry (OTel 101)&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-14T23:52:17.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49466716-1518-43e8-bb40-da1c66482077_1972x692.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/getting-started-with-opentelemetry-otel-101&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843149,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p></p><h2>What is the OpenTelemetry Collector?</h2><p>At its core, the OpenTelemetry Collector is a standalone service (available as a binary or container) that receives telemetry data, optionally processes it, and exports it to backends for storage and analysis. Think of it as a smart relay for your telemetry. Instead of instrumented applications each talking directly to an observability platform, they can all talk to the Collector using standard protocols. The Collector then takes on the heavy lifting of&nbsp;<strong>format translation, buffering, batching, and retrying</strong>, so your apps remain lightweight. This design leads to a more robust system: you can update or reconfigure how data is processed and where it&#8217;s sent without touching application code &#8211; only the Collector&#8217;s config needs to change. It&#8217;s also&nbsp;<strong>extensible</strong>&nbsp;and supports many data sources and destinations out-of-the-box, making it a one-stop component for telemetry management. In the sections below, we&#8217;ll dive into the Collector&#8217;s architecture, how to configure it to send data to a vendor (using <a href="https://newrelic.com/?ref=observability.how">New Relic</a> as an example), how to deploy it on Kubernetes, and best practices to run it in production.</p><div><hr></div><h2>Architecture Overview</h2><p>The OpenTelemetry Collector&#8217;s architecture is pipeline-based. Each&nbsp;<strong>pipeline</strong>&nbsp;defines a path that telemetry data follows through the Collector &#8211; from input to output. A pipeline is configured for a specific signal type (one for traces, one for metrics, one for logs, etc.), and it consists of three primary types of components: <strong>receivers</strong>,&nbsp;<strong>processors</strong>, and&nbsp;<strong>exporters</strong>. (There are also optional&nbsp;<em>extensions</em>&nbsp;and <em>connectors</em>, which we&#8217;ll briefly touch on.)</p><p>To visualize this, consider the following flow: an application emits telemetry which is ingested by a receiver; it then passes through one or more processors for enrichment or batching; finally, an exporter sends the processed data out to a backend.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-hME!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-hME!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png 424w, https://substackcdn.com/image/fetch/$s_!-hME!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png 848w, https://substackcdn.com/image/fetch/$s_!-hME!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png 1272w, https://substackcdn.com/image/fetch/$s_!-hME!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-hME!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png" width="1022" height="439" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:439,&quot;width&quot;:1022,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Using the OpenTelemetry Collector: A Practical Guide&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Using the OpenTelemetry Collector: A Practical Guide" title="Using the OpenTelemetry Collector: A Practical Guide" srcset="https://substackcdn.com/image/fetch/$s_!-hME!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png 424w, https://substackcdn.com/image/fetch/$s_!-hME!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png 848w, https://substackcdn.com/image/fetch/$s_!-hME!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png 1272w, https://substackcdn.com/image/fetch/$s_!-hME!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85e49b1b-4ac0-41eb-abc1-7a15429491b3_1022x439.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The diagram above shows a simplified view of the Collector pipeline: data from sources enters via receivers, flows through processors, and exits via exporters to your backends (extensions provide additional capabilities outside the main data flow).</em></figcaption></figure></div><h3>Receivers</h3><p><strong>Receivers</strong>&nbsp;are the entry point of telemetry into the Collector. They &#8220;receive&#8221; data in various formats and protocols from your applications or other collectors. For example, an OTLP receiver opens endpoints to collect spans, metrics, and logs from OpenTelemetry SDKs, while other receivers can ingest data from sources like Jaeger, Prometheus, Zipkin, FluentBit, etc.&nbsp;You can configure multiple receivers if you need to gather data from different sources. Many receivers support default settings &#8211; for instance, simply enabling the&nbsp;otlp&nbsp;receiver will by default start gRPC (on port 4317) and HTTP (on port 4318) endpoints for OTLP data. (These are the standard OpenTelemetry Protocol ports for traces/metrics over gRPC and HTTP.) Receivers might accept one or more signal types; the OTLP receiver, for example, can ingest traces, metrics, and logs in one go. In a Collector config, receivers are listed under a top-level&nbsp;<code>receivers:</code>&nbsp;section, and you&#8217;ll later tie them into pipelines.</p><h3>Processors</h3><p>After data enters via a receiver, it can pass through&nbsp;<strong>processors</strong>. Processors are optional components that can transform or enhance telemetry before it&#8217;s exported. They can filter out noisy data, mask sensitive fields, add contextual information, or even sample (reduce) traces to control volume. For example, a&nbsp;filter&nbsp;processor might drop certain spans by name, or a&nbsp;<a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/a188a4cd3a75adbdaf3e26c7322a31489a3bb2b4/processor/resourcedetectionprocessor/README.md?ref=observability.how">resourcedetection&nbsp;processor</a> can attach metadata (like cloud region or Kubernetes pod info) to each span/metric. One <strong>crucial processor for production</strong>&nbsp;is the<em>&nbsp;batch&nbsp;</em>processor, which groups telemetry data into batches to send in one go &#8211; this greatly improves throughput and reduces CPU/network overhead. Another important one is the <em>memory_limiter</em>, which prevents the Collector from running out of memory by monitoring usage and applying backpressure if needed. Processors can be chained in sequence; the data flows through each processor in order. It&#8217;s common to include at least a batch processor in every pipeline for efficiency (by default, no processors are active unless you configure them). In your config file, you list processors under&nbsp;<code>processors:</code>&nbsp;and later reference them in pipeline definitions.</p><h3>Exporters</h3><p><strong>Exporters</strong>&nbsp;are the components that send processed telemetry to your chosen destinations (backends or other systems). An exporter knows how to take the Collector&#8217;s internal data and transmit it over a specific protocol to an external service. For example, the&nbsp;otlp&nbsp;exporter can send data to any OTLP-compatible backend (like New Relic&#8217;s <a href="https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp/?ref=observability.how#configure-endpoint-port-protocol">ingest endpoint</a>) using gRPC or HTTP. There are many exporters available &#8211; for logging you might use a&nbsp;logging&nbsp;exporter to print data, or exporters for systems like Jaeger, Prometheus, AWS X-Ray, etc.&nbsp;You can even export to local files or databases if needed. In our case (exporting to New Relic), we will use the OTLP exporter because New Relic accepts OTLP data. An important aspect is that you can attach&nbsp;<strong>multiple exporters</strong>&nbsp;to the same pipeline if you want to send data to more than one backend simultaneously (e.g., to send traces to both New Relic and an on-premise Jaeger). Each exporter goes under the&nbsp;<code>exporters:</code> section in config, and like receivers and processors, they will be referenced in the pipeline configuration.</p><h3>Pipelines</h3><p>A&nbsp;<strong>pipeline</strong>&nbsp;ties together a set of receivers, an ordered list of processors, and a set of exporters for one telemetry signal. In the Collector&#8217;s config, pipelines are defined under the&nbsp;<code>service:</code>&nbsp;section. For example, you might define a&nbsp;traces&nbsp;pipeline that uses the OTLP receiver, some processors (batch, etc.), and the OTLP exporter. This means: &#8220;receive all incoming traces from OTLP, process them (batch them, maybe filter), and export via OTLP protocol to the backend.&#8221; Each pipeline is dedicated to one data type (traces, metrics, or logs)&nbsp;&#8211; you will typically have one pipeline for each type you plan to use. If a component (receiver/processor/exporter) doesn&#8217;t support a certain data type, it cannot be included in that pipeline. Also note: if you define a component in the config but don&#8217;t include it in any pipeline (or enable it in&nbsp;service), it will be ignored. Below, we&#8217;ll see an example configuration that defines pipelines for all three signals.</p><h3>Extensions and Connectors</h3><p>The Collector also supports&nbsp;<strong>extensions</strong>&nbsp;&#8211; add-ons that run alongside pipelines to provide extra functionality like health check endpoints, authentication, or pprof profiling &#8211; and&nbsp;<strong>connectors</strong>, which link pipelines together for advanced routing or stream splitting. These are beyond the scope of this guide, but be aware they exist for more complex scenarios.</p><div><hr></div><h2><strong>Configuring the Collector to Receive and Export Telemetry</strong></h2><p>Configuring the OpenTelemetry Collector is done via a YAML file. The configuration has top-level sections for&nbsp;receivers,&nbsp;processors,&nbsp;exporters,&nbsp;extensions&nbsp;(optional), and&nbsp;service&nbsp;(which defines pipelines). Let&#8217;s walk through how to set up the Collector to receive traces, metrics, and logs and forward them to an OTLP-compatible backend. We&#8217;ll use&nbsp;<strong>New Relic</strong>&nbsp;as the example backend &#8211; which supports OTLP ingestion &#8211; so our goal is to receive OTLP data from apps and export it to New Relic&#8217;s endpoint.</p><h3>Receiver Configuration</h3><p>Since our applications are instrumented with OpenTelemetry SDKs, the simplest approach is to use the&nbsp;<strong>OTLP receiver</strong>&nbsp;on the Collector. This will allow the Collector to accept OTLP-formatted spans, metrics, and logs over gRPC or HTTP. By default, enabling the&nbsp;otlp&nbsp;receiver without additional config will open a gRPC port on 4317 and HTTP port on 4318 on all interfaces. We can explicitly specify protocols and addresses if needed. In most cases, the defaults are fine unless you have port conflicts or want to restrict to localhost. For example, to only enable HTTP, you could configure:</p><pre><code>receivers:
  otlp:
    protocols:
      http:
      # grpc:  # (you could disable gRPC by omitting it)</code></pre><p><em>(In YAML, leaving&nbsp;http:&nbsp;empty under protocols means use the default bind address&nbsp;0.0.0.0:4318. Similarly,&nbsp;grpc:&nbsp;would default to&nbsp;0.0.0.0:4317.)</em></p><p>This&nbsp;otlp&nbsp;receiver will accept&nbsp;<strong>traces, metrics, and logs</strong>&nbsp;from your apps as long as they export via OTLP. Ensure your application SDKs are configured to send to the Collector&#8217;s address (we&#8217;ll cover examples in the Kubernetes deployment section).</p><h3>Exporter Configuration</h3><p>On the other end, we need an exporter that sends data to New Relic. New Relic&#8217;s <a href="https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp/?ref=observability.how#configure-endpoint-port-protocol">OTLP endpoint</a> is a cloud URL (otlp.nr-data.net&nbsp;for US accounts, or&nbsp;otlp.eu01.nr-data.net&nbsp;for EU, etc.) that expects OTLP data over <strong>HTTPS</strong>. We&#8217;ll use the Collector&#8217;s built-in&nbsp;otlp&nbsp;exporter for this. The key things to configure are the <strong>endpoint URL </strong>and an&nbsp;<strong>API key</strong>. New Relic requires you to include your license key as an&nbsp;api-key&nbsp;header on OTLP requests for authentication. In YAML, we can specify headers for the exporter. Here&#8217;s an example exporter config:</p><pre><code>exporters:
  otlp:
    endpoint: "https://otlp.nr-data.net:4318"    # New Relic ingest endpoint (US region, HTTP port 4318)
    headers:
      api-key: "${NEW_RELIC_LICENSE_KEY}"        # New Relic License key for auth
    compression: gzip                            # (optional) use gzip compression (default is gzip)
    timeout: 10s                                 # (optional) timeout for export requests</code></pre><p>A few notes on this exporter setup: We use the HTTPS endpoint on port 4318 which implies OTLP/HTTP. The Collector will automatically append the correct path (/v1/traces,&nbsp;/v1/metrics, etc.) for each data type when sending. We include the&nbsp;api-key&nbsp;header with our New Relic license key &#8211; in practice you&#8217;d set&nbsp;NEW_RELIC_LICENSE_KEY&nbsp;as an environment variable or Kubernetes secret so it&#8217;s not in plain text. We also enabled gzip compression (which is actually the Collector&#8217;s default compression setting) to reduce payload sizes, and set a 10 second timeout for export HTTP calls (the default is 5s; adjusting it can help if network latency is high).</p><h3>Processor Configuration</h3><p>To make our pipeline production-ready, we should include a couple of processors. The most common is the&nbsp;<em>batch</em>&nbsp;processor. Batching accumulates telemetry data and sends it in chunks (either after a certain size or time interval), which significantly improves export efficiency. Without batching, the Collector would try to send every span or metric as a separate request, which is not ideal. We&#8217;ll use default batch settings or tweak them as needed. Another highly recommended processor is&nbsp;<em>memory_limiter</em>, which prevents the Collector from using unlimited memory. It checks memory usage periodically and will refuse new data (applying backpressure) if the Collector exceeds certain thresholds. This way, if the backend is down or slow and data backs up, the Collector won&#8217;t just eat all memory &#8211; it will signal to clients to retry later (which the OpenTelemetry SDKs do automatically with exponential backoff). We can configure&nbsp;memory_limiter&nbsp;with a limit relative to the container&#8217;s memory. For example, if we give the Collector 512 MiB of RAM in Kubernetes, we might set limit to ~400 MiB and a spike allowance of 100 MiB.</p><p>Our processors config might look like:</p><pre><code>processors:
  batch:
    send_batch_size: 1024           # number of spans/metrics per batch (example)
    timeout: 5s                     # send every 5s if batch not filled
  memory_limiter:
    check_interval: 1s
    limit_mib: 400                  # hard limit ~400 MiB
    spike_limit_mib: 100            # extra allowance for spikes</code></pre><p>The above&nbsp;batch&nbsp;config is just an example; often the default batch settings (like 8192 spans or 200ms timeout) are fine, but you can tune as needed. For&nbsp;memory_limiter, when memory usage goes beyond (limit - spike), the Collector starts refusing new data until memory is freed. This triggers client SDK retries (or data drop if the client doesn&#8217;t retry). In practice, the OTLP exporters in the SDK will retry by default on receiving a retryable error, so this mechanism helps throttle to avoid crash while signaling upstream to slow down.</p><h3>Putting It Together</h3><p>Now let&#8217;s combine these into a full Collector configuration that covers&nbsp;<strong>traces, metrics, and logs</strong>. In one YAML file, we&#8217;ll define our receiver(s), processors, exporter(s), then configure pipelines for each signal type. Below is a sample&nbsp;collector-config.yaml:</p><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569245\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-collector-config-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;collector-config.yaml content, created by jigarkb on 07:43AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;collector-config.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>receivers</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>otlp</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>protocols</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>http</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>grpc</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>processors</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>batch</span>: <span class=\&quot;pl-s\&quot;>{}</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>memory_limiter</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>check_interval</span>: <span class=\&quot;pl-c1\&quot;>5s</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>limit_mib</span>: <span class=\&quot;pl-c1\&quot;>400</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>spike_limit_mib</span>: <span class=\&quot;pl-c1\&quot;>100</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>exporters</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>otlp</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>endpoint</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>https://otlp.nr-data.net:4318<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>headers</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>api-key</span>: <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>${NEW_RELIC_LICENSE_KEY}<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>compression</span>: <span class=\&quot;pl-s\&quot;>gzip</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>timeout</span>: <span class=\&quot;pl-c1\&quot;>10s</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>service</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>pipelines</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>traces</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>receivers</span>: <span class=\&quot;pl-s\&quot;>[otlp]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>processors</span>: <span class=\&quot;pl-s\&quot;>[memory_limiter, batch]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>exporters</span>: <span class=\&quot;pl-s\&quot;>[otlp]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>metrics</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>receivers</span>: <span class=\&quot;pl-s\&quot;>[otlp]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>processors</span>: <span class=\&quot;pl-s\&quot;>[memory_limiter, batch]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>exporters</span>: <span class=\&quot;pl-s\&quot;>[otlp]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>logs</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>receivers</span>: <span class=\&quot;pl-s\&quot;>[otlp]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L34\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;34\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC34\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>processors</span>: <span class=\&quot;pl-s\&quot;>[memory_limiter, batch]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-config-yaml-L35\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;35\&quot;></td>\n          <td id=\&quot;file-collector-config-yaml-LC35\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>exporters</span>: <span class=\&quot;pl-s\&quot;>[otlp]</span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/ee690549f2ff44d706fcb864acaed990/raw/1ef2685599309202e34c0c4508e3706a7d23d155/collector-config.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/ee690549f2ff44d706fcb864acaed990#file-collector-config-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          collector-config.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569245" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-collector-config-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="collector-config.yaml">
        <tbody><tr>
          <td id="file-collector-config-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-collector-config-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">receivers</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-collector-config-yaml-LC2" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">otlp</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-collector-config-yaml-LC3" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">protocols</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-collector-config-yaml-LC4" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">http</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-collector-config-yaml-LC5" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">grpc</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-collector-config-yaml-LC6" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-collector-config-yaml-LC7" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">processors</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-collector-config-yaml-LC8" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">batch</span>: <span class="pl-s">{}</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-collector-config-yaml-LC9" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">memory_limiter</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-collector-config-yaml-LC10" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">check_interval</span>: <span class="pl-c1">5s</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-collector-config-yaml-LC11" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">limit_mib</span>: <span class="pl-c1">400</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-collector-config-yaml-LC12" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">spike_limit_mib</span>: <span class="pl-c1">100</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-collector-config-yaml-LC13" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-collector-config-yaml-LC14" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">exporters</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-collector-config-yaml-LC15" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">otlp</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-collector-config-yaml-LC16" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">endpoint</span>: <span class="pl-s"><span class="pl-pds">"</span>https://otlp.nr-data.net:4318<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-collector-config-yaml-LC17" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">headers</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-collector-config-yaml-LC18" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">api-key</span>: <span class="pl-s"><span class="pl-pds">"</span>${NEW_RELIC_LICENSE_KEY}<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-collector-config-yaml-LC19" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">compression</span>: <span class="pl-s">gzip</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-collector-config-yaml-LC20" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">timeout</span>: <span class="pl-c1">10s</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-collector-config-yaml-LC21" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-collector-config-yaml-LC22" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">service</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-collector-config-yaml-LC23" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">pipelines</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-collector-config-yaml-LC24" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">traces</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-collector-config-yaml-LC25" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">receivers</span>: <span class="pl-s">[otlp]</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-collector-config-yaml-LC26" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">processors</span>: <span class="pl-s">[memory_limiter, batch]</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-collector-config-yaml-LC27" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">exporters</span>: <span class="pl-s">[otlp]</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-collector-config-yaml-LC28" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">metrics</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-collector-config-yaml-LC29" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">receivers</span>: <span class="pl-s">[otlp]</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-collector-config-yaml-LC30" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">processors</span>: <span class="pl-s">[memory_limiter, batch]</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-collector-config-yaml-LC31" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">exporters</span>: <span class="pl-s">[otlp]</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-collector-config-yaml-LC32" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">logs</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-collector-config-yaml-LC33" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">receivers</span>: <span class="pl-s">[otlp]</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-collector-config-yaml-LC34" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">processors</span>: <span class="pl-s">[memory_limiter, batch]</span></td>
        </tr>
        <tr>
          <td id="file-collector-config-yaml-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-collector-config-yaml-LC35" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">exporters</span>: <span class="pl-s">[otlp]</span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/ee690549f2ff44d706fcb864acaed990/raw/1ef2685599309202e34c0c4508e3706a7d23d155/collector-config.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/ee690549f2ff44d706fcb864acaed990#file-collector-config-yaml" class="Link--inTextBlock">
          collector-config.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><p>Under&nbsp;<code>service:pipelines</code>, we defined three pipelines: one for&nbsp;traces, one for&nbsp;metrics, one for&nbsp;logs. In each, we list the components it uses. Here all three pipelines use the same receiver (otlp), same processors (memory_limiter, batch), and the same exporter (otlp). This effectively routes&nbsp;<strong>all</strong>&nbsp;incoming telemetry to New Relic with memory protection and batching in place.</p><p>You can of course customize this. For instance, you might only want to collect traces and metrics but not logs &#8211; then you could omit the logs pipeline and even disable log reception on the OTLP receiver. Or if you wanted to send metrics to a different backend (say, <a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/a188a4cd3a75adbdaf3e26c7322a31489a3bb2b4/exporter/prometheusremotewriteexporter/README.md?ref=observability.how">Prometheus remote write</a>) and traces to New Relic, you&#8217;d configure two exporters and use each in the respective pipeline. The Collector&#8217;s config is very flexible.</p><p><strong>Verifying the Config:</strong>&nbsp;Once you have your YAML, you can run the Collector locally to test it. For example, using the official Docker image:</p><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569253\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-collector-run-sh\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-shell  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;collector-run.sh content, created by jigarkb on 07:44AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;collector-run.sh\&quot;>\n        <tr>\n          <td id=\&quot;file-collector-run-sh-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-collector-run-sh-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>docker run -p 4318:4318 -p 4317:4317 \\</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-run-sh-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-collector-run-sh-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  -v <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span><span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>$(</span>pwd<span class=\&quot;pl-pds\&quot;>)</span></span>/collector-config.yaml<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span>:/etc/otel-config.yaml \\</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-run-sh-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-collector-run-sh-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  otel/opentelemetry-collector:latest \\</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-run-sh-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-collector-run-sh-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  --config=/etc/otel-config.yaml</td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/681d6af774994bf07df8d8873763ae9f/raw/ae88e07fc69ca3e593bd7cf90bcfcc46e1ccee9f/collector-run.sh\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/681d6af774994bf07df8d8873763ae9f#file-collector-run-sh\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          collector-run.sh\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569253" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-collector-run-sh" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-shell  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="collector-run.sh">
        <tbody><tr>
          <td id="file-collector-run-sh-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-collector-run-sh-LC1" class="blob-code blob-code-inner js-file-line">docker run -p 4318:4318 -p 4317:4317 \</td>
        </tr>
        <tr>
          <td id="file-collector-run-sh-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-collector-run-sh-LC2" class="blob-code blob-code-inner js-file-line">  -v <span class="pl-s"><span class="pl-pds">"</span><span class="pl-s"><span class="pl-pds">$(</span>pwd<span class="pl-pds">)</span></span>/collector-config.yaml<span class="pl-pds">"</span></span>:/etc/otel-config.yaml \</td>
        </tr>
        <tr>
          <td id="file-collector-run-sh-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-collector-run-sh-LC3" class="blob-code blob-code-inner js-file-line">  otel/opentelemetry-collector:latest \</td>
        </tr>
        <tr>
          <td id="file-collector-run-sh-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-collector-run-sh-LC4" class="blob-code blob-code-inner js-file-line">  --config=/etc/otel-config.yaml</td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/681d6af774994bf07df8d8873763ae9f/raw/ae88e07fc69ca3e593bd7cf90bcfcc46e1ccee9f/collector-run.sh" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/681d6af774994bf07df8d8873763ae9f#file-collector-run-sh" class="Link--inTextBlock">
          collector-run.sh
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><p>This would start the Collector, and you could point a test application&#8217;s OTLP exporter to&nbsp;localhost:4318&nbsp;and see if data shows up in New Relic. The Collector logs will also indicate if it&#8217;s receiving data or encountering errors. In production, you&#8217;d likely run the Collector as a service or sidecar &#8211; which leads us to deployment models, especially in Kubernetes.</p><div><hr></div><h2><strong>Deploying the Collector in Kubernetes: Sidecar/Agent vs Gateway</strong></h2><p>When running on Kubernetes, the OpenTelemetry Collector can be deployed in two common patterns: as an&nbsp;<strong>agent</strong>&nbsp;(close to your application pods, often a sidecar or a daemonset on each node), or as a&nbsp;<strong>gateway</strong>&nbsp;(a centralized service within the cluster). Choosing the right model (or using a hybrid of both) will impact the network architecture of your telemetry data. Let&#8217;s explain each:</p><h3><strong>Agent Deployment (Sidecar or DaemonSet)</strong></h3><p>In the agent model, you run a Collector alongside your application instances to collect data locally. &#8220;Sidecar&#8221; means adding a Collector container to your application&#8217;s Pod, whereas &#8220;DaemonSet&#8221; means a Collector pod runs on every node (collecting for all apps on that node). In both cases, the Collector is&nbsp;<strong>co-located</strong>&nbsp;with the application processes. The advantage is that telemetry is sent over localhost or node-local network, which is faster and more reliable (no extra network hop). This also makes it easier to tag telemetry with host-specific metadata (like Kubernetes pod or node info) using processors, since the Collector has visibility into the local environment. Essentially, the agent pattern brings the Collector&nbsp;<em>to where the data is</em>.</p><p>In Kubernetes, the&nbsp;<strong>DaemonSet</strong>&nbsp;approach is very popular for OpenTelemetry: you deploy a DaemonSet so that each Kubernetes node runs one Collector instance. All apps on that node can be configured to send to&nbsp;localhost:&lt;port&gt;&nbsp;(or host IP) where the agent is listening. This avoids running one Collector per app, which could be wasteful if you have many microservices. (It&#8217;s still a valid approach to use sidecars, especially if different services need very different Collector configurations, but a DaemonSet tends to be simpler to manage overall.) New Relic&#8217;s <a href="https://docs.newrelic.com/docs/kubernetes-pixie/kubernetes-integration/advanced-configuration/link-otel-applications-kubernetes/?ref=observability.how#configure-otel-collector">documentation</a>, for example, recommends deploying the Collector as an agent on every node to receive telemetry locally.</p><p><strong>How to deploy as a DaemonSet:</strong>&nbsp;You would create a DaemonSet manifest for the Collector. This is similar to deploying any other DaemonSet: each pod will run the Collector container with your config mounted. For instance, a simplified example manifest:</p><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569273\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-collector-agent-daemonset-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;collector-agent-daemonset.yaml content, created by jigarkb on 07:45AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;collector-agent-daemonset.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>apiVersion</span>: <span class=\&quot;pl-s\&quot;>apps/v1</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>kind</span>: <span class=\&quot;pl-s\&quot;>DaemonSet</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>metadata</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-collector-agent</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>spec</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>selector</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>matchLabels</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>app</span>: <span class=\&quot;pl-s\&quot;>otel-collector-agent</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>template</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>metadata</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>labels</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>app</span>: <span class=\&quot;pl-s\&quot;>otel-collector-agent</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>spec</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>containers</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-collector</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>otel/opentelemetry-collector-contrib:latest</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>args</span>: <span class=\&quot;pl-s\&quot;>[&amp;quot;--config=/etc/otel-config.yaml&amp;quot;]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        - <span class=\&quot;pl-ent\&quot;>containerPort</span>: <span class=\&quot;pl-c1\&quot;>4318</span>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> HTTP OTLP</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        - <span class=\&quot;pl-ent\&quot;>containerPort</span>: <span class=\&quot;pl-c1\&quot;>4317</span>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> gRPC OTLP</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>volumeMounts</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-config-vol</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>mountPath</span>: <span class=\&quot;pl-s\&quot;>/etc/otel-config.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>subPath</span>: <span class=\&quot;pl-s\&quot;>config.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>volumes</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-config-vol</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>configMap</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-collector-config  </span><span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> ConfigMap containing your collector YAML</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> optionally, define resource limits:</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> resources:</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span>   limits:</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span>     cpu: 200m</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span>     memory: 512Mi</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L34\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;34\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC34\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span>   requests:</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L35\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;35\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC35\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span>     cpu: 50m</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-L36\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;36\&quot;></td>\n          <td id=\&quot;file-collector-agent-daemonset-yaml-LC36\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span>     memory: 128Mi</span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/a7278708b8ca4b01d6660077a957ea70/raw/49c57d460b83f4ca03722786d38c2f25da6f2317/collector-agent-daemonset.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/a7278708b8ca4b01d6660077a957ea70#file-collector-agent-daemonset-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          collector-agent-daemonset.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569273" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-collector-agent-daemonset-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="collector-agent-daemonset.yaml">
        <tbody><tr>
          <td id="file-collector-agent-daemonset-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-collector-agent-daemonset-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">apiVersion</span>: <span class="pl-s">apps/v1</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-collector-agent-daemonset-yaml-LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">kind</span>: <span class="pl-s">DaemonSet</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-collector-agent-daemonset-yaml-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">metadata</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-collector-agent-daemonset-yaml-LC4" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">name</span>: <span class="pl-s">otel-collector-agent</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-collector-agent-daemonset-yaml-LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">spec</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-collector-agent-daemonset-yaml-LC6" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">selector</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-collector-agent-daemonset-yaml-LC7" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">matchLabels</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-collector-agent-daemonset-yaml-LC8" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">app</span>: <span class="pl-s">otel-collector-agent</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-collector-agent-daemonset-yaml-LC9" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">template</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-collector-agent-daemonset-yaml-LC10" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">metadata</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-collector-agent-daemonset-yaml-LC11" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">labels</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-collector-agent-daemonset-yaml-LC12" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">app</span>: <span class="pl-s">otel-collector-agent</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-collector-agent-daemonset-yaml-LC13" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">spec</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-collector-agent-daemonset-yaml-LC14" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">containers</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-collector-agent-daemonset-yaml-LC15" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">name</span>: <span class="pl-s">otel-collector</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-collector-agent-daemonset-yaml-LC16" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">image</span>: <span class="pl-s">otel/opentelemetry-collector-contrib:latest</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-collector-agent-daemonset-yaml-LC17" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">args</span>: <span class="pl-s">["--config=/etc/otel-config.yaml"]</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-collector-agent-daemonset-yaml-LC18" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-collector-agent-daemonset-yaml-LC19" class="blob-code blob-code-inner js-file-line">        - <span class="pl-ent">containerPort</span>: <span class="pl-c1">4318</span>  <span class="pl-c"><span class="pl-c">#</span> HTTP OTLP</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-collector-agent-daemonset-yaml-LC20" class="blob-code blob-code-inner js-file-line">        - <span class="pl-ent">containerPort</span>: <span class="pl-c1">4317</span>  <span class="pl-c"><span class="pl-c">#</span> gRPC OTLP</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-collector-agent-daemonset-yaml-LC21" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">volumeMounts</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-collector-agent-daemonset-yaml-LC22" class="blob-code blob-code-inner js-file-line">        - <span class="pl-ent">name</span>: <span class="pl-s">otel-config-vol</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-collector-agent-daemonset-yaml-LC23" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">mountPath</span>: <span class="pl-s">/etc/otel-config.yaml</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-collector-agent-daemonset-yaml-LC24" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">subPath</span>: <span class="pl-s">config.yaml</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-collector-agent-daemonset-yaml-LC25" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">volumes</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-collector-agent-daemonset-yaml-LC26" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">name</span>: <span class="pl-s">otel-config-vol</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-collector-agent-daemonset-yaml-LC27" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">configMap</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-collector-agent-daemonset-yaml-LC28" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">name</span>: <span class="pl-s">otel-collector-config  </span><span class="pl-c"><span class="pl-c">#</span> ConfigMap containing your collector YAML</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-collector-agent-daemonset-yaml-LC29" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span> optionally, define resource limits:</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-collector-agent-daemonset-yaml-LC30" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span> resources:</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-collector-agent-daemonset-yaml-LC31" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span>   limits:</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-collector-agent-daemonset-yaml-LC32" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span>     cpu: 200m</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-collector-agent-daemonset-yaml-LC33" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span>     memory: 512Mi</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-collector-agent-daemonset-yaml-LC34" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span>   requests:</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-collector-agent-daemonset-yaml-LC35" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span>     cpu: 50m</span></td>
        </tr>
        <tr>
          <td id="file-collector-agent-daemonset-yaml-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
          <td id="file-collector-agent-daemonset-yaml-LC36" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span>     memory: 128Mi</span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/a7278708b8ca4b01d6660077a957ea70/raw/49c57d460b83f4ca03722786d38c2f25da6f2317/collector-agent-daemonset.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/a7278708b8ca4b01d6660077a957ea70#file-collector-agent-daemonset-yaml" class="Link--inTextBlock">
          collector-agent-daemonset.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><p>In this manifest, we mount the config from a ConfigMap and expose ports 4317/4318. We&#8217;d also likely include a&nbsp;resourceblock to cap CPU and memory, because you want to ensure the Collector doesn&#8217;t exceed allocated resources on each node. Once this DaemonSet is running, each pod (Collector) will listen on those ports. Your application pods should then be configured to send OTLP data to the <strong>node&#8217;s address</strong>. If using environment variables in the SDK, for example:&nbsp;OTEL_EXPORTER_OTLP_ENDPOINT=http://&lt;node-ip&gt;:4318. Kubernetes downward API can inject the node IP into a pod env var (using&nbsp;status.hostIP). If using sidecar deployment instead, the app would send to&nbsp;localhost:4318&nbsp;since the Collector sidecar shares the pod network.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DDbZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DDbZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png 424w, https://substackcdn.com/image/fetch/$s_!DDbZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png 848w, https://substackcdn.com/image/fetch/$s_!DDbZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png 1272w, https://substackcdn.com/image/fetch/$s_!DDbZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DDbZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png" width="2000" height="1464" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1464,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Using the OpenTelemetry Collector: A Practical Guide&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Using the OpenTelemetry Collector: A Practical Guide" title="Using the OpenTelemetry Collector: A Practical Guide" srcset="https://substackcdn.com/image/fetch/$s_!DDbZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png 424w, https://substackcdn.com/image/fetch/$s_!DDbZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png 848w, https://substackcdn.com/image/fetch/$s_!DDbZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png 1272w, https://substackcdn.com/image/fetch/$s_!DDbZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd0346e2-3412-47a8-90ee-bc4cd3c5d4aa_2170x1588.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>OTel Collector Agent Deployment (as a DaemonSet)</em></figcaption></figure></div><p>A sidecar deployment looks similar but the Collector container is defined in the same pod spec as your app. The <a href="https://opentelemetry.io/docs/platforms/kubernetes/operator/?ref=observability.how">OpenTelemetry Operator</a> can even automate sidecar injection by annotating pods (e.g.&nbsp;<code>sidecar.opentelemetry.io/inject:true</code>), which is convenient. Sidecars are great for isolating telemetry per service, but they do mean you&#8217;ll run N collectors for N pods, so consider the resource overhead. DaemonSet (one per node) strikes a good balance between proximity and efficiency.</p><h3><strong>Gateway Deployment (Centralized Service)</strong></h3><p>In the gateway model, the Collector runs as a&nbsp;<strong>standalone service</strong>&nbsp;(one or a few pods) that aggregates telemetry from many sources. Instead of each node having a collector, you might have a deployment of 2&#8211;3 Collector replicas and all your applications send data to a single Kubernetes Service (the gateway&#8217;s address). The gateway then processes and exports the data to your backend. This pattern centralizes the telemetry pipeline. It&#8217;s useful for cluster-level data collection or when you want a single point to apply certain processing (like sampling policies or encryption of data in transit to outside) for all telemetry.</p><p>For example, you might run a&nbsp;<strong>Deployment</strong>&nbsp;of the Collector with (say) 3 replicas behind a Service&nbsp;otel-collector.my-namespace.svc:4318. All apps are configured to send to that service. The Collectors then share the load (ideally behind a load-balancer or round-robin Kubernetes Service). This is easier to manage in terms of updating config (fewer instances to update) and uses less overall resources than dozens of sidecars. However, it introduces a network hop &#8211; telemetry has to travel from the app&#8217;s node to the collector service over the network &#8211; which can add latency and potential bottlenecks. You also need to ensure the gateway is scaled enough to handle the volume (and maybe use a LoadBalancer or headless service for gRPC to distribute evenly). If not scaled, a single gateway becomes a single point of failure or throughput choke point&nbsp;.</p><p><strong>How to deploy as a Gateway:</strong>&nbsp;Typically, you create a normal Deployment for the Collector. For instance:</p><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569284\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-collector-gateway-deployment-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;collector-gateway-deployment.yaml content, created by jigarkb on 07:46AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;collector-gateway-deployment.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>apiVersion</span>: <span class=\&quot;pl-s\&quot;>apps/v1</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>kind</span>: <span class=\&quot;pl-s\&quot;>Deployment</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>metadata</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-collector-gateway</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>spec</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>replicas</span>: <span class=\&quot;pl-c1\&quot;>3</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>selector</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>matchLabels</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>app</span>: <span class=\&quot;pl-s\&quot;>otel-collector-gateway</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>template</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>metadata</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>labels</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>app</span>: <span class=\&quot;pl-s\&quot;>otel-collector-gateway</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>spec</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>containers</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-collector</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>image</span>: <span class=\&quot;pl-s\&quot;>otel/opentelemetry-collector-contrib:latest</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>args</span>: <span class=\&quot;pl-s\&quot;>[&amp;quot;--config=/etc/otel-config.yaml&amp;quot;]</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        - <span class=\&quot;pl-ent\&quot;>containerPort</span>: <span class=\&quot;pl-c1\&quot;>4318</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        - <span class=\&quot;pl-ent\&quot;>containerPort</span>: <span class=\&quot;pl-c1\&quot;>4317</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>volumeMounts</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-config-vol</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>mountPath</span>: <span class=\&quot;pl-s\&quot;>/etc/otel-config.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>subPath</span>: <span class=\&quot;pl-s\&quot;>config.yaml</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>volumes</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-config-vol</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=\&quot;pl-ent\&quot;>configMap</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>          <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-collector-config</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-collector-gateway-deployment-yaml-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> resources: (set requests/limits as appropriate)</span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/6b0978b930b23de7f1e68333d0a428e9/raw/08445e8e85d7cebd8cea778fa6da1f04a83df827/collector-gateway-deployment.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/6b0978b930b23de7f1e68333d0a428e9#file-collector-gateway-deployment-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          collector-gateway-deployment.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569284" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-collector-gateway-deployment-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="collector-gateway-deployment.yaml">
        <tbody><tr>
          <td id="file-collector-gateway-deployment-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-collector-gateway-deployment-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">apiVersion</span>: <span class="pl-s">apps/v1</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-collector-gateway-deployment-yaml-LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">kind</span>: <span class="pl-s">Deployment</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-collector-gateway-deployment-yaml-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">metadata</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-collector-gateway-deployment-yaml-LC4" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">name</span>: <span class="pl-s">otel-collector-gateway</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-collector-gateway-deployment-yaml-LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">spec</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-collector-gateway-deployment-yaml-LC6" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">replicas</span>: <span class="pl-c1">3</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-collector-gateway-deployment-yaml-LC7" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">selector</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-collector-gateway-deployment-yaml-LC8" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">matchLabels</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-collector-gateway-deployment-yaml-LC9" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">app</span>: <span class="pl-s">otel-collector-gateway</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-collector-gateway-deployment-yaml-LC10" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">template</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-collector-gateway-deployment-yaml-LC11" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">metadata</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-collector-gateway-deployment-yaml-LC12" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">labels</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-collector-gateway-deployment-yaml-LC13" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">app</span>: <span class="pl-s">otel-collector-gateway</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-collector-gateway-deployment-yaml-LC14" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">spec</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-collector-gateway-deployment-yaml-LC15" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">containers</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-collector-gateway-deployment-yaml-LC16" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">name</span>: <span class="pl-s">otel-collector</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-collector-gateway-deployment-yaml-LC17" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">image</span>: <span class="pl-s">otel/opentelemetry-collector-contrib:latest</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-collector-gateway-deployment-yaml-LC18" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">args</span>: <span class="pl-s">["--config=/etc/otel-config.yaml"]</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-collector-gateway-deployment-yaml-LC19" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-collector-gateway-deployment-yaml-LC20" class="blob-code blob-code-inner js-file-line">        - <span class="pl-ent">containerPort</span>: <span class="pl-c1">4318</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-collector-gateway-deployment-yaml-LC21" class="blob-code blob-code-inner js-file-line">        - <span class="pl-ent">containerPort</span>: <span class="pl-c1">4317</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-collector-gateway-deployment-yaml-LC22" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">volumeMounts</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-collector-gateway-deployment-yaml-LC23" class="blob-code blob-code-inner js-file-line">        - <span class="pl-ent">name</span>: <span class="pl-s">otel-config-vol</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-collector-gateway-deployment-yaml-LC24" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">mountPath</span>: <span class="pl-s">/etc/otel-config.yaml</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-collector-gateway-deployment-yaml-LC25" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">subPath</span>: <span class="pl-s">config.yaml</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-collector-gateway-deployment-yaml-LC26" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">volumes</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-collector-gateway-deployment-yaml-LC27" class="blob-code blob-code-inner js-file-line">      - <span class="pl-ent">name</span>: <span class="pl-s">otel-config-vol</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-collector-gateway-deployment-yaml-LC28" class="blob-code blob-code-inner js-file-line">        <span class="pl-ent">configMap</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-collector-gateway-deployment-yaml-LC29" class="blob-code blob-code-inner js-file-line">          <span class="pl-ent">name</span>: <span class="pl-s">otel-collector-config</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-deployment-yaml-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-collector-gateway-deployment-yaml-LC30" class="blob-code blob-code-inner js-file-line">      <span class="pl-c"><span class="pl-c">#</span> resources: (set requests/limits as appropriate)</span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/6b0978b930b23de7f1e68333d0a428e9/raw/08445e8e85d7cebd8cea778fa6da1f04a83df827/collector-gateway-deployment.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/6b0978b930b23de7f1e68333d0a428e9#file-collector-gateway-deployment-yaml" class="Link--inTextBlock">
          collector-gateway-deployment.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><p>And then a Service to expose it within the cluster:</p><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144569295\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-collector-gateway-service-yaml\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-yaml  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;collector-gateway-service.yaml content, created by jigarkb on 07:47AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;collector-gateway-service.yaml\&quot;>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>kind</span>: <span class=\&quot;pl-s\&quot;>Service</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>metadata</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otel-collector</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-ent\&quot;>spec</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>selector</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=\&quot;pl-ent\&quot;>app</span>: <span class=\&quot;pl-s\&quot;>otel-collector-gateway</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-ent\&quot;>ports</span>:</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otlp-grpc</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>port</span>: <span class=\&quot;pl-c1\&quot;>4317</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>targetPort</span>: <span class=\&quot;pl-c1\&quot;>4317</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    - <span class=\&quot;pl-ent\&quot;>name</span>: <span class=\&quot;pl-s\&quot;>otlp-http</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>port</span>: <span class=\&quot;pl-c1\&quot;>4318</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>      <span class=\&quot;pl-ent\&quot;>targetPort</span>: <span class=\&quot;pl-c1\&quot;>4318</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-collector-gateway-service-yaml-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-collector-gateway-service-yaml-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> type: LoadBalancer or ClusterIP depending on needs</span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/6736330e64b300a351e21292050dbac3/raw/585a87bd86f16faced628abf98de3d95ef6eef0d/collector-gateway-service.yaml\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/6736330e64b300a351e21292050dbac3#file-collector-gateway-service-yaml\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          collector-gateway-service.yaml\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144569295" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-collector-gateway-service-yaml" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-yaml  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="collector-gateway-service.yaml">
        <tbody><tr>
          <td id="file-collector-gateway-service-yaml-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-collector-gateway-service-yaml-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">kind</span>: <span class="pl-s">Service</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-collector-gateway-service-yaml-LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">metadata</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-collector-gateway-service-yaml-LC3" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">name</span>: <span class="pl-s">otel-collector</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-collector-gateway-service-yaml-LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-ent">spec</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-collector-gateway-service-yaml-LC5" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">selector</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-collector-gateway-service-yaml-LC6" class="blob-code blob-code-inner js-file-line">    <span class="pl-ent">app</span>: <span class="pl-s">otel-collector-gateway</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-collector-gateway-service-yaml-LC7" class="blob-code blob-code-inner js-file-line">  <span class="pl-ent">ports</span>:</td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-collector-gateway-service-yaml-LC8" class="blob-code blob-code-inner js-file-line">    - <span class="pl-ent">name</span>: <span class="pl-s">otlp-grpc</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-collector-gateway-service-yaml-LC9" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">port</span>: <span class="pl-c1">4317</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-collector-gateway-service-yaml-LC10" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">targetPort</span>: <span class="pl-c1">4317</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-collector-gateway-service-yaml-LC11" class="blob-code blob-code-inner js-file-line">    - <span class="pl-ent">name</span>: <span class="pl-s">otlp-http</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-collector-gateway-service-yaml-LC12" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">port</span>: <span class="pl-c1">4318</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-collector-gateway-service-yaml-LC13" class="blob-code blob-code-inner js-file-line">      <span class="pl-ent">targetPort</span>: <span class="pl-c1">4318</span></td>
        </tr>
        <tr>
          <td id="file-collector-gateway-service-yaml-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-collector-gateway-service-yaml-LC14" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> type: LoadBalancer or ClusterIP depending on needs</span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/6736330e64b300a351e21292050dbac3/raw/585a87bd86f16faced628abf98de3d95ef6eef0d/collector-gateway-service.yaml" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/6736330e64b300a351e21292050dbac3#file-collector-gateway-service-yaml" class="Link--inTextBlock">
          collector-gateway-service.yaml
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><p>With this, apps can use&nbsp;otel-collector:4318&nbsp;(ClusterIP service) as their OTLP endpoint. The gateway Collectors will receive all data. You might implement horizontal pod autoscaling on this Deployment based on CPU/memory if load is variable. Do take care to avoid&nbsp;<em>duplicate collection</em>: If you also use the Collector to scrape metrics (say from Kubelet or Prometheus endpoints), a centralized deployment might end up scraping the same target multiple times from each replica. In such cases, a DaemonSet (one per node) is better for those particular receivers.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J4uy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J4uy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png 424w, https://substackcdn.com/image/fetch/$s_!J4uy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png 848w, https://substackcdn.com/image/fetch/$s_!J4uy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png 1272w, https://substackcdn.com/image/fetch/$s_!J4uy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!J4uy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png" width="1250" height="793" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:793,&quot;width&quot;:1250,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Using the OpenTelemetry Collector: A Practical Guide&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Using the OpenTelemetry Collector: A Practical Guide" title="Using the OpenTelemetry Collector: A Practical Guide" srcset="https://substackcdn.com/image/fetch/$s_!J4uy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png 424w, https://substackcdn.com/image/fetch/$s_!J4uy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png 848w, https://substackcdn.com/image/fetch/$s_!J4uy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png 1272w, https://substackcdn.com/image/fetch/$s_!J4uy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfa95468-278d-47b0-9af9-09f2117d04e2_1250x793.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>OTel Collector Gateway Deployment (as a Deployment)</em></figcaption></figure></div><p>It&#8217;s common to use a&nbsp;<strong>combination</strong>: run an agent (DaemonSet) for things like host metrics that need to be collected on each node, and have those agents forward data to a central gateway for heavy processing and exporting. The agent Collector could be configured to export to the gateway Collector (via OTLP) rather than directly to the vendor, forming a two-tier pipeline. This combined approach offers the best of both: reliability of local collection and centralized control at the gateway.</p><p><strong>Which model to choose?</strong>&nbsp;It depends on your needs. If you prioritize minimal network hops and per-host isolation, use the agent pattern (DaemonSet or Sidecars). If you want easier manageability and can tolerate an extra hop, use a gateway. Many production setups actually use both: an agent to collect and perhaps lightly pre-process, then send to a gateway for heavy processing and final export. The OpenTelemetry project notes this as a recommended practice especially for large deployments.</p><div><hr></div><h2><strong>Production Best Practices and Tips</strong></h2><p>Now that we have the Collector up and running, how do we ensure it stays healthy and doesn&#8217;t become a bottleneck? Here are some&nbsp;<strong>production-readiness tips</strong>&nbsp;and&nbsp;<strong>common pitfalls to avoid</strong>&nbsp;when using the OpenTelemetry Collector in real-world deployments:</p><ol><li><p><strong>Enable Batching for Efficiency</strong></p></li></ol><p>Always use the&nbsp;batch&nbsp;processor (as we did in the config above) unless you have a specific reason not to. Batching significantly reduces CPU and network overhead by sending telemetry in chunks rather than item by item. It also can improve throughput to your backend. Tune the batch size and timeout if needed to balance latency vs. efficiency. For example, if you want to ensure traces get out within 5 seconds, set a&nbsp;timeout: 5s&nbsp;on batch; if your backend has payload size limits (like New Relic&#8217;s 1MB limit), adjust the&nbsp;send_batch_size&nbsp;so that payloads stay under that threshold. Batching is crucial for logs as well, to avoid overwhelming the exporter with too many small log messages.</p><ol start="2"><li><p><strong>Use Memory Limits and Monitor Backpressure</strong></p></li></ol><p>The Collector runs in process and will buffer data (especially with batch + queueing). If the volume of incoming data outpaces the ability to export (say the backend is slow or down), the Collector&#8217;s memory can fill up. This is where the&nbsp;memory_limiter&nbsp;processor helps: configure it to a reasonable limit based on your container&#8217;s memory. When it activates, it will start dropping incoming data and signal upstream to retry. This is preferable to crashing but it means data may be delayed or lost if the situation persists. To avoid hitting this, try to right-size the Collector: allocate enough CPU/memory for the expected telemetry volume, and <strong>scale out</strong>&nbsp;(add more Collector instances) if one instance isn&#8217;t enough. Monitor the Collector&#8217;s own metrics &#8211; it can emit metrics like the number of spans dropped due to memory pressure. Set resource requests/limits in Kubernetes to give the Collector breathing room and prevent eviction. In practice, you might give each Collector a few hundred millicpu and a few hundred MBs memory as a starting point and adjust from there. The memory limiter ensures it won&#8217;t exceed the set limit by too much, providing a safety net.</p><ol start="3"><li><p><strong>Ensure Retries to Prevent Data Loss</strong></p></li></ol><p>Transient failures happen &#8211; maybe a brief network hiccup or the backend returns a 503. The Collector should retry those exports. The good news is that the OTLP exporter has a built-in retry mechanism (using an exponential backoff) and by default it&nbsp;<strong>will</strong>&nbsp;retry on failure. In older versions of OpenTelemetry Collector, you had to explicitly add a&nbsp;retry&nbsp;processor or enable&nbsp;retry_on_failure&nbsp;in the exporter config. Recent versions enable retry by default, but always double-check the documentation for your specific version. One configurable parameter is&nbsp;max_elapsed_time&nbsp;for retries &#8211; by default, the collector may give up after some time (e.g., 300 seconds). If you absolutely cannot afford to drop data, you might set&nbsp;max_elapsed_time: 0&nbsp;(retry indefinitely), but be cautious: infinite retries could lead to a large memory buildup. It&#8217;s often better to ensure high availability of your backend and use persistent queues (see next point) for extreme reliability. Still, <strong>make sure retries are on</strong>. If using the Collector&#8217;s built-in settings, you might not need any extra config as long as you see logs indicating retries on failures. Additionally, monitor metrics like&nbsp;otelcol_exporter_send_failed&nbsp;or logs for &#8220;dropping data&#8221; messages to catch if data ever gets dropped after retries exhaust.</p><ol start="4"><li><p><strong>Consider Persistent Queues for Extreme Reliability</strong></p></li></ol><p>By default, the Collector&#8217;s queue (batch + retry queue) is in-memory. If the Collector process crashes or restarts, in-flight telemetry in the queue is lost. In production, especially when deploying new versions of the Collector, this can lead to gaps. If you require strong guarantees, consider enabling a&nbsp;<strong>persistent storage extension</strong>&nbsp;for the queue, which will spool the data to disk. The Collector offers a&nbsp;file_storage&nbsp;extension that exporters can use to persist their batches. With this, a restart will reload the queued data and continue sending. The trade-off is disk I/O and complexity. Many users find in-memory with retry is acceptable because telemetry systems are often tolerant to minor loss, but if you&#8217;re in a strict environment (e.g., audit logs), persistent queues are worth exploring. To use it, you&#8217;d configure something like:</p><pre><code>extensions:
  file_storage:
    directory: /etc/otel/spool

exporters:
  otlp:
    endpoint: ...
    headers: {api-key: "..."}
    sending_queue:
      storage: file_storage</code></pre><p>And include&nbsp;file_storage&nbsp;in the service extensions. This is an advanced setup and ensure the disk (or persistent volume in k8s) has enough space.</p><ol start="5"><li><p><strong>Tune Timeouts and Resource Usage</strong></p></li></ol><p>Longer export times can cause backup in the pipeline. The OTLP exporter default timeout might be 10 seconds for gRPC. If you find that in high load scenarios you hit timeouts, you might increase this value to, say, 30s. However, if your backend is routinely taking &gt;10s to accept data, something else might be wrong (or you need to reduce batch size). New Relic&#8217;s guidance is to&nbsp;<strong>increase exporter timeout if you send very large batches or have slow network</strong>. On the flip side, you don&#8217;t want it infinite, or the Collector could hang indefinitely on a stuck request. Find a balance (5-15s is common for trace/metric exports). Also verify that your backend isn&#8217;t rejecting data due to size &#8211; e.g., keep payloads under 1MB as mentioned earlier for New Relic. If you enable compression (gzip or zstd), it will reduce payload sizes and often speed up transmission; the Collector uses gzip by default which generally is good. You can consider switching to zstd compression for better performance if your backend and Collector version support it. Keep an eye on CPU usage &#8211; compression and large batch processing can be CPU intensive. If CPU is a bottleneck, you might reduce batch sizes or scale out more Collector instances so each does less work.</p><ol start="6"><li><p><strong>Avoid Overloading a Single Collector</strong></p></li></ol><p>One common pitfall is routing all telemetry through a single Collector instance without realizing the volume. If that instance can&#8217;t keep up (CPU pegged or memory thrashing), it will start dropping data or falling behind. In Kubernetes, if you use a Deployment (gateway) with a single replica for simplicity, monitor its resource usage. You may need to run multiple collectors and load balance among them. The Collector is stateless for traces and logs, so scaling horizontally is straightforward (metrics can be trickier due to stateful scraping &#8211; ensure a single-writer principle for each metric stream). Use&nbsp;<strong>Horizontal Pod Autoscalers</strong>&nbsp;or manually set 2-3 replicas for the gateway to handle spikes. If using DaemonSet, you automatically get scaling with the cluster size, but if one node has an unusually high telemetry volume (perhaps many pods), that node&#8217;s agent might be struggling. In such cases, consider deploying an extra sidecar for that pod or increase resources on that node&#8217;s agent. The goal is to prevent any single Collector from becoming a bottleneck.</p><p>Also be mindful of&nbsp;<strong>telemetry volume</strong>&nbsp;&#8211; sending every trace, log, and metric from every service at full detail can be overwhelming. Best practice is to filter and sample data before it hits your backend (and possibly before it even leaves the app or the agent). You can implement tail-based sampling in the Collector (there&#8217;s a&nbsp;sampling&nbsp;processor for traces) if needed to reduce volume. Or at least sample at the SDK level for very high-traffic services. Overloading the Collector with too high throughput will either crash it or incur lots of data drops. Gradually increase load and see how it performs, rather than turning on everything at once in production.</p><ol start="7"><li><p><strong>Monitor the Collector Itself</strong></p></li></ol><p>Treat the Collector as part of your production infrastructure &#8211; monitor its health and performance just as you would any service. The Collector can emit its own logs, metrics, and traces about its operation. For example, it can report how many spans it has received, how many it exported, if any were dropped, its memory usage, GC pauses, etc. You can configure a&nbsp;<strong>prometheus exporter/receiver</strong>&nbsp;pair on the Collector to scrape its metrics and send to your monitoring system, or use the&nbsp;health_check&nbsp;extension which provides an HTTP health endpoint. At minimum, check the Collector&#8217;s logs for warnings or errors (e.g., retry attempts, dropped data messages). New Relic&#8217;s backend (and others) also often provide feedback &#8211; for instance, if your data exceeds attribute size limits, New Relic might send back&nbsp;NrIntegrationError&nbsp;events or log warnings. These are signs that the Collector is sending data the backend can&#8217;t accept (perhaps a too-large attribute or missing required field). Incorporate those signals into your monitoring. If you see sustained errors or dropped telemetry, react by adjusting config (e.g., truncate attributes using a processor if they&#8217;re too large&nbsp;, or increase resources, etc.).</p><ol start="8"><li><p><strong>Upgrade and Update Carefully</strong></p></li></ol><p>The OpenTelemetry Collector project is under active development. New releases come out regularly with improvements, bug fixes, and sometimes breaking changes in configuration. When running in production, stick to a&nbsp;<strong>released version </strong>(avoid running a random&nbsp;:latest&nbsp;image long-term) and test new versions in a lower environment. Check the changelog for any changes to default behavior (for example, the <a href="https://github.com/open-telemetry/opentelemetry-collector/issues/10976?ref=observability.how">change</a> where after a certain version, data is dropped after retry timeout by default). Also, consider using the distribution provided by your backend vendor if they have one (e.g., some vendors offer a custom build or at least a recommended version that they support). But generally, the upstream OpenTelemetry Collector (especially the &#8220;contrib&#8221; build with many integrations) is very solid by late 2024 and is used in many production systems. Just make sure you&#8217;re not on a very old version that might be missing these features (batch, retry defaults, etc.) &#8211; the guide here assumes a relatively recent version.</p><p>To summarize the best practices:&nbsp;<strong>use the Collector to its strengths</strong>. Decouple your app from direct exporters (use OTLP to a local or remote collector). Enable processors like batch, retry (should be on by default), memory limiter, and any data sanitization you need. Right-size your deployment (either one-per-host or centralized, or both). Keep an eye on it &#8211; a misconfigured Collector (e.g., no batching, or too small memory) can drop a lot of data silently. Avoid common pitfalls of sending too much data: if you don&#8217;t need high-cardinality metrics or verbose debug logs, don&#8217;t ship them unchecked. The Collector gives you knobs to drop or sample those. And finally,&nbsp;<strong>test your observability pipeline</strong>&nbsp;under load. It&#8217;s better to discover in staging that your Collector needs tuning than to find out during a production traffic surge that telemetry is getting lost.</p><div><hr></div><p>Moving from OpenTelemetry experiments to a production deployment is a big step, but the OpenTelemetry Collector makes it much more manageable. In this guide, we covered how the Collector works, how to configure it to receive all your signals and send them off to an OTLP-compatible backend like New Relic, and the key considerations for deploying it on Kubernetes. The Collector is a powerful ally for your observability: it abstracts away backend specifics, lets you process data in-flight, and adds resilience to your telemetry pipeline. By using the Collector in either an agent or gateway mode (or both), you gain flexibility to evolve your observability strategy without touching application code &#8211; whether that means switching vendors, adjusting sampling rates, or enriching data with new attributes. Remember to apply the best practices around batching, resource limits, and monitoring, and you&#8217;ll have a robust, production-grade observability setup. OpenTelemetry is all about getting telemetry out of your systems reliably and consistently; with the Collector in place, you&#8217;re well on your way to achieving just that. Happy tracing (and measuring, and logging)!</p>]]></content:encoded></item><item><title><![CDATA[Getting Started with OpenTelemetry (OTel 101)]]></title><description><![CDATA[OpenTelemetry (OTel) has quickly become a cornerstone of modern observability.]]></description><link>https://www.observability.how/p/getting-started-with-opentelemetry-otel-101</link><guid isPermaLink="false">https://www.observability.how/p/getting-started-with-opentelemetry-otel-101</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Mon, 14 Apr 2025 23:52:17 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/49466716-1518-43e8-bb40-da1c66482077_1972x692.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!80Rw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!80Rw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png 424w, https://substackcdn.com/image/fetch/$s_!80Rw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png 848w, https://substackcdn.com/image/fetch/$s_!80Rw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png 1272w, https://substackcdn.com/image/fetch/$s_!80Rw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!80Rw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Getting Started with OpenTelemetry (OTel 101)&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Getting Started with OpenTelemetry (OTel 101)" title="Getting Started with OpenTelemetry (OTel 101)" srcset="https://substackcdn.com/image/fetch/$s_!80Rw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png 424w, https://substackcdn.com/image/fetch/$s_!80Rw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png 848w, https://substackcdn.com/image/fetch/$s_!80Rw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png 1272w, https://substackcdn.com/image/fetch/$s_!80Rw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3239c91-5822-4d15-8309-f28bf90d99ad_1972x692.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>OpenTelemetry (OTel) has quickly become a cornerstone of modern observability. If you&#8217;re a developer or engineer looking to instrument your applications for better insight, this beginner&#8217;s guide is for you. I&#8217;ll explain what OpenTelemetry is, why it matters, and walk through a step-by-step tutorial to instrument a simple Java app with basic traces and metrics &#8211; all using console output (no external systems required). By the end, you&#8217;ll have a solid foundation in OTel and know how to get started in your own projects.</p><div><hr></div><h2>What is OpenTelemetry and Why Does It Matter?</h2><p><strong><a href="https://opentelemetry.io/?ref=observability.how">OpenTelemetry</a> (OTel)</strong>&nbsp;is an open-source observability framework &#8211; essentially a collection of APIs, SDKs, and tools for generating and exporting telemetry data (<strong>traces</strong>,&nbsp;<strong>metrics</strong>, and&nbsp;<strong>logs</strong>) from your software. In practice, OTel allows you to instrument code in a&nbsp;<strong>vendor-neutral</strong>&nbsp;way, meaning you aren&#8217;t locked into any specific monitoring vendor or product. You can send your app&#8217;s telemetry to any backend that supports OpenTelemetry, or even multiple backends simultaneously. This flexibility makes OTel a popular choice for cloud-native and microservices architectures.</p><p>OTel covers the three key types of telemetry data (aka <strong>Observability pillars</strong>).</p><p></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;d95995f3-63b2-4f1c-a0ee-8cf92fc78db8&quot;,&quot;caption&quot;:&quot;Imagine you&#8217;re a detective for software systems. Late one night, an alert goes off: something is wrong with your application. But what is wrong? In a complex microservices environment, finding the culprit can feel like searching for a needle in a haystack. This is where&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;What is Observability? &#8211; Metrics, Logs, and Traces Demystified&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:3948178,&quot;name&quot;:&quot;Jigar Bhatt&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4c98809-3113-4229-a8d2-dadc514906f2_1597x1597.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-04-13T06:03:38.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2eea1394-f04e-4824-86f2-a5ec578abfba_2000x1333.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://observabilityhow.substack.com/p/what-is-observability-metrics-logs-and-traces-demystified&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:184843152,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:7661027,&quot;publication_name&quot;:&quot;Observability.&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3y9a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb61d30f7-d950-434d-a62c-18abe1307588_500x500.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p></p><p><strong>Why use OpenTelemetry?</strong>&nbsp;In a word:&nbsp;<strong>standardization</strong>. Before OTel, engineers had to rely on disparate libraries or vendor-specific agents for tracing and metrics. OTel combines the efforts of prior projects (OpenTracing and OpenCensus) into one standard, <strong>simplifying instrumentation</strong>. With OTel, you instrument your code once and gain the ability to export data to many analysis tools (open source or commercial) without changing your instrumentation. It&#8217;s also&nbsp;<strong>cloud-native and CNCF-endorsed</strong>&nbsp;&#8211; OpenTelemetry is an incubating project under CNCF and is generally available (GA) in many languages, meaning it&#8217;s production-ready and supported by a broad community. In short, OTel makes it easier to build reliable, observable systems and focus on writing code rather than wiring up monitoring.</p><div><hr></div><h2>OpenTelemetry Architecture: API, SDK, and Collector</h2><p>OpenTelemetry&#8217;s design is modular. To understand how it works, let&#8217;s break down its three main components: the&nbsp;<strong>API</strong>, the&nbsp;<strong>SDK</strong>, and the&nbsp;<strong>Collector</strong>.</p><ul><li><p><strong>OpenTelemetry API:</strong>&nbsp;The API is the interface for instrumentation. It defines the data types and operations for creating spans, recording metrics, and propagating context. When you add OTel to your app, you use the API to mark up your code (for example, starting a span or updating a metric). The API is deliberately kept separate from any specific backend or vendor. It&#8217;s lightweight and&nbsp;<strong>no-op by default</strong>&nbsp;&#8211; if no SDK is present, API calls do essentially nothing, incurring minimal overhead. This design means&nbsp;<strong>libraries or applications can include OpenTelemetry API calls without forcing a particular telemetry backend on users</strong>. Using the API gives you&nbsp;<strong>vendor-neutral instrumentation</strong>: your telemetry can be sent anywhere, and you can swap out how data is handled without changing the instrumentation code.</p></li><li><p><strong>OpenTelemetry SDK:</strong>&nbsp;The SDK is the engine under the hood that actually collects and exports telemetry. It&#8217;s the implementation of the API for a given language. The SDK provides the functionality to batch and process spans, aggregate metrics, and send data out via&nbsp;<strong>exporters</strong>. You&#8217;ll configure the SDK in your application to specify things like which exporter to use (e.g., send data to Jaeger, Prometheus, etc.), what sampling rate to apply for traces, and other behaviors. In Java, the SDK includes components like the&nbsp;SdkTracerProvider&nbsp;(a factory for tracers),&nbsp;SdkMeterProvider&nbsp;(for metrics), processors, and exporters. Think of the SDK as the piece that <strong>handles the heavy lifting</strong>&nbsp;of telemetry data &#8211; buffering, processing, and transmitting it according to your configuration. Without the SDK, the API calls alone wouldn&#8217;t output anything; with the SDK, your spans and metrics get captured and forwarded to your chosen destination.</p></li><li><p><strong>OpenTelemetry Collector:</strong>&nbsp;The Collector is a separate process (or set of processes) that receives, processes, and exports telemetry data on behalf of your application. It is&nbsp;<strong>vendor-agnostic</strong>&nbsp;and can accept data in various formats (OTLP, Jaeger, Zipkin, Prometheus, etc.), optionally transform or filter it, and then export it to one or multiple backends. The Collector is often run as an agent (next to your app) or as a centralized service. Why use a Collector? It decouples your application code from specific exporters. Your app can send data in a standard format (OTLP) to the Collector, and the Collector worries about forwarding it to the right place(s). This provides flexibility: you can change or add monitoring backends by updating Collector config, without redeploying your app. In our beginner example we won&#8217;t set up a Collector (to keep things simple), but it&#8217;s good to know this component exists. In production, a Collector is highly recommended for its buffering, load shedding, and routing capabilities.</p></li></ul><p><strong>How these pieces fit together:</strong>&nbsp;In a typical setup, your&nbsp;<strong>application code uses the OTel API</strong>&nbsp;(e.g., to start spans). You also include and configure the&nbsp;<strong>OTel SDK</strong>&nbsp;in the app, which handles those API calls (for example, it takes a span and sends it via an exporter). Optionally, you might configure the SDK&#8217;s exporter to send data to the&nbsp;<strong>Collector</strong>&nbsp;instead of directly to a backend. The Collector then forwards data to your observability backend (like Jaeger, Zipkin, Prometheus, Honeycomb, etc.). This layering provides a lot of flexibility and has become an industry standard approach to observability.</p><div><hr></div><h2>Tutorial: Instrumenting a Java Application with OpenTelemetry</h2><p>Enough theory &#8211; let&#8217;s get hands-on! In this tutorial, we&#8217;ll instrument a simple Java application to emit a basic trace and a metric using OpenTelemetry. We&#8217;ll use <strong>console logging</strong>&nbsp;as our &#8220;exporter&#8221; so that you can see the telemetry output right in the console (no external systems like Jaeger or Prometheus needed). The goal is to illustrate the end-to-end process: from setting up OTel, to generating spans and metrics, to seeing the results.</p><p><strong>Scenario:</strong>&nbsp;Imagine we have a simple Java program that processes a batch of items. We want to trace the processing and count how many items were processed. We&#8217;ll create spans for the overall batch and each item, and use a counter metric to record the count. All telemetry data will be printed to the console via OpenTelemetry&#8217;s logging exporter.</p><h3>I. Setting Up the Project and Dependencies</h3><p>First, we need to include OpenTelemetry in our project. If you&#8217;re using Maven or Gradle, add the following dependencies (using the latest version of OpenTelemetry Java, which at the time of writing is 1.x):</p><ul><li><p><strong>OpenTelemetry API</strong>&nbsp;(<code>io.opentelemetry:opentelemetry-api</code>) &#8211; for the instrumentation API (tracers, meters, etc.).</p></li><li><p><strong>OpenTelemetry SDK</strong>&nbsp;(<code>io.opentelemetry:opentelemetry-sdk</code>) &#8211; for the core implementation (needed to actually emit telemetry).</p></li><li><p><strong>OpenTelemetry Logging Exporter</strong>&nbsp;(<code>io.opentelemetry:opentelemetry-exporter-logging</code>) &#8211; an exporter that logs spans and metrics to the console using Java&#8217;s logging framework. This is what allows us to see trace and metric output in stdout.</p></li></ul><p>With Maven, you might also include the BOM (<a href="https://mvnrepository.com/artifact/io.opentelemetry/opentelemetry-bom?ref=observability.how">opentelemetry-bom</a>) to manage versions. For brevity, we&#8217;ll skip showing the full&nbsp;pom.xml&nbsp;or Gradle file, but ensure these artifacts are present. Once dependencies are set, we can proceed to writing code.</p><h3>II. Initializing OpenTelemetry (API + SDK Configuration)</h3><p>Before we create any spans or metrics, we have to initialize OpenTelemetry in our application. This means configuring the OTel SDK and specifying how it should export data. In our case, we&#8217;ll configure the SDK to use the&nbsp;<strong>Logging exporter</strong>&nbsp;for both traces and metrics (so data goes to console). We&#8217;ll do this in a setup method for clarity:</p><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144568769\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-otel-101-otelinitializer-java\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-java  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;OTel-101-OTelInitializer.java content, created by jigarkb on 07:20AM today.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;OTel-101-OTelInitializer.java\&quot;>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>package</span> <span class=pl-s1>how</span>.<span class=pl-s1>observability</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>api</span>.<span class=pl-s1>OpenTelemetry</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>exporter</span>.<span class=pl-s1>logging</span>.<span class=pl-s1>LoggingMetricExporter</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>exporter</span>.<span class=pl-s1>logging</span>.<span class=pl-s1>LoggingSpanExporter</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>sdk</span>.<span class=pl-s1>OpenTelemetrySdk</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>sdk</span>.<span class=pl-s1>metrics</span>.<span class=pl-s1>SdkMeterProvider</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>sdk</span>.<span class=pl-s1>metrics</span>.<span class=pl-s1>export</span>.<span class=pl-s1>PeriodicMetricReader</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>sdk</span>.<span class=pl-s1>trace</span>.<span class=pl-s1>SdkTracerProvider</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>sdk</span>.<span class=pl-s1>trace</span>.<span class=pl-s1>export</span>.<span class=pl-s1>SimpleSpanProcessor</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>java</span>.<span class=pl-s1>time</span>.<span class=pl-s1>Duration</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>public</span> <span class=pl-k>class</span> <span class=pl-smi>OTelInitializer</span> {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=pl-c>// Configure OpenTelemetry SDK with console (logging) exporters</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=pl-k>public</span> <span class=pl-k>static</span> <span class=pl-smi>OpenTelemetry</span> <span class=pl-en>initOpenTelemetry</span>() {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-c>// 1. Configure TracerProvider with LoggingSpanExporter (for traces)</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>SdkTracerProvider</span> <span class=pl-s1>tracerProvider</span> = <span class=pl-smi>SdkTracerProvider</span>.<span class=pl-en>builder</span>()</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>addSpanProcessor</span>(<span class=pl-smi>SimpleSpanProcessor</span>.<span class=pl-en>create</span>(<span class=pl-smi>LoggingSpanExporter</span>.<span class=pl-en>create</span>()))</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>build</span>();</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-c>// 2. Configure MeterProvider with LoggingMetricExporter (for metrics)</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>SdkMeterProvider</span> <span class=pl-s1>meterProvider</span> = <span class=pl-smi>SdkMeterProvider</span>.<span class=pl-en>builder</span>()</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>registerMetricReader</span>(<span class=pl-smi>PeriodicMetricReader</span>.<span class=pl-en>builder</span>(<span class=pl-smi>LoggingMetricExporter</span>.<span class=pl-en>create</span>())</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                        .<span class=pl-en>setInterval</span>(<span class=pl-smi>Duration</span>.<span class=pl-en>ofMillis</span>(<span class=pl-c1>1000</span>)) <span class=pl-c>// export metrics every 1s</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                        .<span class=pl-en>build</span>()</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                )</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>build</span>();</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-c>// 3. Build OpenTelemetry SDK instance with our providers and make it global</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>OpenTelemetry</span> <span class=pl-s1>openTelemetry</span> = <span class=pl-smi>OpenTelemetrySdk</span>.<span class=pl-en>builder</span>()</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>setTracerProvider</span>(<span class=pl-s1>tracerProvider</span>)</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L34\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;34\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC34\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>setMeterProvider</span>(<span class=pl-s1>meterProvider</span>)</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L35\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;35\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC35\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>buildAndRegisterGlobal</span>();</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L36\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;36\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC36\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-k>return</span> <span class=pl-s1>openTelemetry</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L37\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;37\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC37\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    }</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-otelinitializer-java-L38\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;38\&quot;></td>\n          <td id=\&quot;file-otel-101-otelinitializer-java-LC38\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>}</td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/70f1378c1db8cb723401b3b121bfeeea/raw/ead89e398c59c5c20e7b263eedc681dea75fbcd6/OTel-101-OTelInitializer.java\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/70f1378c1db8cb723401b3b121bfeeea#file-otel-101-otelinitializer-java\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          OTel-101-OTelInitializer.java\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144568769" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-otel-101-otelinitializer-java" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-java  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="OTel-101-OTelInitializer.java">
        <tbody><tr>
          <td id="file-otel-101-otelinitializer-java-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-otel-101-otelinitializer-java-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-k">package</span> <span class="pl-s1">how</span>.<span class="pl-s1">observability</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-otel-101-otelinitializer-java-LC2" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-otel-101-otelinitializer-java-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">api</span>.<span class="pl-s1">OpenTelemetry</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-otel-101-otelinitializer-java-LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">exporter</span>.<span class="pl-s1">logging</span>.<span class="pl-s1">LoggingMetricExporter</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-otel-101-otelinitializer-java-LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">exporter</span>.<span class="pl-s1">logging</span>.<span class="pl-s1">LoggingSpanExporter</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-otel-101-otelinitializer-java-LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">sdk</span>.<span class="pl-s1">OpenTelemetrySdk</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-otel-101-otelinitializer-java-LC7" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">sdk</span>.<span class="pl-s1">metrics</span>.<span class="pl-s1">SdkMeterProvider</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-otel-101-otelinitializer-java-LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">sdk</span>.<span class="pl-s1">metrics</span>.<span class="pl-s1">export</span>.<span class="pl-s1">PeriodicMetricReader</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-otel-101-otelinitializer-java-LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">sdk</span>.<span class="pl-s1">trace</span>.<span class="pl-s1">SdkTracerProvider</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-otel-101-otelinitializer-java-LC10" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">sdk</span>.<span class="pl-s1">trace</span>.<span class="pl-s1">export</span>.<span class="pl-s1">SimpleSpanProcessor</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-otel-101-otelinitializer-java-LC11" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-otel-101-otelinitializer-java-LC12" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">java</span>.<span class="pl-s1">time</span>.<span class="pl-s1">Duration</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-otel-101-otelinitializer-java-LC13" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-otel-101-otelinitializer-java-LC14" class="blob-code blob-code-inner js-file-line"><span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">OTelInitializer</span> {</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-otel-101-otelinitializer-java-LC15" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-otel-101-otelinitializer-java-LC16" class="blob-code blob-code-inner js-file-line">    <span class="pl-c">// Configure OpenTelemetry SDK with console (logging) exporters</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-otel-101-otelinitializer-java-LC17" class="blob-code blob-code-inner js-file-line">    <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-smi">OpenTelemetry</span> <span class="pl-en">initOpenTelemetry</span>() {</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-otel-101-otelinitializer-java-LC18" class="blob-code blob-code-inner js-file-line">        <span class="pl-c">// 1. Configure TracerProvider with LoggingSpanExporter (for traces)</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-otel-101-otelinitializer-java-LC19" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">SdkTracerProvider</span> <span class="pl-s1">tracerProvider</span> = <span class="pl-smi">SdkTracerProvider</span>.<span class="pl-en">builder</span>()</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-otel-101-otelinitializer-java-LC20" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">addSpanProcessor</span>(<span class="pl-smi">SimpleSpanProcessor</span>.<span class="pl-en">create</span>(<span class="pl-smi">LoggingSpanExporter</span>.<span class="pl-en">create</span>()))</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-otel-101-otelinitializer-java-LC21" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">build</span>();</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-otel-101-otelinitializer-java-LC22" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-otel-101-otelinitializer-java-LC23" class="blob-code blob-code-inner js-file-line">        <span class="pl-c">// 2. Configure MeterProvider with LoggingMetricExporter (for metrics)</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-otel-101-otelinitializer-java-LC24" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">SdkMeterProvider</span> <span class="pl-s1">meterProvider</span> = <span class="pl-smi">SdkMeterProvider</span>.<span class="pl-en">builder</span>()</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-otel-101-otelinitializer-java-LC25" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">registerMetricReader</span>(<span class="pl-smi">PeriodicMetricReader</span>.<span class="pl-en">builder</span>(<span class="pl-smi">LoggingMetricExporter</span>.<span class="pl-en">create</span>())</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-otel-101-otelinitializer-java-LC26" class="blob-code blob-code-inner js-file-line">                        .<span class="pl-en">setInterval</span>(<span class="pl-smi">Duration</span>.<span class="pl-en">ofMillis</span>(<span class="pl-c1">1000</span>)) <span class="pl-c">// export metrics every 1s</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-otel-101-otelinitializer-java-LC27" class="blob-code blob-code-inner js-file-line">                        .<span class="pl-en">build</span>()</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-otel-101-otelinitializer-java-LC28" class="blob-code blob-code-inner js-file-line">                )</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-otel-101-otelinitializer-java-LC29" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">build</span>();</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-otel-101-otelinitializer-java-LC30" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-otel-101-otelinitializer-java-LC31" class="blob-code blob-code-inner js-file-line">        <span class="pl-c">// 3. Build OpenTelemetry SDK instance with our providers and make it global</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-otel-101-otelinitializer-java-LC32" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">OpenTelemetry</span> <span class="pl-s1">openTelemetry</span> = <span class="pl-smi">OpenTelemetrySdk</span>.<span class="pl-en">builder</span>()</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-otel-101-otelinitializer-java-LC33" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">setTracerProvider</span>(<span class="pl-s1">tracerProvider</span>)</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-otel-101-otelinitializer-java-LC34" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">setMeterProvider</span>(<span class="pl-s1">meterProvider</span>)</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-otel-101-otelinitializer-java-LC35" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">buildAndRegisterGlobal</span>();</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
          <td id="file-otel-101-otelinitializer-java-LC36" class="blob-code blob-code-inner js-file-line">        <span class="pl-k">return</span> <span class="pl-s1">openTelemetry</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L37" class="blob-num js-line-number js-blob-rnum" data-line-number="37"></td>
          <td id="file-otel-101-otelinitializer-java-LC37" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-otel-101-otelinitializer-java-L38" class="blob-num js-line-number js-blob-rnum" data-line-number="38"></td>
          <td id="file-otel-101-otelinitializer-java-LC38" class="blob-code blob-code-inner js-file-line">}</td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/70f1378c1db8cb723401b3b121bfeeea/raw/ead89e398c59c5c20e7b263eedc681dea75fbcd6/OTel-101-OTelInitializer.java" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/70f1378c1db8cb723401b3b121bfeeea#file-otel-101-otelinitializer-java" class="Link--inTextBlock">
          OTel-101-OTelInitializer.java
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><p>Let&#8217;s break down what this does:</p><ul><li><p>We create an&nbsp;<code>SdkTracerProvider</code>&nbsp;and attach a&nbsp;<strong><code>SimpleSpanProcessor</code></strong>&nbsp;with a <strong><code>LoggingSpanExporter</code></strong>. The span processor is what takes finished spans and passes them to an exporter; here we use a simple processor that exports spans immediately as they end. The LoggingSpanExporter, provided by the OTel SDK, will log span data using Java&#8217;s&nbsp;java.util.logging&nbsp;(JUL) in a human-readable format. In short, each span will result in a log line in our console output.</p></li><li><p>We create an&nbsp;<code>SdkMeterProvider</code>&nbsp;and register a&nbsp;<strong><code>PeriodicMetricReader</code></strong>&nbsp;with a <strong><code>LoggingMetricExporter</code></strong>. This means the SDK will collect metrics and, every 1000ms (1 second), it will export the metrics via the LoggingMetricExporter. The <code>LoggingMetricExporter</code> similarly uses JUL to log metric data. The periodic reader is necessary because metrics are aggregated &#8211; we don&#8217;t send a metric every single update, but rather periodically report the current value or delta. By setting the interval to 1 second, we&#8217;ll see metrics printed to console every second (which is fine for demonstration). We choose a short interval here just so we don&#8217;t have to wait long to see output.</p></li><li><p>Finally, we build the&nbsp;<code>OpenTelemetrySdk</code>&nbsp;with the tracer and meter providers, and register it as the global instance. Marking it global (buildAndRegisterGlobal()) means the static&nbsp;<strong><code>GlobalOpenTelemetry</code></strong>&nbsp;accessor or anyone else in the app can get this configured instance. We then return the OpenTelemetry instance as well, for direct use.</p></li></ul><p>At this point, we have an&nbsp;<strong>OpenTelemetry SDK initialized</strong>&nbsp;to log all telemetry to the console. In a real application, you might configure a different exporter (e.g., an OTLP exporter to send data to a collector or backend), and you might use a BatchSpanProcessor for efficiency, but the above is the simplest setup for illustrative purposes.</p><h3>III. Instrumenting Metrics and Traces (Spans)</h3><p>With the SDK ready, we can now instrument our application code. We&#8217;ll obtain a <strong>Tracer</strong>&nbsp;from the OpenTelemetry API to create spans. We&#8217;ll also get a&nbsp;<strong>Meter</strong>&nbsp;to record metrics. Let&#8217;s write a simple&nbsp;main&nbsp;method for our demo application:</p><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist137421866\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-otel-101-demoapp-java\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-java  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;OTel-101-DemoApp.java content, created by jigarkb on 11:07PM on April 14, 2025.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;OTel-101-DemoApp.java\&quot;>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>package</span> <span class=pl-s1>how</span>.<span class=pl-s1>observability</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>api</span>.<span class=pl-s1>OpenTelemetry</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>api</span>.<span class=pl-s1>metrics</span>.<span class=pl-s1>LongCounter</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>api</span>.<span class=pl-s1>metrics</span>.<span class=pl-s1>Meter</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>api</span>.<span class=pl-s1>trace</span>.<span class=pl-s1>Span</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>api</span>.<span class=pl-s1>trace</span>.<span class=pl-s1>Tracer</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>import</span> <span class=pl-s1>io</span>.<span class=pl-s1>opentelemetry</span>.<span class=pl-s1>context</span>.<span class=pl-s1>Scope</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=pl-k>public</span> <span class=pl-k>class</span> <span class=pl-smi>DemoApp</span> {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=pl-k>private</span> <span class=pl-k>static</span> <span class=pl-k>final</span> <span class=pl-smi>String</span> <span class=pl-c1>INSTRUMENTATION_NAME</span> = <span class=pl-s>&amp;quot;OTelDemoApp&amp;quot;</span>;</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    <span class=pl-k>public</span> <span class=pl-k>static</span> <span class=pl-smi>void</span> <span class=pl-en>main</span>(<span class=pl-smi>String</span>[] <span class=pl-s1>args</span>) {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-c>// Initialize OpenTelemetry (set up exporters to console)</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>OpenTelemetry</span> <span class=pl-s1>openTelemetry</span> = <span class=pl-smi>OTelInitializer</span>.<span class=pl-en>initOpenTelemetry</span>();</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-c>// Get a Tracer and Meter from the OpenTelemetry API</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>Tracer</span> <span class=pl-s1>tracer</span> = <span class=pl-s1>openTelemetry</span>.<span class=pl-en>getTracer</span>(<span class=pl-c1>INSTRUMENTATION_NAME</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>Meter</span> <span class=pl-s1>meter</span> = <span class=pl-s1>openTelemetry</span>.<span class=pl-en>getMeter</span>(<span class=pl-c1>INSTRUMENTATION_NAME</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-c>// Create a Counter instrument for metrics</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>LongCounter</span> <span class=pl-s1>itemsProcessedCounter</span> = <span class=pl-s1>meter</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>counterBuilder</span>(<span class=pl-s>&amp;quot;processed_items&amp;quot;</span>)</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>setDescription</span>(<span class=pl-s>&amp;quot;Number of items processed&amp;quot;</span>)</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>setUnit</span>(<span class=pl-s>&amp;quot;1&amp;quot;</span>)</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                .<span class=pl-en>build</span>();</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-c>// Start a span for the batch process</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-smi>Span</span> <span class=pl-s1>batchSpan</span> = <span class=pl-s1>tracer</span>.<span class=pl-en>spanBuilder</span>(<span class=pl-s>&amp;quot;processBatch&amp;quot;</span>).<span class=pl-en>startSpan</span>();</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-k>try</span> (<span class=pl-smi>Scope</span> <span class=pl-s1>batchScope</span> = <span class=pl-s1>batchSpan</span>.<span class=pl-en>makeCurrent</span>()) {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            <span class=pl-c>// Simulate processing 5 items, each item will have its own span</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            <span class=pl-k>for</span> (<span class=pl-smi>int</span> <span class=pl-s1>i</span> = <span class=pl-c1>1</span>; <span class=pl-s1>i</span> &amp;lt;= <span class=pl-c1>5</span>; <span class=pl-s1>i</span>++) {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                <span class=pl-smi>Span</span> <span class=pl-s1>itemSpan</span> = <span class=pl-s1>tracer</span>.<span class=pl-en>spanBuilder</span>(<span class=pl-s>&amp;quot;processItem&amp;quot;</span>).<span class=pl-en>startSpan</span>();</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L34\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;34\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC34\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                <span class=pl-k>try</span> (<span class=pl-smi>Scope</span> <span class=pl-s1>itemScope</span> = <span class=pl-s1>itemSpan</span>.<span class=pl-en>makeCurrent</span>()) {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L35\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;35\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC35\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    <span class=pl-c>// Simulate some work for the item</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L36\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;36\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC36\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    <span class=pl-smi>System</span>.<span class=pl-s1>out</span>.<span class=pl-en>println</span>(<span class=pl-s>&amp;quot;Processing item &amp;quot;</span> + <span class=pl-s1>i</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L37\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;37\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC37\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    <span class=pl-c>// Record a metric for the processed item</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L38\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;38\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC38\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    <span class=pl-s1>itemsProcessedCounter</span>.<span class=pl-en>add</span>(<span class=pl-c1>1</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L39\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;39\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC39\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                } <span class=pl-k>finally</span> {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L40\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;40\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC40\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                    <span class=pl-s1>itemSpan</span>.<span class=pl-en>end</span>();  <span class=pl-c>// end the item span</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L41\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;41\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC41\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>                }</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L42\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;42\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC42\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            }</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L43\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;43\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC43\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        } <span class=pl-k>finally</span> {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L44\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;44\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC44\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            <span class=pl-s1>batchSpan</span>.<span class=pl-en>end</span>();  <span class=pl-c>// end the batch span</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L45\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;45\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC45\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        }</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L46\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;46\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC46\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L47\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;47\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC47\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-c>// Wait briefly to ensure the last metric is exported</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L48\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;48\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC48\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        <span class=pl-k>try</span> {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L49\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;49\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC49\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>            <span class=pl-smi>Thread</span>.<span class=pl-en>sleep</span>(<span class=pl-c1>1500</span>);</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L50\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;50\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC50\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        } <span class=pl-k>catch</span> (<span class=pl-smi>InterruptedException</span> <span class=pl-s1>ignored</span>) {</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L51\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;51\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC51\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L52\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;52\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC52\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>        }</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L53\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;53\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC53\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>    }</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-otel-101-demoapp-java-L54\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;54\&quot;></td>\n          <td id=\&quot;file-otel-101-demoapp-java-LC54\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>}</td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/jigarkb/8d0903a6bcd14bffc745c1a68017169d/raw/badf33f7fa80735e29ceb8bfb20f834dff55663e/OTel-101-DemoApp.java\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/jigarkb/8d0903a6bcd14bffc745c1a68017169d#file-otel-101-demoapp-java\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          OTel-101-DemoApp.java\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist137421866" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-otel-101-demoapp-java" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-java  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="OTel-101-DemoApp.java">
        <tbody><tr>
          <td id="file-otel-101-demoapp-java-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-otel-101-demoapp-java-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-k">package</span> <span class="pl-s1">how</span>.<span class="pl-s1">observability</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-otel-101-demoapp-java-LC2" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-otel-101-demoapp-java-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">api</span>.<span class="pl-s1">OpenTelemetry</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-otel-101-demoapp-java-LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">api</span>.<span class="pl-s1">metrics</span>.<span class="pl-s1">LongCounter</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-otel-101-demoapp-java-LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">api</span>.<span class="pl-s1">metrics</span>.<span class="pl-s1">Meter</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-otel-101-demoapp-java-LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">api</span>.<span class="pl-s1">trace</span>.<span class="pl-s1">Span</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-otel-101-demoapp-java-LC7" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">api</span>.<span class="pl-s1">trace</span>.<span class="pl-s1">Tracer</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-otel-101-demoapp-java-LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-s1">io</span>.<span class="pl-s1">opentelemetry</span>.<span class="pl-s1">context</span>.<span class="pl-s1">Scope</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-otel-101-demoapp-java-LC9" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-otel-101-demoapp-java-LC10" class="blob-code blob-code-inner js-file-line"><span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">DemoApp</span> {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-otel-101-demoapp-java-LC11" class="blob-code blob-code-inner js-file-line">    <span class="pl-k">private</span> <span class="pl-k">static</span> <span class="pl-k">final</span> <span class="pl-smi">String</span> <span class="pl-c1">INSTRUMENTATION_NAME</span> = <span class="pl-s">"OTelDemoApp"</span>;</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-otel-101-demoapp-java-LC12" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-otel-101-demoapp-java-LC13" class="blob-code blob-code-inner js-file-line">    <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-smi">void</span> <span class="pl-en">main</span>(<span class="pl-smi">String</span>[] <span class="pl-s1">args</span>) {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-otel-101-demoapp-java-LC14" class="blob-code blob-code-inner js-file-line">        <span class="pl-c">// Initialize OpenTelemetry (set up exporters to console)</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-otel-101-demoapp-java-LC15" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">OpenTelemetry</span> <span class="pl-s1">openTelemetry</span> = <span class="pl-smi">OTelInitializer</span>.<span class="pl-en">initOpenTelemetry</span>();</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-otel-101-demoapp-java-LC16" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-otel-101-demoapp-java-LC17" class="blob-code blob-code-inner js-file-line">        <span class="pl-c">// Get a Tracer and Meter from the OpenTelemetry API</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-otel-101-demoapp-java-LC18" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">Tracer</span> <span class="pl-s1">tracer</span> = <span class="pl-s1">openTelemetry</span>.<span class="pl-en">getTracer</span>(<span class="pl-c1">INSTRUMENTATION_NAME</span>);</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-otel-101-demoapp-java-LC19" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">Meter</span> <span class="pl-s1">meter</span> = <span class="pl-s1">openTelemetry</span>.<span class="pl-en">getMeter</span>(<span class="pl-c1">INSTRUMENTATION_NAME</span>);</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-otel-101-demoapp-java-LC20" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-otel-101-demoapp-java-LC21" class="blob-code blob-code-inner js-file-line">        <span class="pl-c">// Create a Counter instrument for metrics</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-otel-101-demoapp-java-LC22" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">LongCounter</span> <span class="pl-s1">itemsProcessedCounter</span> = <span class="pl-s1">meter</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-otel-101-demoapp-java-LC23" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">counterBuilder</span>(<span class="pl-s">"processed_items"</span>)</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-otel-101-demoapp-java-LC24" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">setDescription</span>(<span class="pl-s">"Number of items processed"</span>)</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-otel-101-demoapp-java-LC25" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">setUnit</span>(<span class="pl-s">"1"</span>)</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-otel-101-demoapp-java-LC26" class="blob-code blob-code-inner js-file-line">                .<span class="pl-en">build</span>();</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-otel-101-demoapp-java-LC27" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-otel-101-demoapp-java-LC28" class="blob-code blob-code-inner js-file-line">        <span class="pl-c">// Start a span for the batch process</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-otel-101-demoapp-java-LC29" class="blob-code blob-code-inner js-file-line">        <span class="pl-smi">Span</span> <span class="pl-s1">batchSpan</span> = <span class="pl-s1">tracer</span>.<span class="pl-en">spanBuilder</span>(<span class="pl-s">"processBatch"</span>).<span class="pl-en">startSpan</span>();</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-otel-101-demoapp-java-LC30" class="blob-code blob-code-inner js-file-line">        <span class="pl-k">try</span> (<span class="pl-smi">Scope</span> <span class="pl-s1">batchScope</span> = <span class="pl-s1">batchSpan</span>.<span class="pl-en">makeCurrent</span>()) {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-otel-101-demoapp-java-LC31" class="blob-code blob-code-inner js-file-line">            <span class="pl-c">// Simulate processing 5 items, each item will have its own span</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-otel-101-demoapp-java-LC32" class="blob-code blob-code-inner js-file-line">            <span class="pl-k">for</span> (<span class="pl-smi">int</span> <span class="pl-s1">i</span> = <span class="pl-c1">1</span>; <span class="pl-s1">i</span> &lt;= <span class="pl-c1">5</span>; <span class="pl-s1">i</span>++) {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-otel-101-demoapp-java-LC33" class="blob-code blob-code-inner js-file-line">                <span class="pl-smi">Span</span> <span class="pl-s1">itemSpan</span> = <span class="pl-s1">tracer</span>.<span class="pl-en">spanBuilder</span>(<span class="pl-s">"processItem"</span>).<span class="pl-en">startSpan</span>();</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-otel-101-demoapp-java-LC34" class="blob-code blob-code-inner js-file-line">                <span class="pl-k">try</span> (<span class="pl-smi">Scope</span> <span class="pl-s1">itemScope</span> = <span class="pl-s1">itemSpan</span>.<span class="pl-en">makeCurrent</span>()) {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-otel-101-demoapp-java-LC35" class="blob-code blob-code-inner js-file-line">                    <span class="pl-c">// Simulate some work for the item</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
          <td id="file-otel-101-demoapp-java-LC36" class="blob-code blob-code-inner js-file-line">                    <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"Processing item "</span> + <span class="pl-s1">i</span>);</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L37" class="blob-num js-line-number js-blob-rnum" data-line-number="37"></td>
          <td id="file-otel-101-demoapp-java-LC37" class="blob-code blob-code-inner js-file-line">                    <span class="pl-c">// Record a metric for the processed item</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L38" class="blob-num js-line-number js-blob-rnum" data-line-number="38"></td>
          <td id="file-otel-101-demoapp-java-LC38" class="blob-code blob-code-inner js-file-line">                    <span class="pl-s1">itemsProcessedCounter</span>.<span class="pl-en">add</span>(<span class="pl-c1">1</span>);</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L39" class="blob-num js-line-number js-blob-rnum" data-line-number="39"></td>
          <td id="file-otel-101-demoapp-java-LC39" class="blob-code blob-code-inner js-file-line">                } <span class="pl-k">finally</span> {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L40" class="blob-num js-line-number js-blob-rnum" data-line-number="40"></td>
          <td id="file-otel-101-demoapp-java-LC40" class="blob-code blob-code-inner js-file-line">                    <span class="pl-s1">itemSpan</span>.<span class="pl-en">end</span>();  <span class="pl-c">// end the item span</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L41" class="blob-num js-line-number js-blob-rnum" data-line-number="41"></td>
          <td id="file-otel-101-demoapp-java-LC41" class="blob-code blob-code-inner js-file-line">                }</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L42" class="blob-num js-line-number js-blob-rnum" data-line-number="42"></td>
          <td id="file-otel-101-demoapp-java-LC42" class="blob-code blob-code-inner js-file-line">            }</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L43" class="blob-num js-line-number js-blob-rnum" data-line-number="43"></td>
          <td id="file-otel-101-demoapp-java-LC43" class="blob-code blob-code-inner js-file-line">        } <span class="pl-k">finally</span> {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L44" class="blob-num js-line-number js-blob-rnum" data-line-number="44"></td>
          <td id="file-otel-101-demoapp-java-LC44" class="blob-code blob-code-inner js-file-line">            <span class="pl-s1">batchSpan</span>.<span class="pl-en">end</span>();  <span class="pl-c">// end the batch span</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L45" class="blob-num js-line-number js-blob-rnum" data-line-number="45"></td>
          <td id="file-otel-101-demoapp-java-LC45" class="blob-code blob-code-inner js-file-line">        }</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L46" class="blob-num js-line-number js-blob-rnum" data-line-number="46"></td>
          <td id="file-otel-101-demoapp-java-LC46" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L47" class="blob-num js-line-number js-blob-rnum" data-line-number="47"></td>
          <td id="file-otel-101-demoapp-java-LC47" class="blob-code blob-code-inner js-file-line">        <span class="pl-c">// Wait briefly to ensure the last metric is exported</span></td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L48" class="blob-num js-line-number js-blob-rnum" data-line-number="48"></td>
          <td id="file-otel-101-demoapp-java-LC48" class="blob-code blob-code-inner js-file-line">        <span class="pl-k">try</span> {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L49" class="blob-num js-line-number js-blob-rnum" data-line-number="49"></td>
          <td id="file-otel-101-demoapp-java-LC49" class="blob-code blob-code-inner js-file-line">            <span class="pl-smi">Thread</span>.<span class="pl-en">sleep</span>(<span class="pl-c1">1500</span>);</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L50" class="blob-num js-line-number js-blob-rnum" data-line-number="50"></td>
          <td id="file-otel-101-demoapp-java-LC50" class="blob-code blob-code-inner js-file-line">        } <span class="pl-k">catch</span> (<span class="pl-smi">InterruptedException</span> <span class="pl-s1">ignored</span>) {</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L51" class="blob-num js-line-number js-blob-rnum" data-line-number="51"></td>
          <td id="file-otel-101-demoapp-java-LC51" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L52" class="blob-num js-line-number js-blob-rnum" data-line-number="52"></td>
          <td id="file-otel-101-demoapp-java-LC52" class="blob-code blob-code-inner js-file-line">        }</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L53" class="blob-num js-line-number js-blob-rnum" data-line-number="53"></td>
          <td id="file-otel-101-demoapp-java-LC53" class="blob-code blob-code-inner js-file-line">    }</td>
        </tr>
        <tr>
          <td id="file-otel-101-demoapp-java-L54" class="blob-num js-line-number js-blob-rnum" data-line-number="54"></td>
          <td id="file-otel-101-demoapp-java-LC54" class="blob-code blob-code-inner js-file-line">}</td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/jigarkb/8d0903a6bcd14bffc745c1a68017169d/raw/badf33f7fa80735e29ceb8bfb20f834dff55663e/OTel-101-DemoApp.java" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/jigarkb/8d0903a6bcd14bffc745c1a68017169d#file-otel-101-demoapp-java" class="Link--inTextBlock">
          OTel-101-DemoApp.java
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div><p>Let&#8217;s walk through this code step by step:</p><ul><li><p>We retrieve a&nbsp;Tracer&nbsp;and&nbsp;Meter&nbsp;from the OpenTelemetry instance. We pass an <strong>instrumentation name</strong>("OTelDemoApp") to identify our tracer and meter. This name can be anything describing your instrumentation or service (often it&#8217;s a package name or component name, optionally with version). It helps group and identify telemetry &#8211; for example, the logging exporter will include this name in span logs (as the &#8220;tracer&#8221; identity). Using a consistent name is useful when you have multiple instrumented components.</p></li><li><p>We create a&nbsp;<code>LongCounter</code>&nbsp;named&nbsp;"processed_items". This is a type of metric instrument suited for counting things. We give it a description and unit (just &#8220;1&#8221; as it counts items). We&#8217;ll use this counter to tally how many items we processed. In OpenTelemetry Metrics, a counter is a monotonic increasing value (it only goes up, and often reported as a rate by monitoring systems).</p></li><li><p>We start a span named&nbsp;"processBatch". This represents the overall work of processing a batch of items. We use <code>tracer.spanBuilder("processBatch").startSpan()</code>&nbsp;to create and start the span. The span is now recording, and we want any work done inside this span to be attributed to it. We therefore use a try-with-resources and <code>batchSpan.makeCurrent()</code>&nbsp;to make this span the&nbsp;current context. This ensures that any new spans created inside will automatically be children of&nbsp;batchSpan&nbsp;(the OpenTelemetry context is propagated within the thread).</p></li><li><p>Inside the batch span&#8217;s scope, we loop over 5 items. For each item, we create a new span&nbsp;"processItem"&nbsp;and make it current inside the loop. This span represents processing of an individual item. Within that span, our simulated work is just a&nbsp;System.out.println&nbsp;(imagine this could be some processing logic or an I/O operation in a real app). We also call&nbsp;itemsProcessedCounter.add(1)&nbsp;to increment our counter metric each time an item is processed.</p></li><li><p>We end each item span when done (in the&nbsp;finally&nbsp;block). After the loop, we exit the batch span&#8217;s try-with-resources, which automatically closes the scope, and then we end the batch span. It&#8217;s important to end spans; ending a span signals to the SDK that the span is complete and ready to be exported.</p></li><li><p>Finally, we sleep for 1.5 seconds. Why? Recall that our metric exporter sends data every 1 second. The sleep ensures that the loop&#8217;s last metric update gets picked up by the periodic reader and logged out. Without this, the program might exit before the last metric export occurs. (In a long-running application this isn&#8217;t needed; metrics would continuously export on the interval. We do it here because this is a short-lived demo program.)</p></li></ul><p>A quick note on the use of&nbsp;Scope&nbsp;and&nbsp;makeCurrent(): This is one way to manage span context. By making a span current, you tie it to the thread context so that any child spans or telemetry in that context automatically knows the parent span. We used try-with-resources for neatness to ensure scopes are closed. You could also manually manage context, but the pattern above is common and ensures parent-child relationships in traces are set up correctly.</p><h3>IV. Running the Application and Viewing the Output</h3><p>Now it&#8217;s time to run our&nbsp;DemoApp&nbsp;and see OpenTelemetry in action! Compile and run the Java program (e.g.,&nbsp;<code>java DemoApp</code>). As the program executes, you&#8217;ll see the&nbsp;System.out.println&nbsp;messages for &#8220;Processing item X&#8221;, and more importantly, you&#8217;ll see log output from OpenTelemetry&#8217;s exporters in the console.</p><p>The&nbsp;<strong>LoggingSpanExporter</strong>&nbsp;will log each span as it ends. You should see log lines for the&nbsp;"processItem"&nbsp;spans and the&nbsp;"processBatch"&nbsp;span. They will look something like:</p><pre><code>INFO io.opentelemetry.exporter.logging.LoggingSpanExporter - 'processItem' : 6f9a2f3d2eae4ac9be405ea3d1e2f847  d2e9f12bb6f1d3c9 INTERNAL [tracer: OTelDemoApp] AttributesMap{data={}}</code></pre><p>Each span log includes the span name (in quotes), the trace ID and span ID, the span kind (INTERNAL, since these are internal spans), the tracer name (which includes our instrumentation name &#8220;OTelDemoApp&#8221;), and any attributes (none in our simple example). You&#8217;ll have five lines similar to the above for each&nbsp;"processItem"&nbsp;(they will share the same trace ID, since they are part of the same trace, and have different span IDs). Finally, you&#8217;ll see the&nbsp;"processBatch"&nbsp;span logged with the same trace ID (as parent) once it ends.</p><p>The&nbsp;<strong>LoggingMetricExporter</strong>&nbsp;will log metrics on the set interval. Since we kept the program alive for a bit, it should have exported at least one metric update. The output might be a bit verbose, but essentially it will indicate the metric name (processed_items) and the value. For example, it could log something like:</p><pre><code>INFO io.opentelemetry.exporter.logging.LoggingMetricExporter - Received a collection of 1 metrics for export
INFO io.opentelemetry.exporter.logging.LoggingMetricExporter - Instrument: processed_items, Total: 5</code></pre><p><em>(The exact format may vary, but the key is that our counter&#8217;s value (5) gets reported.)</em>&nbsp;This indicates that 5 items were processed, as expected.</p><p>Check that the trace logs and metric log make sense: All 5 item spans should have the same trace ID (meaning they are all part of one trace corresponding to the batch), and the batch span is the parent. The metric count should equal 5 at the end. If you see those, congratulations &#8211; you have successfully instrumented a Java app with OpenTelemetry!</p><h3>V. Next Steps and Best Practices</h3><p>We&#8217;ve kept this example simple, but you&#8217;ve learned the fundamentals of using OpenTelemetry in Java:</p><ul><li><p>Initializing the OpenTelemetry SDK with an exporter (console logging in our case).</p></li><li><p>Creating a tracer and spans to generate trace data (with parent-child relationships).</p></li><li><p>Creating a meter and counter to collect metric data.</p></li><li><p>Verifying that telemetry is exported (seeing it in console logs).</p></li></ul><p>From here, there are many directions to go:</p><ul><li><p><strong>Use a real backend:</strong>&nbsp;Instead of logging to console, you can configure other exporters. For example, you could use the OTLP exporter to send data to an OpenTelemetry Collector, or use Jaeger/Zipkin exporters to send traces to those systems. With a backend like <a href="http://jaegertracing.io/?ref=observability.how">Jaeger</a>, you could visualize the trace we created in a web UI, seeing the hierarchy of spans and their durations. Using <a href="https://prometheus.io/?ref=observability.how">Prometheus</a> or another metrics backend, you could scrape or receive the metric we created and observe it over time. OTel makes it easy to switch exporters &#8211; you&#8217;d just swap out the Logging exporter for another in the initialization step (and perhaps adjust configuration like endpoints).</p></li><li><p><strong>Automatic instrumentation:</strong>&nbsp;In our tutorial, we did manual instrumentation (we wrote code to create spans and metrics). OpenTelemetry also supports auto-instrumentation via the Java Agent, which can instrument many libraries/frameworks without code changes. For instance, if our app were a Spring Boot service, the OTel Java agent could automatically trace incoming HTTP requests, database calls, etc. Auto-instrumentation can jump-start your observability with minimal effort, though manual instrumentation (as we did) is still useful for business-specific code and custom metrics.</p></li><li><p><strong>Add more telemetry:</strong>&nbsp;We only scratched the surface by recording one metric and very simple spans. In a real app, you might instrument multiple operations with spans, add attributes to spans (e.g., to record context like order ID, user ID, etc.), record additional metrics (gauges, histograms for latencies, etc.), and attach logs to traces. OpenTelemetry allows you to correlate all three signal types (traces, metrics, logs) for a holistic view.</p></li><li><p><strong>Learn the API in depth:</strong>&nbsp;The OpenTelemetry API has more to offer &#8211; for example, context propagation across threads or services (so traces can continue across network calls), configuring&nbsp;<strong>Samplers</strong>&nbsp;to control tracing volume, and <strong>Propagators</strong>&nbsp;for context (e.g., W3C Trace Context). As a beginner, you don&#8217;t need to master these upfront, but be aware they exist for advanced use cases.</p></li></ul><div><hr></div><p>OpenTelemetry provides a powerful, standardized way to make your applications observable. In this guide, we introduced OTel and demonstrated a basic Java instrumentation that prints traces and metrics to the console. You saw how the OpenTelemetry API and SDK work together: the API lets us define spans and metrics in code, while the SDK handles exporting that data. We also discussed OTel&#8217;s architecture, including the optional Collector that can sit between your app and telemetry backends for added flexibility.</p><p>By implementing OTel in even a simple program, you&#8217;ve taken the first steps toward robust observability. From here, you can confidently instrument more complex applications, knowing that the same concepts apply. As you grow, you might integrate with production-grade backends, leverage auto-instrumentation, and fine-tune what you collect &#8211; all while relying on OpenTelemetry as a consistent framework. Observability is a journey, but with OpenTelemetry, getting started is no longer the hardest part. Happy tracing!</p><div><hr></div><p><strong>Source code:</strong> <a href="https://github.com/ObservabilityHow/OTel-101?ref=observability.how">https://github.com/ObservabilityHow/OTel-101</a></p>]]></content:encoded></item><item><title><![CDATA[Glossary of Observability Terms (Beginner’s Cheat Sheet)]]></title><description><![CDATA[Welcome to the world of observability! If you&#8217;re new to this field, all the jargon and acronyms can feel overwhelming.]]></description><link>https://www.observability.how/p/glossary-of-observability-terms-beginners-cheat-sheet</link><guid isPermaLink="false">https://www.observability.how/p/glossary-of-observability-terms-beginners-cheat-sheet</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Sun, 13 Apr 2025 07:44:40 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/23badbbe-f4e8-4a93-afdf-5980416b9c8c_2000x1333.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HClR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HClR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HClR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HClR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HClR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HClR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Glossary of Observability Terms (Beginner&#8217;s Cheat Sheet)&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Glossary of Observability Terms (Beginner&#8217;s Cheat Sheet)" title="Glossary of Observability Terms (Beginner&#8217;s Cheat Sheet)" srcset="https://substackcdn.com/image/fetch/$s_!HClR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HClR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HClR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HClR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79912601-72d1-4a40-8f2c-f703fc3a21dd_2000x1333.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><p><em>Welcome to the world of observability!</em>&nbsp;If you&#8217;re new to this field, all the jargon and acronyms can feel overwhelming. But fear not&#8212;this beginner&#8217;s cheat sheet will walk you through the&nbsp;<strong>essential observability terms</strong>&nbsp;in plain language.</p><p>Use it as a reference whenever you encounter an unfamiliar term, or read it straight through to build a solid foundation. Let&#8217;s dive in!</p><h4>Aggregation</h4><p><strong>Aggregation</strong>&nbsp;is the process of combining data and summarizing it. In observability, this often means taking a large set of raw data points and rolling them up into a summary statistic or group. For example, instead of recording every single response time, you might aggregate them into an average response time per minute. Aggregation reduces data volume and makes trends easier to see &#8211; think of it as&nbsp;<strong>summarizing a book into key bullet points</strong>&nbsp;so you get the gist without reading every word.</p><h4>Alerting</h4><p><strong>Alerting</strong>&nbsp;is the practice of sending out notifications when something important happens or when predefined conditions are met. In the context of observability, you set up rules or thresholds for your system&#8217;s metrics and logs, and if those rules are violated, an alert (message) is sent to your team. For example, you might receive an alert if a server&#8217;s CPU usage stays above 90% for too long or if an application&#8217;s error rate suddenly spikes. Alerts are like&nbsp;<strong>smoke alarms for your software</strong>&#8212; they loudly warn you when there&#8217;s a fire (issue) so you can respond quickly. Good alerting helps ensure you discover problems&nbsp;<em>before</em>&nbsp;your users do.</p><h4><strong>APM (Application Performance Monitoring)</strong></h4><p><strong>APM</strong>&nbsp;stands for&nbsp;<strong>Application Performance Monitoring</strong>&nbsp;(sometimes &#8220;Application Performance Management&#8221;). It refers to tools and practices for tracking how well your applications are performing. APM involves measuring things like response times, error rates, transaction throughput, and resource usage (CPU, memory, etc.) to detect performance issues&nbsp;. Essentially, APM is like a&nbsp;<strong>health tracker for your apps</strong>&nbsp;&#8211; it keeps an eye on your application&#8217;s vital signs and tells you if something is wrong. For example, an APM tool might show you that a database query in your login service is slowing down the entire app, so you know exactly where to fix the problem to ensure users have a smooth experience.</p><h4><strong>Cardinality</strong></h4><p>In data terms,&nbsp;<strong>cardinality</strong>&nbsp;means the number of unique values in a set. In observability, we often talk about cardinality in the context of metrics or logs. For example, the cardinality of a &#8220;user ID&#8221; field in your logs is the number of different user IDs that appear. High cardinality means there are <em>lots</em>&nbsp;of unique values. High cardinality can strain monitoring systems because there&#8217;s more data variety to handle.&nbsp;<strong>Think of cardinality as &#8220;variety&#8221;</strong>: a low-cardinality metric is like an ice cream shop with only vanilla and chocolate, whereas a high-cardinality metric is like one with 50 flavors plus all the toppings &#8211; richer detail, but heavier to manage.</p><h4>Collector</h4><p>A&nbsp;<strong>collector</strong>&nbsp;is a component or service that gathers telemetry data and funnels it to where it needs to go. It acts as a central hub that&nbsp;<strong>collects, processes, and exports</strong>&nbsp;observability data (logs, metrics, traces) from one or many sources. It&#8217;s like a postal sorting office for telemetry: the collector receives all the data &#8220;mail,&#8221; sorts and packages it, and then delivers it to the right destination (usually an observability backend or database). Using a collector centralizes your data collection, making it easier to manage and route telemetry from your apps to your monitoring tools.</p><h4>Dashboard</h4><p>In observability, a&nbsp;<strong>dashboard</strong>&nbsp;is a customizable display or&nbsp;<strong>visual board</strong>&nbsp;that shows important metrics and data visualizations (graphs, charts, tables) about your system in real time. Dashboards are like an airplane cockpit for your software &#8211; at a glance, you can see key indicators like CPU usage, request rates, error counts, or whatever matters to you. Teams set up dashboards to monitor the health and performance of services. For example, you might have a dashboard for your website that shows the number of active users, request latency, and error rate all in one view. A well-crafted dashboard helps you&nbsp;<strong>quickly interpret</strong>&nbsp;complex data and spot anomalies or trends (say, a sudden drop in user sign-ups) without combing through raw logs.</p><h4><strong>Distributed Tracing</strong></h4><p><strong>Distributed tracing</strong>&nbsp;is a technique for tracking the path of a single request or transaction as it moves through a distributed system (for example, through multiple microservices). When a user performs an action &#8211; like clicking &#8220;Purchase&#8221; on a website &#8211; that request may travel through many different services (authentication service, order service, payment service, etc.). Distributed tracing follows that journey and records each step of the process. It&#8217;s like&nbsp;<strong>following a trail of breadcrumbs</strong>&nbsp;through your services to see where time is spent or where errors occur. By looking at a distributed trace, you can identify bottlenecks or failures &#8211; for instance, you might discover that the payment service was slow or a database call errored out. Each step in a distributed trace is called a&nbsp;<strong>span</strong>&nbsp;(see&nbsp;<strong>Span</strong>&nbsp;below), and together all the spans form the complete trace. Distributed tracing is invaluable for understanding how different parts of a system work together and for troubleshooting issues that span -no pun intended- multiple services.</p><h4>Exporter</h4><p>An&nbsp;<strong>exporter</strong>&nbsp;is a component or plugin that&nbsp;<strong>sends telemetry data from one system to another</strong>. In many observability setups, exporters are used to get metrics or logs out of a system and into a monitoring platform. For example, with Prometheus (a popular open-source monitoring tool), you might use a&nbsp;<em>Node Exporter</em>&nbsp;on a Linux server to expose CPU, memory, and disk metrics in a format Prometheus can scrape. Essentially, exporters act as <strong>translators or data shippers</strong>&nbsp;&#8211; they take internal data and present it in the right format for your observability system to consume. This allows data from various systems (databases, servers, applications) to be exported and analyzed in a centralized monitoring tool.</p><h4>Instrumentation</h4><p><strong>Instrumentation</strong>&nbsp;is the act of adding code (or using tools) in your application to collect telemetry data about its behavior and performance. When you instrument an application, you insert &#8220;sensors&#8221; into the code &#8211; capturing metrics (e.g. how long a function takes or how often an event happens), tracing operations, or logging important events. It&#8217;s like outfitting a car with gauges and sensors: without instrumentation, you&#8217;re driving blind, but with it, you have a speedometer, fuel gauge, and other dials. Similarly, with software, instrumentation gives you insight into what&#8217;s happening inside your application. Good instrumentation is the foundation of observability &#8211; it provides the raw data (metrics, logs, traces) that all your monitoring and analysis tools rely on.</p><h4>Logs</h4><p><strong>Logs</strong>&nbsp;are&nbsp;<strong>textual records</strong>&nbsp;of events that happen within a system. Whenever something noteworthy occurs in an application or on a server &#8211; for example, an error, a user action, or a configuration change &#8211; it can be recorded as a log entry. Logs are usually timestamped and can include details like severity level (Info, Warning, Error) and contextual information (e.g., which user or process triggered the event). In everyday terms, logs are like a&nbsp;<strong>diary or journal</strong>&nbsp;for your application, recording what happened and when. They are incredibly useful for debugging and forensic analysis &#8211; when something goes wrong, reading the logs lets you trace the sequence of events leading up to the issue. Logs may be plain text or structured (e.g., in JSON format). They are one of the&nbsp;<em>three pillars of observability</em>, alongside metrics and traces, because they provide a detailed narrative of system activity.</p><h4>Metrics</h4><p><strong>Metrics</strong>&nbsp;are&nbsp;<strong>numeric measurements</strong>&nbsp;about your system, tracked over time. Common metrics include things like CPU usage percentage, memory consumption, request rate (requests per second), error rate, and response latency. These are typically collected at regular intervals (for example, every 10 seconds) which lets you see historical trends &#8211; like &#8220;CPU usage spiked to 90% at 2:00 AM&#8221; or &#8220;we had double the traffic on Friday compared to Thursday.&#8221; Metrics are easy to graph on dashboards to observe patterns and are often used to trigger alerts when they go out of expected ranges. In short, metrics are like&nbsp;<strong>the vital signs of your application</strong>&nbsp;&#8211; they quantify aspects of system performance and health (how much, how many, how fast, how slow). They help answer questions such as &#8220;Is our error rate higher today?&#8221; or &#8220;What&#8217;s the average response time right now?&#8221;</p><h4>Monitoring</h4><p><strong>Monitoring</strong>&nbsp;is the practice of continuously observing the state of your system by tracking a set of predefined metrics and logs, and alerting when something seems wrong. With monitoring, you might set up dashboards and alerts for things like uptime, CPU load, or error rate. For example, you monitor a web server&#8217;s response time and set an alert if it exceeds 500 milliseconds on average. Monitoring is essentially a subset of observability&nbsp;&#8211; it focuses on the key metrics and thresholds you predict might fail. It&#8217;s very useful for catching obvious issues (e.g., &#8220;server down&#8221; or &#8220;disk 95% full&#8221;) through automated checks and alarms.</p><h4>Observability</h4><p><strong><a href="https://www.observability.how/what-is-observability-metrics-logs-and-traces-demystified/">Observability</a></strong>&nbsp;is the ability to understand what&#8217;s happening inside a complex system by looking at the data it produces on the outside. In practical terms, it means using telemetry data &#8211;&nbsp;<strong>logs, metrics, and traces</strong>&nbsp;(often called the three pillars of observability) &#8211; to infer the internal state and health of your applications. When a system is highly observable, you can answer almost any question about its behavior by examining its external outputs, without needing to add new probes or instrumentation each time. Observability is like being a doctor who can diagnose an illness from symptoms and test results &#8211; you don&#8217;t need to take the patient apart to know what&#8217;s wrong; you use the signals they give off (fever, blood pressure, etc.) to figure it out. In the software world, those signals are your logs, metrics, traces, and other telemetry. A strong observability setup means engineers can explore the&nbsp;<em>why</em>&nbsp;behind issues (not just detect that an issue happened).</p><h4>OpenTelemetry</h4><p><strong>OpenTelemetry</strong>&nbsp;(often abbreviated&nbsp;<strong>OTel</strong>) is an open-source collection of tools, APIs, and SDKs for instrumenting software and collecting telemetry data. It provides a&nbsp;<em><a href="https://opentelemetry.io/?ref=observability.how">standardized framework</a></em>&nbsp;to generate and export observability data (logs, metrics, traces) in a vendor-neutral way. OpenTelemetry defines a common language for telemetry so that you can instrument your code once and send the data to many different backend systems that support OTel. Think of OpenTelemetry as a&nbsp;<strong>universal telemetry toolkit</strong>&nbsp;&#8211; instead of each monitoring vendor having its own agent or format, they all collaborate on OTel. By using OpenTelemetry libraries in your application, you can switch or send data to different observability platforms (open-source or commercial) without changing your instrumentation. This flexibility has made OpenTelemetry a key part of modern observability, as it avoids vendor lock-in and encourages interoperability across tools.</p><h4>OTLP <strong>(OpenTelemetry Protocol)</strong></h4><p><strong>OTLP</strong>&nbsp;stands for the&nbsp;<strong>OpenTelemetry Protocol</strong>. It is the protocol used by OpenTelemetry to transmit telemetry data over the network. In simple terms, OTLP is the format or &#8220;language&#8221; that OpenTelemetry speaks when sending data (spans, metrics, logs) from your applications to a backend or collector. It&#8217;s designed to be efficient and vendor-neutral. You can think of OTLP as the&nbsp;<strong>postal service for your telemetry</strong>: it defines how telemetry data is packaged up and delivered so that any OTLP-compatible receiver can understand it. The benefit of having a standard like OTLP is that all your services and tools can communicate observability data seamlessly &#8211; if your app and your monitoring backend both support OTLP, they can talk to each other without custom adapters.</p><h4>PromQL</h4><p><strong><a href="https://prometheus.io/docs/prometheus/latest/querying/basics/?ref=observability.how">PromQL</a></strong>&nbsp;is the&nbsp;<strong>Prometheus Query Language</strong>, used to query and aggregate data from Prometheus &#8211; a popular open-source time-series database for metrics. If your metrics are stored in Prometheus, PromQL is how you ask questions about that data. It&#8217;s a flexible, functional language that lets you filter metrics and apply calculations on the fly. For example, you could write a PromQL query to get the average CPU usage of a service over the last 5 minutes, or to get the 99th percentile response time of an API endpoint. Think of PromQL as&nbsp;<strong>Excel formulas for time-series data</strong>&nbsp;&#8211; instead of cells and columns, you have metric names and time ranges, but you can sum them up, average them, take maximums, etc., often grouping by labels (like grouping metrics per service or per datacenter). PromQL&#8217;s power allows you to create dynamic dashboards and set up precise alerts (e.g., &#8220;alert if 5-minute error rate &gt; 1%&#8221;). While it has its own syntax, with a bit of practice you can extract very rich insights from your metrics using PromQL.</p><h4>Sampling</h4><p>In observability,&nbsp;<strong>sampling</strong>&nbsp;means recording only a subset of all data points rather than everything. This is usually done to control overhead and cost when there&#8217;s a high volume of telemetry data. For example, instead of collecting&nbsp;<strong>every</strong>&nbsp;single request trace in a high-traffic system (which could be millions of traces), you might only sample 1% of requests and ignore the rest. The idea is that a representative sample of data can still tell you what&#8217;s going on, at a fraction of the cost. It&#8217;s analogous to polling a small percentage of voters to predict an election result instead of surveying everyone. The trade-off is that you lose some detail (there&#8217;s a chance an infrequent error or outlier might not be captured if it falls outside the sample), but you&nbsp;<strong>greatly reduce overhead</strong>&nbsp;in terms of storage and processing. Different sampling strategies exist (fixed-rate, random, or more intelligent ones that try to keep &#8220;interesting&#8221; events), but all share the goal of balancing visibility with efficiency.</p><h4>Service Map</h4><p>A&nbsp;<strong>service map</strong>&nbsp;is a visual representation of how the different services or components in your architecture connect and interact with each other. If you have a bunch of microservices, a service map will show each service as a node and draw lines (edges) between them to indicate which services talk to which. It&#8217;s like an&nbsp;<strong>architectural map</strong>&nbsp;for your software system. Service maps are often generated automatically using data from distributed tracing or network telemetry. They help you see the big picture of your system&#8217;s topology: for example, you can quickly grasp that&nbsp;<em>Service A</em>&nbsp;calls&nbsp;<em>Service B </em>and&nbsp;<em>Service C</em>, and&nbsp;<em>Service C</em>&nbsp;in turn calls&nbsp;<em>Service D</em>. This is useful for understanding dependencies and figuring out what might be impacted when one service has an issue. In short, a service map helps connect the dots, giving you a bird&#8217;s-eye view of your system&#8217;s structure that complements the detailed data you get from logs and metrics.</p><h4>SLA <strong>(Service Level Agreement)</strong></h4><p>A&nbsp;<strong>Service Level Agreement (SLA)</strong>&nbsp;is a formal (often contractual) commitment between a service provider and a customer that defines the expected level of service. It usually specifies concrete targets like uptime, responsiveness, or throughput over a period (for example, 99.9% uptime per month) and the remedies if those targets are not met. In essence, an SLA is the &#8220;official promise&#8221; of service quality. If the provider fails to meet the agreed targets, the SLA typically outlines consequences, such as service credits or penalties. SLAs often incorporate one or more SLOs (see below) as the specific objectives that must be met, but an SLA adds legal weight &#8211; it&#8217;s what you can hold the provider accountable to. Think of an SLA as a guarantee: it sets clear expectations for performance and reliability, and it manages risk for the customer. Because breaking an SLA can have business or legal implications, these agreements are usually carefully defined and tracked.</p><h4>SLI <strong>(Service Level Indicator)</strong></h4><p>A&nbsp;<strong>Service Level Indicator (SLI)</strong>&nbsp;is a specific metric or measurement that indicates how well a service is performing in a certain area. It&#8217;s essentially the&nbsp;<strong>measurement of something that matters to users</strong>. Common SLIs include things like availability (uptime percentage), latency (for example, &#8220;95% of requests complete in under 200ms&#8221;), throughput (requests per second), and error rate. In short, an SLI is the&nbsp;<em>quantitative indicator</em>&nbsp;of some aspect of service quality. If you think of a service level as a concept (say &#8220;reliability&#8221;), the SLI is how you measure it (&#8220;99.99% uptime&#8221; or &#8220;error rate = 0.1%&#8221;). These indicators are the building blocks for defining objectives and agreements &#8211; you set SLOs (objectives) and SLAs (agreements) based on SLIs. For example, if one SLI is &#8220;error rate = 0.1%,&#8221; the SLO might be to keep that error rate below 1% over a month, and the SLA might formalize that as a promise. In summary, SLIs tell you&nbsp;<strong>how you&#8217;re measuring success</strong>&nbsp;for a service&#8217;s attribute, and they provide the data for SLOs and SLAs&nbsp;.</p><h4>SLO <strong>(Service Level Objective)</strong></h4><p>A&nbsp;<strong>Service Level Objective (SLO)</strong>&nbsp;is a&nbsp;<strong>target or goal</strong>&nbsp;for a service&#8217;s performance or reliability, defined for a specific metric (SLI) over a period of time. It&#8217;s what your team&nbsp;<em>aims for</em>&nbsp;to ensure a good user experience. For example, an SLO might be&nbsp;<em>99.5% uptime</em>&nbsp;for your service each quarter, or <em>95% of API responses under 300ms</em>&nbsp;over the last 7 days. SLOs are usually internal goals and are often expressed as percentages or thresholds. They&#8217;re not customer-facing promises (that would be an SLA), but they guide your engineering and operations decisions. If your service stays within SLO, you&#8217;re meeting your reliability targets; if it consistently misses the SLO, that&#8217;s a signal to invest in improvements. Think of an SLO as the <strong>performance bar</strong>&nbsp;you set for your service &#8211; &#8220;we want to be&nbsp;<em>this</em>&nbsp;reliable or better.&#8221; By tracking SLOs, teams can balance pushing new features with maintaining quality (as in SRE practices with error budgets). In essence, SLOs help you answer &#8220;Are we meeting our reliability/performance goals?&#8221; and drive action if you&#8217;re not.</p><h4>Span</h4><p>A&nbsp;<strong><a href="https://opentelemetry.io/docs/concepts/signals/traces/?ref=observability.how#spans">span</a></strong>&nbsp;is a single operation or unit of work within a distributed trace. Each span has a name (what operation it represents), a start time and end time (so you know its duration), and metadata (tags or context about what it did). Spans can be&nbsp;<strong>nested</strong>: for example, if Service A calls Service B as part of handling a request, Service A&#8217;s span will be the parent and Service B&#8217;s span will be a child. In a trace, multiple spans are connected to form the full picture of a request. By examining spans in a trace, you can see which step took the longest or where an error occurred. In other words, spans let you <strong>zoom in</strong>&nbsp;on individual steps of a transaction, providing detailed context for each part of a workflow. They are the building blocks of distributed tracing &#8211; every trace consists of one or more spans linked together.</p><h4>Telemetry</h4><p>In software,&nbsp;<strong>telemetry</strong>&nbsp;refers to the data that a system produces about its own state and operations, which is collected for monitoring and analysis. In observability, telemetry typically includes all the logs, metrics, traces, and other signals emitted by your applications and infrastructure. The word comes from Greek roots meaning &#8220;remote measurement&#8221;, and that&#8217;s exactly what it is &#8211; measurements sent from your system to an external location (like your observability platform). It&#8217;s like how a spacecraft continuously sends status data back to mission control so engineers can understand what&#8217;s happening on the ship. Similarly, your services send telemetry data (e.g., CPU metrics, error logs, request traces) to your monitoring tools. Telemetry is the lifeblood of observability: without it, you&#8217;d be &#8220;flying blind&#8221; with no insight into your system&#8217;s behavior. Modern telemetry often relies on standardized protocols (like OTLP) and formats, so different systems can share and aggregate this data. Simply put,&nbsp;<strong>telemetry is all the data your system is telling you about itself</strong>&nbsp;&#8211; and observability is about listening to and making sense of that data.</p><h4>Trace</h4><p>A&nbsp;<strong><a href="https://opentelemetry.io/docs/concepts/signals/traces/?ref=observability.how">trace</a></strong>&nbsp;represents the end-to-end journey of a single request through a system, composed of a series of spans (each span is one step or operation). It shows how a request travels from one service or component to the next and how long each step takes. Traces are very useful for diagnosing performance issues and understanding service dependencies. By looking at a trace, you can pinpoint&nbsp;<strong>which part of a workflow</strong>&nbsp;caused a slowdown or an error &#8211; for example, you might see that a database query took 5000ms while all other steps were fast, indicating a database bottleneck. In essence, a trace links together all the related operations for one transaction, giving you a detailed story of that request. This distributed context is something you don&#8217;t get from metrics alone, which is why traces (along with logs and metrics) are such an important pillar of observability.</p><div><hr></div><p>With this glossary at your fingertips, you should feel more comfortable navigating conversations and documentation about observability. When someone throws out an acronym like &#8220;SLO&#8221; or mentions &#8220;instrumenting with OpenTelemetry&#8221;, you&#8217;ll know exactly what they mean. Observability is a big field, but these core concepts will serve as your foundation as you dive deeper.</p><p><em>Happy Monitoring!</em>&nbsp;(And remember, now you can explain the difference between <strong>monitoring</strong>&nbsp;and&nbsp;<strong>observability</strong>&nbsp;too.) Keep this cheat sheet handy as you explore tools and techniques &#8212; and soon enough, you&#8217;ll be the one explaining these terms to others.</p>]]></content:encoded></item><item><title><![CDATA[What is Observability? – Metrics, Logs, and Traces Demystified]]></title><description><![CDATA[Imagine you&#8217;re a detective for software systems.]]></description><link>https://www.observability.how/p/what-is-observability-metrics-logs-and-traces-demystified</link><guid isPermaLink="false">https://www.observability.how/p/what-is-observability-metrics-logs-and-traces-demystified</guid><dc:creator><![CDATA[Jigar Bhatt]]></dc:creator><pubDate>Sun, 13 Apr 2025 06:03:38 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/2eea1394-f04e-4824-86f2-a5ec578abfba_2000x1333.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YP9h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YP9h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YP9h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YP9h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YP9h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YP9h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;What is Observability? &#8211; Metrics, Logs, and Traces Demystified&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="What is Observability? &#8211; Metrics, Logs, and Traces Demystified" title="What is Observability? &#8211; Metrics, Logs, and Traces Demystified" srcset="https://substackcdn.com/image/fetch/$s_!YP9h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YP9h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YP9h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YP9h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c434f92-f4b7-470a-ba0a-51bf4bebceca_2000x1333.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Imagine you&#8217;re a detective for software systems. Late one night, an alert goes off: something is wrong with your application. But&nbsp;what&nbsp;is wrong? In a complex microservices environment, finding the culprit can feel like searching for a needle in a haystack. This is where&nbsp;<strong>observability</strong>&nbsp;comes in.&nbsp;Observability&nbsp;is about gaining insight into the internal state of a system by looking at its outputs (like logs, metrics, and traces), so you can understand not just&nbsp;<em>that</em>&nbsp;something failed, but&nbsp;<em>why</em>&nbsp;and&nbsp;<em>where</em>. In simpler terms, it&#8217;s like a mechanic figuring out why a car won&#8217;t start by reading the sensor output &#8211; without taking the engine apart.</p><p>In modern software, observability has become a&nbsp;buzzword, but for good reason. Today&#8217;s applications are distributed across many services and containers. Traditional monitoring (checking a few metrics or logs) is often not enough to troubleshoot issues in these&nbsp;<strong>complex systems</strong>. We need a more holistic approach. This article will demystify observability from the ground up. We&#8217;ll explain why observability matters, how it differs from traditional monitoring, and break down its three &#8220;pillars&#8221; &#8211;&nbsp;<strong>metrics, logs, and traces</strong>&nbsp;&#8211; with simple real-world analogies to make the concepts easy to grasp.</p><div><hr></div><h2><strong>Monitoring vs. Observability</strong></h2><p>Before diving into the details, it&#8217;s important to clarify&nbsp;observability vs. monitoring. These two terms are related but not identical. In fact, monitoring is a part of observability, but observability goes beyond just monitoring.</p><p><strong>Monitoring</strong>&nbsp;generally refers to watching a system&#8217;s health and performance over time. You pick a set of metrics or conditions to track (CPU usage, error rates, etc.) and set up dashboards or alerts to tell you when something is off. Monitoring is usually <strong>reactive</strong>&nbsp;&#8211; it answers the question &#8220;<strong>Is my system working correctly right now?</strong>&#8221;. For example, you monitor uptime or CPU usage and get alerted when they go out of bounds. Monitoring is great for known issues and predefined failure modes. If a disk fills up or a server goes down, monitoring should catch it.</p><p><strong>Observability</strong>, on the other hand, is a broader property of a system. It&#8217;s essentially the ability to understand&nbsp;<strong>why </strong>something is happening inside the system, even if it&#8217;s a new or unforeseen issue. In other words, observability is <strong>proactive</strong>&nbsp;rather than reactive. While monitoring asks &#8220;Is everything OK?&#8221;, observability asks &#8220;<strong>What&#8217;s going on inside the system?</strong>&#8221;. An observable system exposes rich telemetry data that allows engineers to trace problems to their root cause without guesswork.</p><div class="pullquote"><p>Monitoring is like checking a patient&#8217;s vital signs, whereas observability is like doing medical tests to diagnose the issue when the patient isn&#8217;t feeling well. Monitoring might tell you the patient has a fever, but observability reveals the infection causing it by looking at various test results.</p></div><p>Why does this matter today? Modern systems (e.g. microservices in the cloud) are highly complex and unpredictable. Observability equips you to handle this complexity. It<em> goes beyond mere issue detection to ensure system integrity</em>.</p><div><hr></div><h2><strong>The Three Pillars of Observability</strong></h2><p>In observability, these three types of telemetry are often referred to as the&nbsp;<strong>three pillars</strong>&nbsp;of observability. Each provides a unique perspective, and together they give a comprehensive view.</p><h3><strong>Metrics</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5d6f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5d6f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png 424w, https://substackcdn.com/image/fetch/$s_!5d6f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png 848w, https://substackcdn.com/image/fetch/$s_!5d6f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png 1272w, https://substackcdn.com/image/fetch/$s_!5d6f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5d6f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png" width="400" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;What is Observability? &#8211; Metrics, Logs, and Traces Demystified&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="What is Observability? &#8211; Metrics, Logs, and Traces Demystified" title="What is Observability? &#8211; Metrics, Logs, and Traces Demystified" srcset="https://substackcdn.com/image/fetch/$s_!5d6f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png 424w, https://substackcdn.com/image/fetch/$s_!5d6f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png 848w, https://substackcdn.com/image/fetch/$s_!5d6f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png 1272w, https://substackcdn.com/image/fetch/$s_!5d6f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde252f78-2c3c-4406-82e1-82a96bc894e5_400x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Metrics</strong>&nbsp;are numeric measurements that are tracked over time. If you think of your software system as a living organism, metrics are like its vital signs. They are typically things you can measure as a number and plot on a graph. For example: the number of requests your web server handles per second, the amount of memory in use (MB), or the latency of an API call (ms).</p><p>Metrics are usually collected at regular intervals (e.g. every 10 seconds) and are great for showing&nbsp;<strong>trends and patterns </strong>over time. One data point is useful, but the real power of metrics is seeing how they change over time. Metrics give you a fast heartbeat check of system health. If something deviates from the norm, metrics are often the first indicators (e.g. a sudden drop to zero in request count might mean a crash, a spike in latency might signal a bottleneck).</p><p>Metrics also enable&nbsp;<strong>monitoring and alerts</strong>. You can set thresholds on metric values to trigger alerts &#8211; for instance, if error rate goes above 5% or CPU usage stays over 90% for a period.</p><div class="pullquote"><p>Metrics are like a car&#8217;s dashboard gauges. If the engine temperature suddenly shoots up, it warns you of a problem (maybe a coolant leak). Similarly, if your website&#8217;s response time metric spikes, it flags a performance issue.</p></div><p>However, metrics usually lack detail about individual events. Metrics might tell you <em>that</em> something went wrong, but not the specifics of any single failure. That&#8217;s where the next pillar comes in.</p><h3><strong>Logs</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OYci!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OYci!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png 424w, https://substackcdn.com/image/fetch/$s_!OYci!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png 848w, https://substackcdn.com/image/fetch/$s_!OYci!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png 1272w, https://substackcdn.com/image/fetch/$s_!OYci!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OYci!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png" width="400" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;What is Observability? &#8211; Metrics, Logs, and Traces Demystified&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="What is Observability? &#8211; Metrics, Logs, and Traces Demystified" title="What is Observability? &#8211; Metrics, Logs, and Traces Demystified" srcset="https://substackcdn.com/image/fetch/$s_!OYci!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png 424w, https://substackcdn.com/image/fetch/$s_!OYci!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png 848w, https://substackcdn.com/image/fetch/$s_!OYci!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png 1272w, https://substackcdn.com/image/fetch/$s_!OYci!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca91b050-fb58-4825-aaaa-ae9e67c8f975_400x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Logs</strong>&nbsp;are the chronicle of events happening in your systems. A log is typically a timestamped record of some event or message emitted by an application or service to describe what it&#8217;s doing. Logs are like a detailed journal or a black-box recorder &#8211; they capture what happened and when, often with rich context.</p><p>Logs provide the&nbsp;<strong>detailed context</strong>&nbsp;behind the metrics. They answer questions like &#8220;What exactly happened?&#8221; and &#8220;Why?&#8221;. For example, an error log might indicate that a payment failed due to an&nbsp;<strong>expired card</strong>, or that there was a <strong>timeout connecting to an external service</strong>. This kind of information goes beyond what a metric can tell you.</p><p>Logs are invaluable for&nbsp;<strong>debugging</strong>&nbsp;and forensic analysis. When something goes wrong, engineers comb through logs to find error messages, stack traces, or specific events leading up to the failure. If a metric shows a spike in errors, the logs will often reveal the exact error messages (e.g. &#8220;Database connection timeout&#8221; or &#8220;NullPointerException in OrderService&#8221;) and even the affected request or user ID. This is crucial for understanding the cause of the problem.</p><p>In a distributed system, logs from different services are usually aggregated using log management tools so you can search them in one place. Given their volume, logs are typically analyzed on demand (when investigating issues) rather than watched continuously like metrics. Logs give a ton of detail, but on their own, they don&#8217;t easily show how an event flows through multiple services. To trace the path of an event through the system, we need the third pillar: tracing.</p><h3><strong>Traces</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NY0Q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NY0Q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png 424w, https://substackcdn.com/image/fetch/$s_!NY0Q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png 848w, https://substackcdn.com/image/fetch/$s_!NY0Q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png 1272w, https://substackcdn.com/image/fetch/$s_!NY0Q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NY0Q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png" width="400" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;What is Observability? &#8211; Metrics, Logs, and Traces Demystified&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="What is Observability? &#8211; Metrics, Logs, and Traces Demystified" title="What is Observability? &#8211; Metrics, Logs, and Traces Demystified" srcset="https://substackcdn.com/image/fetch/$s_!NY0Q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png 424w, https://substackcdn.com/image/fetch/$s_!NY0Q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png 848w, https://substackcdn.com/image/fetch/$s_!NY0Q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png 1272w, https://substackcdn.com/image/fetch/$s_!NY0Q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcde2b68-234b-45ac-b490-c432aeefc1ea_400x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" style="height:20px;width:20px" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Traces</strong>&nbsp;represent the journey of a single request or transaction through a distributed system. In a microservices environment, a single user action (say, placing an order) can cause a chain of calls between many services. A trace follows that action end-to-end, showing each step it took and how long each step took.</p><p>A trace is composed of&nbsp;<strong>spans</strong>, where each span represents one segment of that journey (like a call to a database or another service). All the spans share a common trace ID so they can be stitched together. Tracing gives you a&nbsp;<strong>map of the request&#8217;s path</strong>&nbsp;through the system.</p><p>Traces are invaluable for finding&nbsp;<strong>performance bottlenecks and understanding dependencies</strong>&nbsp;between services. For example, a trace of a user request might show it went through Service A, then Service B, then a database. If the request was slow, the trace will pinpoint exactly where the slowdown occurred (maybe the database call took 5 seconds instead of the usual 50 milliseconds). If an error occurred, the trace shows which service in the chain threw the error.</p><div class="pullquote"><p>Imagine tracing a single checkout request in our online store. The trace might reveal something like: It enters the&nbsp;<strong>WebFrontend</strong>&nbsp;service, then calls the <strong>OrderService</strong>&nbsp;(which takes ~200ms). Inside OrderService, it calls the <strong>InventoryService</strong>&nbsp;(~50ms) and <strong>PaymentService</strong>&nbsp;(~5000ms = 5s). Finally, it calls the <strong>NotificationService</strong>&nbsp;(~30ms). This trace makes it immediately obvious that the PaymentService (5 seconds) is the bottleneck. If an error occurred there, we know that&#8217;s the component to focus on.</p></div><p>Traces are especially crucial for <strong>microservices</strong>, because they map out how services interact. Capturing every trace can be heavy, so systems often sample them or allow you to enable tracing on demand. Still, traces provide an end-to-end view you can&#8217;t get from metrics or logs alone.</p><div><hr></div><h2><strong>How Metrics, Logs, and Traces Work Together</strong></h2><p>Using all three pillars together gives you a much more complete understanding of issues than any one alone. For example:</p><ol><li><p><strong>Metrics raise the flag:</strong>&nbsp;Suppose our dashboard shows a sudden spike in error rate or a drop in successful requests. This tells us&nbsp;<strong>something is wrong</strong>&nbsp;and roughly where (e.g. the checkout service).</p></li><li><p><strong>Logs give the details:</strong>&nbsp;Next, we check the logs from that service around that time. The logs might reveal specific error messages or exceptions &#8211; for instance, &#8220;Database connection timeout&#8221; or &#8220;Payment service unreachable&#8221;. Now we know&nbsp;<strong>what happened</strong>.</p></li><li><p><strong>Traces reveal the big picture:</strong>&nbsp;Finally, we look at a distributed trace for one of those failing requests. The trace shows the path through multiple services and pinpoints&nbsp;<strong>where</strong>&nbsp;in the chain it failed or slowed down. For example, it might reveal the checkout request spent 5 seconds in the payment service before erroring out, confirming it as the bottleneck.</p></li></ol><p>In summary, metrics often tell you&nbsp;<em>that</em>&nbsp;there&#8217;s an issue, logs tell you&nbsp;<em>what</em>&nbsp;the issue is, and traces show&nbsp;<em>where</em>&nbsp;and&nbsp;<em>how</em>&nbsp;it happened across components. Each pillar complements the others &#8211; together they provide a&nbsp;<strong>holistic understanding</strong> of what&#8217;s going on.</p><div><hr></div><h2><strong>Tools and Ecosystem</strong></h2><p>A variety of tools and technologies help implement observability. For example:</p><ul><li><p><strong><a href="https://opentelemetry.io/?ref=observability.how">OpenTelemetry</a></strong>&nbsp;&#8211; An open-source observability framework providing a unified set of APIs and SDKs to instrument your code for metrics, logs, and traces.</p></li><li><p><strong><a href="https://prometheus.io/?ref=observability.how">Prometheus</a></strong>&nbsp;&#8211; A widely used open-source system for collecting metrics and sending alerts. It stores time-series data and works with Grafana for visualization.</p></li><li><p><strong><a href="https://www.jaegertracing.io/?ref=observability.how">Jaeger</a></strong>&nbsp;&#8211; An open-source distributed tracing platform for capturing and visualizing traces across microservices.</p></li><li><p><strong>Log Aggregation</strong>&nbsp;&#8211; Tools like the&nbsp;<a href="https://www.elastic.co/elastic-stack?ref=observability.how">ELK stack</a>&nbsp;(Elasticsearch, Logstash, Kibana) or&nbsp;<a href="https://grafana.com/oss/loki/?ref=observability.how">Grafana Loki</a>&nbsp;collect logs from across your services and let you search and analyze them centrally.</p></li></ul><p><em>There are also many all-in-one observability platforms - Datadog, New Relic, etc. that combine metrics, logs, and traces in one place.</em></p><div><hr></div><p>In a world of complex, distributed software, <strong>Observability</strong>&nbsp;is your best ally for keeping systems reliable and debuggable. We&#8217;ve covered what observability is, how it differs from monitoring, and how metrics, logs, and traces each play a role. No single pillar can do it alone &#8211;&nbsp;<strong>combining</strong>&nbsp;all three gives the full picture.</p><p>With good observability in place, you can spend less time guessing and more time <strong>knowing</strong>&nbsp;how your software behaves. The more you observe, the more you&#8217;ll learn &#8211; and the more resilient your systems will become. Happy exploring!</p>]]></content:encoded></item></channel></rss>