<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Farhan Munir</title>
    <description>The latest articles on DEV Community by Farhan Munir (@munirfarhan).</description>
    <link>https://dev.to/munirfarhan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3833974%2Fd6f31945-fbf3-430a-aca8-9937f9230037.jpg</url>
      <title>DEV Community: Farhan Munir</title>
      <link>https://dev.to/munirfarhan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/munirfarhan"/>
    <language>en</language>
    <item>
      <title>Feature Request: Theme Switching for Reel-Quick</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Tue, 07 Jul 2026 10:56:59 +0000</pubDate>
      <link>https://dev.to/munirfarhan/feature-request-theme-switching-for-reel-quick-2oim</link>
      <guid>https://dev.to/munirfarhan/feature-request-theme-switching-for-reel-quick-2oim</guid>
      <description>&lt;p&gt;I have opened a feature request to add frontend theme support to Reel-Quick.&lt;/p&gt;

&lt;p&gt;The proposed feature would allow users to select between Light, Dark, and System-default themes. The selected preference should persist across sessions and apply consistently throughout the application.&lt;/p&gt;

&lt;p&gt;Because Reel-Quick is built with Next.js, this could be implemented using a theme provider such as next-themes, together with CSS variables, Tailwind dark-mode utilities, or the project’s existing styling approach.&lt;/p&gt;

&lt;p&gt;Theme support would improve accessibility, reduce visual fatigue in low-light environments, and make the platform more adaptable for individual users and future team deployments.&lt;/p&gt;

&lt;p&gt;The initial scope can remain simple: Light, Dark, and System modes. Later enhancements could include accent colors, high-contrast mode, compact layouts, or organization-level branding.&lt;/p&gt;

&lt;p&gt;View, discuss, or contribute to the feature request here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ronin1770/reel-quick/issues/11" rel="noopener noreferrer"&gt;https://github.com/ronin1770/reel-quick/issues/11&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>ux</category>
    </item>
    <item>
      <title>Introducing Heka Insights Agent v0.1.0: Our First Release</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Wed, 01 Jul 2026 18:08:25 +0000</pubDate>
      <link>https://dev.to/munirfarhan/introducing-heka-insights-agent-v010-our-first-release-4k06</link>
      <guid>https://dev.to/munirfarhan/introducing-heka-insights-agent-v010-our-first-release-4k06</guid>
      <description>&lt;p&gt;We are shipping the &lt;strong&gt;first release&lt;/strong&gt; of Heka Insights Agent.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;ronin1770/heka-insights-agent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Heka Insights Agent is a lightweight Linux telemetry agent focused on a simple goal: collect host-level signals, normalize them into a consistent format, and make delivery flexible enough for different observability backends.&lt;/p&gt;

&lt;p&gt;For this first release, we wanted to establish a solid base instead of trying to do everything at once. That means a working runtime, clear configuration, multiple exporter options, and a packaging story that makes installation easier on real Linux systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Heka Insights Agent Is
&lt;/h2&gt;

&lt;p&gt;At its core, Heka Insights Agent is designed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collect essential Linux host telemetry&lt;/li&gt;
&lt;li&gt;normalize metrics into a consistent internal model&lt;/li&gt;
&lt;li&gt;keep collection separate from delivery&lt;/li&gt;
&lt;li&gt;support multiple backend paths without changing collectors&lt;/li&gt;
&lt;li&gt;stay lightweight enough for continuous runtime use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That separation is important. It means the agent is not tightly locked to one vendor from day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Ships in v0.1.0
&lt;/h2&gt;

&lt;p&gt;This first release includes several important pieces.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Linux host telemetry collection
&lt;/h3&gt;

&lt;p&gt;The project collects core machine-level signals such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU usage&lt;/li&gt;
&lt;li&gt;memory usage&lt;/li&gt;
&lt;li&gt;disk I/O&lt;/li&gt;
&lt;li&gt;runtime health-oriented metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to keep the foundation practical and extensible.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Multiple exporter paths
&lt;/h3&gt;

&lt;p&gt;This release supports a small but meaningful set of delivery modes through &lt;code&gt;EXPORTER_TYPE&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;console&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;otlp_http&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;datadog_otlp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;datadog_native&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;newrelic_otlp&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That gives teams a path to start locally, use standard OTLP HTTP delivery, or integrate with Datadog and New Relic using repo-supported configuration flows.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Strict runtime configuration behavior
&lt;/h3&gt;

&lt;p&gt;One of the priorities in this release is predictable startup behavior.&lt;/p&gt;

&lt;p&gt;Instead of silently accepting bad configuration, the runtime validates required settings and fails fast when critical exporter values are missing or malformed. That matters a lot for agents that are expected to run unattended.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Debian package build and install flow
&lt;/h3&gt;

&lt;p&gt;This release also includes a Debian packaging path for Ubuntu &lt;code&gt;amd64&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The package flow covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a bundled executable under &lt;code&gt;/usr/local/bin/heka-insights-agent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a systemd service unit&lt;/li&gt;
&lt;li&gt;packaged runtime config under &lt;code&gt;/etc/heka-insights-agent/.env&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;log output under &lt;code&gt;/var/log/heka-insights-agent/agent.log&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;an interactive setup path for first-time installation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a meaningful step forward compared with a repo-only Python workflow, because it gives users a clearer route for installing the agent as a managed service.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Interactive setup flow
&lt;/h3&gt;

&lt;p&gt;The packaged runtime includes a setup mode so installation is not just "copy files and figure it out yourself."&lt;/p&gt;

&lt;p&gt;The setup flow is meant to help with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;selecting exporter mode&lt;/li&gt;
&lt;li&gt;capturing required environment values&lt;/li&gt;
&lt;li&gt;writing packaged runtime configuration&lt;/li&gt;
&lt;li&gt;enabling and starting the service on success&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes the first release much closer to something an operator can actually install and use.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Docs and test coverage around the exporter paths
&lt;/h3&gt;

&lt;p&gt;We also shipped supporting documentation and test coverage for the exporter/runtime surface, including milestone-specific integration coverage for the Datadog and New Relic paths.&lt;/p&gt;

&lt;p&gt;That does not mean the project is feature-complete. It means the base is being treated seriously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation Direction
&lt;/h2&gt;

&lt;p&gt;For release users, the install direction is now straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; heka-insights-agent_&amp;lt;version&amp;gt;_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If setup is interrupted, it can be resumed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; /usr/local/bin/heka-insights-agent setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This first release is intentionally Linux-focused and packaging-aware from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We’re Starting Here
&lt;/h2&gt;

&lt;p&gt;There are already many observability tools in the market, but there is still room for agents that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simpler to understand&lt;/li&gt;
&lt;li&gt;easier to extend&lt;/li&gt;
&lt;li&gt;less coupled to a single backend&lt;/li&gt;
&lt;li&gt;easier to package and operate on Linux hosts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first release is about getting those fundamentals in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collection&lt;/li&gt;
&lt;li&gt;normalization&lt;/li&gt;
&lt;li&gt;delivery options&lt;/li&gt;
&lt;li&gt;installability&lt;/li&gt;
&lt;li&gt;operational clarity&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Open Source Repo
&lt;/h2&gt;

&lt;p&gt;If you want to inspect the code, follow the release progress, or contribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;ronin1770/heka-insights-agent&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;From here, the focus is to keep improving the agent in practical ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deeper collector coverage&lt;/li&gt;
&lt;li&gt;stronger runtime hardening&lt;/li&gt;
&lt;li&gt;broader integration coverage&lt;/li&gt;
&lt;li&gt;more production-oriented examples&lt;/li&gt;
&lt;li&gt;continued packaging and rollout improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is that the first release is no longer just an idea. There is now a concrete repo, a real runtime, documented exporter behavior, and a packaged install path to build on.&lt;/p&gt;

</description>
      <category>python</category>
      <category>linux</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Heka-Insights-Agent: Milestone 6 Complete: Datadog OTLP + Native Integration Paths</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Sun, 17 May 2026 06:04:48 +0000</pubDate>
      <link>https://dev.to/munirfarhan/heka-insights-agent-milestone-6-complete-datadog-otlp-native-integration-paths-4144</link>
      <guid>https://dev.to/munirfarhan/heka-insights-agent-milestone-6-complete-datadog-otlp-native-integration-paths-4144</guid>
      <description>&lt;p&gt;Milestone 6 is complete for the Heka Insights Agent.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;https://github.com/ronin1770/heka-insights-agent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this milestone, we implemented &lt;strong&gt;two Datadog-compatible delivery paths&lt;/strong&gt; so teams can choose what fits their needs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Datadog OTLP preset mode&lt;/strong&gt; (&lt;code&gt;EXPORTER_TYPE=datadog_otlp&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Datadog native API mode&lt;/strong&gt; (&lt;code&gt;EXPORTER_TYPE=datadog_native&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Milestone 6 Goal
&lt;/h2&gt;

&lt;p&gt;Provide Datadog integration through both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OTLP-based delivery for portability&lt;/li&gt;
&lt;li&gt;Datadog-native delivery for backend-specific control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In common terms: this means your agent can now send metrics to Datadog in either a standards-oriented way (OTLP) or a Datadog-specific way (native API), without changing your collectors.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Implemented
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Datadog OTLP preset mode (&lt;code&gt;datadog_otlp&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;We added a Datadog preset resolver that derives endpoint + auth headers from Datadog config.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;endpoint is derived from site: &lt;code&gt;https://otlp.&amp;lt;DATADOG_SITE&amp;gt;/v1/metrics&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;auth header is injected: &lt;code&gt;dd-api-key: &amp;lt;DATADOG_API_KEY&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;optional Datadog hostname/tags are mapped into resource attributes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Datadog native exporter (&lt;code&gt;datadog_native&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;We implemented a native Datadog metrics exporter for &lt;code&gt;POST /api/v1/series&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;endpoint is derived from site: &lt;code&gt;https://api.&amp;lt;DATADOG_SITE&amp;gt;/api/v1/series&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;canonical &lt;code&gt;gauge&lt;/code&gt; -&amp;gt; Datadog &lt;code&gt;gauge&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;canonical &lt;code&gt;counter&lt;/code&gt; -&amp;gt; Datadog &lt;code&gt;count&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;timestamp_unix_ms&lt;/code&gt; -&amp;gt; Unix seconds&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count.interval&lt;/code&gt; is derived from &lt;code&gt;CPU_POLL_INTERVAL_SECONDS&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Validation hardening (M6-3)
&lt;/h3&gt;

&lt;p&gt;We fail fast on invalid/missing Datadog config:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DATADOG_SITE&lt;/code&gt; must be an allowed full domain&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DATADOG_API_KEY&lt;/code&gt; must be non-empty&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DATADOG_TAGS&lt;/code&gt; must be strict &lt;code&gt;key:value&lt;/code&gt; format&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Deterministic mapping rules (M6-4)
&lt;/h3&gt;

&lt;p&gt;We made mapping predictable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DATADOG_HOSTNAME&lt;/code&gt; overrides label-derived host&lt;/li&gt;
&lt;li&gt;tag conflicts are deterministic (&lt;code&gt;DATADOG_TAGS&lt;/code&gt; override label tags by key)&lt;/li&gt;
&lt;li&gt;metric prefixing is idempotent (won't double-prefix)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. OTLP vs native comparison docs (M6-5)
&lt;/h3&gt;

&lt;p&gt;We added side-by-side docs so teams can quickly decide mode based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transport style&lt;/li&gt;
&lt;li&gt;portability&lt;/li&gt;
&lt;li&gt;mapping behavior&lt;/li&gt;
&lt;li&gt;counter interval semantics&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Docker-based milestone-6 integration tests (M6-6)
&lt;/h3&gt;

&lt;p&gt;We added dedicated tests under:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tests/milestone-6/test_datadog_live_integration.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are intentionally gated and only run when explicitly enabled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Files Added/Updated
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/config/runtime.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/config/__init__.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/exporters/factory.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/exporters/datadog_native.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests/test_config_otlp_env.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests/test_datadog_exporters.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests/milestone-6/test_datadog_live_integration.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs/configuration.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs/architecture.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs/development.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation Strategy
&lt;/h2&gt;

&lt;p&gt;We followed the existing exporter architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep collectors unchanged&lt;/li&gt;
&lt;li&gt;Extend runtime config with strict validation and preset resolution&lt;/li&gt;
&lt;li&gt;Reuse OTLP HTTP exporter for Datadog OTLP mode&lt;/li&gt;
&lt;li&gt;Add a dedicated native exporter for Datadog API v1 series&lt;/li&gt;
&lt;li&gt;Add deterministic mapping rules + comprehensive tests&lt;/li&gt;
&lt;li&gt;Add Docker-backed live tests in a milestone-specific folder&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Test Commands and Outputs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Local Datadog-focused test suite
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src python3 &lt;span class="nt"&gt;-m&lt;/span&gt; unittest &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  tests.test_config_otlp_env &lt;span class="se"&gt;\&lt;/span&gt;
  tests.test_datadog_exporters
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ran 21 tests in 0.008s

OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Full local suite
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src python3 &lt;span class="nt"&gt;-m&lt;/span&gt; unittest discover &lt;span class="nt"&gt;-s&lt;/span&gt; tests &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ran 42 tests in 0.014s

OK (skipped=1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Docker live Datadog integration tests (milestone-6)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.test.yml run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;RUN_OTLP_INTEGRATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;RUN_DATADOG_LIVE_INTEGRATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DATADOG_SITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us5.datadoghq.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DATADOG_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;REDACTED_DATADOG_API_KEY&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  test-runner &lt;span class="se"&gt;\&lt;/span&gt;
  pytest &lt;span class="nt"&gt;-vv&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-rs&lt;/span&gt; tests/milestone-6/test_datadog_live_integration.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observed output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;collected 2 items

tests/milestone-6/test_datadog_live_integration.py::DatadogLiveIntegrationTests::test_datadog_native_exports_gauge_and_count_metrics PASSED
tests/milestone-6/test_datadog_live_integration.py::DatadogLiveIntegrationTests::test_datadog_otlp_preset_exports_gauge_metric PASSED

2 passed in 2.63s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;With Milestone 6 complete, Datadog users can now choose the integration path that matches their operations model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;choose &lt;strong&gt;OTLP preset&lt;/strong&gt; for standards-aligned portability&lt;/li&gt;
&lt;li&gt;choose &lt;strong&gt;native mode&lt;/strong&gt; for Datadog-specific control and semantics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both paths are now validated, tested, and documented.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contribute
&lt;/h2&gt;

&lt;p&gt;If you're interested in observability agents, OTLP pipelines, or exporter design, contributions are welcome:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;https://github.com/ronin1770/heka-insights-agent&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Useful contribution areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;additional Datadog live integration coverage&lt;/li&gt;
&lt;li&gt;CI automation for gated integration scenarios&lt;/li&gt;
&lt;li&gt;docs/examples for production deployments&lt;/li&gt;
&lt;li&gt;future milestone reliability and operability improvements&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>datadog</category>
      <category>telemetry</category>
    </item>
    <item>
      <title>Milestone 5 Complete: New Relic OTLP Integration for Heka Insights Agent</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Tue, 12 May 2026 05:33:12 +0000</pubDate>
      <link>https://dev.to/munirfarhan/milestone-5-complete-new-relic-otlp-integration-for-heka-insights-agent-411f</link>
      <guid>https://dev.to/munirfarhan/milestone-5-complete-new-relic-otlp-integration-for-heka-insights-agent-411f</guid>
      <description>&lt;p&gt;In this milestone, we focused on making &lt;strong&gt;New Relic integration first-class&lt;/strong&gt; in the Heka Insights Agent, while still using the same OTLP HTTP exporter foundation.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;https://github.com/ronin1770/heka-insights-agent&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Milestone 5 Goal
&lt;/h2&gt;

&lt;p&gt;Milestone 5 was about shipping a reliable, low-friction New Relic path without creating a separate proprietary exporter.&lt;/p&gt;

&lt;p&gt;Scope covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New Relic preset configuration layer&lt;/li&gt;
&lt;li&gt;Automatic New Relic auth header injection&lt;/li&gt;
&lt;li&gt;Endpoint and required field validation&lt;/li&gt;
&lt;li&gt;Documentation updates with practical examples&lt;/li&gt;
&lt;li&gt;Integration tests for preset behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What We Changed
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. New Relic preset mode (&lt;code&gt;EXPORTER_TYPE=newrelic_otlp&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;We added a preset resolver that maps New Relic-specific environment variables into OTLP HTTP exporter inputs.&lt;/p&gt;

&lt;p&gt;Required variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NEWRELIC_OTLP_ENDPOINT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEWRELIC_API_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEWRELIC_SERVICE_NAME&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NEWRELIC_ENVIRONMENT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEWRELIC_HOST_NAME&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Automatic auth header injection
&lt;/h3&gt;

&lt;p&gt;When &lt;code&gt;EXPORTER_TYPE=newrelic_otlp&lt;/code&gt; is selected, the runtime now injects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;api-key: &amp;lt;NEWRELIC_API_KEY&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No manual &lt;code&gt;OTLP_HTTP_HEADERS&lt;/code&gt; setup is required for baseline New Relic auth.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Precedence behavior
&lt;/h3&gt;

&lt;p&gt;In preset mode, &lt;code&gt;NEWRELIC_*&lt;/code&gt; values take precedence over conflicting generic &lt;code&gt;OTLP_*&lt;/code&gt; values.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NEWRELIC_API_KEY&lt;/code&gt; overrides any conflicting &lt;code&gt;OTLP_HTTP_HEADERS&lt;/code&gt; &lt;code&gt;api-key&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NEWRELIC_SERVICE_NAME&lt;/code&gt; overrides &lt;code&gt;service.name&lt;/code&gt; from &lt;code&gt;OTLP_RESOURCE_ATTRIBUTES&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Validation hardening
&lt;/h3&gt;

&lt;p&gt;We now fail fast on invalid or missing required New Relic settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing required keys -&amp;gt; startup error&lt;/li&gt;
&lt;li&gt;invalid endpoint format -&amp;gt; startup error (must be absolute &lt;code&gt;http://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Documentation updates
&lt;/h3&gt;

&lt;p&gt;We updated project docs and examples to include New Relic preset usage and expected test flows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commands to Run Tests
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unit tests for config behavior
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src python3 &lt;span class="nt"&gt;-m&lt;/span&gt; unittest &lt;span class="nt"&gt;-v&lt;/span&gt; tests.test_config_otlp_env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  New Relic Docker integration tests (explicit)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.test.yml run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;RUN_OTLP_INTEGRATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;OTLP_IT_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host.docker.internal &lt;span class="se"&gt;\&lt;/span&gt;
  test-runner &lt;span class="se"&gt;\&lt;/span&gt;
  pytest &lt;span class="nt"&gt;-vv&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-rs&lt;/span&gt; tests/milestone-5/test_newrelic_otlp_integration.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;collected 3 items
...
3 passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Full OTLP/HTTP Docker test stack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.test.yml up &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nt"&gt;--abort-on-container-exit&lt;/span&gt; &lt;span class="nt"&gt;--exit-code-from&lt;/span&gt; test-runner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;With Milestone 5 complete, teams can onboard New Relic using a predictable preset path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;less config ambiguity&lt;/li&gt;
&lt;li&gt;safer startup behavior through validation&lt;/li&gt;
&lt;li&gt;standardized OTLP transport path&lt;/li&gt;
&lt;li&gt;stronger confidence through Docker-backed integration tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next steps will continue building on this exporter foundation while keeping the runtime predictable and vendor-friendly.&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>telemetry</category>
      <category>agents</category>
    </item>
    <item>
      <title>Milestone 4 Complete — OTLP HTTP Exporter for Heka Insights Agent</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Wed, 29 Apr 2026 06:49:27 +0000</pubDate>
      <link>https://dev.to/munirfarhan/milestone-4-complete-otlp-http-exporter-for-heka-insights-agent-1chp</link>
      <guid>https://dev.to/munirfarhan/milestone-4-complete-otlp-http-exporter-for-heka-insights-agent-1chp</guid>
      <description>&lt;p&gt;In this milestone, I completed the OTLP HTTP exporter implementation for &lt;strong&gt;Heka Insights Agent&lt;/strong&gt; and validated it with both unit tests and Docker-backed integration tests.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;https://github.com/ronin1770/heka-insights-agent&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What was implemented in Milestone 4
&lt;/h2&gt;

&lt;p&gt;Milestone 4 includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OTLP HTTP exporter wiring&lt;/li&gt;
&lt;li&gt;OTLP metric payload mapping&lt;/li&gt;
&lt;li&gt;OTLP auth header support&lt;/li&gt;
&lt;li&gt;OTLP resource attribute mapping&lt;/li&gt;
&lt;li&gt;Retry/backoff behavior for transient failures&lt;/li&gt;
&lt;li&gt;Unit test coverage for config + sender + exporter + mapping&lt;/li&gt;
&lt;li&gt;Docker integration tests against a real OpenTelemetry Collector&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Configuration added
&lt;/h2&gt;

&lt;p&gt;OTLP configuration is environment-driven through &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOG_LOCATION=./log/heka_agent.log
CPU_POLL_INTERVAL_SECONDS=10
EXPORTER_TYPE=otlp_http
OTLP_HTTP_ENDPOINT=http://localhost:4318/v1/metrics
OTLP_HTTP_HEADERS=key=Bearer abcd1234
OTLP_RESOURCE_ATTRIBUTES=service.name=heka-insights-agent,host.name=localhost
OTLP_HTTP_TIMEOUT_SECONDS=10
OTLP_HTTP_RETRY_MAX_ATTEMPTS=5
OTLP_HTTP_RETRY_INITIAL_BACKOFF_SECONDS=1
OTLP_HTTP_RETRY_MAX_BACKOFF_SECONDS=5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;OTLP_HTTP_HEADERS&lt;/code&gt; format: &lt;code&gt;key=value,key2=value2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OTLP_RESOURCE_ATTRIBUTES&lt;/code&gt; format: &lt;code&gt;key=value,key2=value2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Retryable failures:

&lt;ul&gt;
&lt;li&gt;transport errors&lt;/li&gt;
&lt;li&gt;HTTP &lt;code&gt;408&lt;/code&gt;, &lt;code&gt;429&lt;/code&gt;, and &lt;code&gt;5xx&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Non-retryable failures:

&lt;ul&gt;
&lt;li&gt;HTTP &lt;code&gt;400&lt;/code&gt;, &lt;code&gt;401&lt;/code&gt;, &lt;code&gt;403&lt;/code&gt;, &lt;code&gt;404&lt;/code&gt;, and similar client-side errors&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Unit tests
&lt;/h2&gt;

&lt;p&gt;Unit tests cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OTLP env parsing and validation&lt;/li&gt;
&lt;li&gt;OTLP payload mapping&lt;/li&gt;
&lt;li&gt;OTLP HTTP sender behavior&lt;/li&gt;
&lt;li&gt;Retry/backoff behavior&lt;/li&gt;
&lt;li&gt;Exporter initialization and wiring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run unit tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src python3 &lt;span class="nt"&gt;-m&lt;/span&gt; unittest discover &lt;span class="nt"&gt;-s&lt;/span&gt; tests &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Unit test output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ran 27 tests in 0.008s

OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Integration tests (Docker + real collector)
&lt;/h2&gt;

&lt;p&gt;Integration tests validate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;auth success (&lt;code&gt;200&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;auth reject path (&lt;code&gt;401&lt;/code&gt;) and no retry on non-retryable status&lt;/li&gt;
&lt;li&gt;no-auth collector path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run OTLP integration tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;RUN_OTLP_INTEGRATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src python3 &lt;span class="nt"&gt;-m&lt;/span&gt; unittest &lt;span class="nt"&gt;-v&lt;/span&gt; tests.test_otlp_http_integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integration test output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test_auth_rejected_without_retry_for_401 ... ok
test_auth_success_with_bearer_header ... ok
test_no_auth_collector_accepts_without_headers ... ok

----------------------------------------------------------------------
Ran 3 tests in 2.417s

OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Collector config used in tests
&lt;/h2&gt;

&lt;p&gt;The project includes collector fixtures under &lt;code&gt;tests/fixtures/otlp/&lt;/code&gt;, including auth-required and no-auth variants for scenario testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final result
&lt;/h2&gt;

&lt;p&gt;Milestone 4 now has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;working OTLP HTTP exporter&lt;/li&gt;
&lt;li&gt;production-style config controls&lt;/li&gt;
&lt;li&gt;retry/backoff logic for transient failures&lt;/li&gt;
&lt;li&gt;unit + integration test coverage&lt;/li&gt;
&lt;li&gt;updated docs and run instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo again: &lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;https://github.com/ronin1770/heka-insights-agent&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>devops</category>
      <category>telemetry</category>
    </item>
    <item>
      <title>Milestone 4 (Part 1): Implementing OTLP HTTP Core in Heka Insights Agent (M4-1, M4-2)</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Mon, 27 Apr 2026 09:57:30 +0000</pubDate>
      <link>https://dev.to/munirfarhan/milestone-4-part-1-implementing-otlp-http-core-in-heka-insights-agent-m4-1-m4-2-2a79</link>
      <guid>https://dev.to/munirfarhan/milestone-4-part-1-implementing-otlp-http-core-in-heka-insights-agent-m4-1-m4-2-2a79</guid>
      <description>&lt;h1&gt;
  
  
  Milestone 4 (Part 1): Implementing OTLP HTTP Core in Heka Insights Agent (M4-1, M4-2)
&lt;/h1&gt;

&lt;p&gt;Heka Insights Agent already had a canonical metrics pipeline from Milestone 3.&lt;br&gt;&lt;br&gt;
In this part of Milestone 4, I implemented the OTLP HTTP core in two focused steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;M4-1&lt;/code&gt;: Canonical metrics -&amp;gt; OTLP payload mapping layer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;M4-2&lt;/code&gt;: OTLP HTTP request sender and exporter wiring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post covers only these two items. Auth headers, resource attributes, retry/compression controls are intentionally deferred to later M4 tasks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Split Matters
&lt;/h2&gt;

&lt;p&gt;By separating mapping from transport, we get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stable internal metric model&lt;/li&gt;
&lt;li&gt;explicit OTLP payload construction&lt;/li&gt;
&lt;li&gt;transport logic that can evolve independently&lt;/li&gt;
&lt;li&gt;clean foundation for New Relic/Datadog-style OTLP integrations later&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What Was Implemented
&lt;/h2&gt;
&lt;h3&gt;
  
  
  M4-1: OTLP Payload Mapping Layer
&lt;/h3&gt;

&lt;p&gt;I added a dedicated mapper that converts canonical metric records into OTLP HTTP JSON payloads.&lt;/p&gt;

&lt;p&gt;Core behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validates required canonical fields before send&lt;/li&gt;
&lt;li&gt;supports explicit type mapping:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gauge&lt;/code&gt; -&amp;gt; OTLP &lt;code&gt;gauge.dataPoints&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;counter&lt;/code&gt; -&amp;gt; OTLP &lt;code&gt;sum.dataPoints&lt;/code&gt; with cumulative temporality&lt;/li&gt;
&lt;li&gt;maps canonical labels to OTLP metric attributes&lt;/li&gt;
&lt;li&gt;maps &lt;code&gt;timestamp_unix_ms&lt;/code&gt; to OTLP &lt;code&gt;timeUnixNano&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;rejects malformed metrics early with explicit errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result: malformed payloads are blocked before network transport.&lt;/p&gt;
&lt;h3&gt;
  
  
  M4-2: OTLP HTTP Sender + Exporter
&lt;/h3&gt;

&lt;p&gt;I added OTLP HTTP sender/exporter flow and wired it into exporter selection.&lt;/p&gt;

&lt;p&gt;Core behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;EXPORTER_TYPE=otlp_http&lt;/code&gt; now creates OTLP exporter&lt;/li&gt;
&lt;li&gt;validates OTLP endpoint format (&lt;code&gt;http/https&lt;/code&gt; absolute URL) at startup&lt;/li&gt;
&lt;li&gt;fails fast when endpoint is missing/invalid&lt;/li&gt;
&lt;li&gt;sends JSON payload via HTTP &lt;code&gt;POST&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;treats only &lt;code&gt;2xx&lt;/code&gt; responses as success&lt;/li&gt;
&lt;li&gt;raises explicit errors for HTTP failures and transport errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result: working end-to-end OTLP HTTP delivery with fail-fast startup safety.&lt;/p&gt;
&lt;h2&gt;
  
  
  Local Test Setup with OpenTelemetry Collector (Docker)
&lt;/h2&gt;

&lt;p&gt;I used OTel Collector debug exporter to validate incoming metrics.&lt;/p&gt;
&lt;h3&gt;
  
  
  Collector config (&lt;code&gt;otel-collector-config.yaml&lt;/code&gt;)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;protocols&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0:4318&lt;/span&gt;

&lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;debug&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Run collector
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 4318:4318 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/otel-collector-config.yaml:/etc/otelcol/config.yaml"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  otel/opentelemetry-collector:latest &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/otelcol/config.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Agent &lt;code&gt;.env&lt;/code&gt; for this test
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOG_LOCATION=./log/heka_agent.log
CPU_POLL_INTERVAL_SECONDS=10
EXPORTER_TYPE=otlp_http
OTLP_HTTP_ENDPOINT=http://localhost:4318/v1/metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Run agent
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python src/main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Verification Signals
&lt;/h2&gt;

&lt;p&gt;From runtime behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agent starts with &lt;code&gt;exporter_type=otlp_http&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;collector logs periodic metric batches every ~10 seconds&lt;/li&gt;
&lt;li&gt;no exporter exceptions during dispatch&lt;/li&gt;
&lt;li&gt;first cycle has fewer points due to CPU warm-up, then normalizes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example collector signal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;resource metrics: 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metrics: 24&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data points: 24&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Tests Added
&lt;/h2&gt;

&lt;p&gt;I added focused tests for M4-1/M4-2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;payload mapping correctness (gauge/counter, labels, timestamps)&lt;/li&gt;
&lt;li&gt;validation failures for malformed canonical metrics&lt;/li&gt;
&lt;li&gt;HTTP sender request behavior and error handling&lt;/li&gt;
&lt;li&gt;exporter wiring and missing-endpoint startup failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All tests pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src python3 &lt;span class="nt"&gt;-m&lt;/span&gt; unittest discover &lt;span class="nt"&gt;-s&lt;/span&gt; tests &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Is Intentionally Not Included Yet
&lt;/h2&gt;

&lt;p&gt;Deferred to later M4 items:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;auth headers (&lt;code&gt;M4-3&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;resource attribute mapping (&lt;code&gt;M4-4&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;timeout/compression/retry controls (&lt;code&gt;M4-5&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;broader OTLP docs and expanded test matrix (&lt;code&gt;M4-6&lt;/code&gt;, &lt;code&gt;M4-7&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;M4-1 and M4-2 establish the OTLP core path: canonical metrics are now mapped deterministically and sent over HTTP with fail-fast validation.&lt;br&gt;&lt;br&gt;
This gives a production-friendly base to layer auth, resource metadata, and resiliency controls next.&lt;/p&gt;

&lt;p&gt;Repo URL: &lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;https://github.com/ronin1770/heka-insights-agent&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>devops</category>
      <category>telemetry</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Heka-Insights-Agent: Milestone M3-4: Fail-Fast Exporter Validation at Startup</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Fri, 24 Apr 2026 06:30:06 +0000</pubDate>
      <link>https://dev.to/munirfarhan/heka-insights-agent-milestone-m3-4-fail-fast-exporter-validation-at-startup-14p</link>
      <guid>https://dev.to/munirfarhan/heka-insights-agent-milestone-m3-4-fail-fast-exporter-validation-at-startup-14p</guid>
      <description>&lt;h1&gt;
  
  
  Milestone M3-4: Fail-Fast Exporter Validation at Startup
&lt;/h1&gt;

&lt;p&gt;On &lt;strong&gt;April 24, 2026&lt;/strong&gt;, I completed &lt;strong&gt;M3-4&lt;/strong&gt; in &lt;code&gt;heka-insights-agent&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;M3-4: Add configuration validation for exporter settings&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This milestone closed a critical gap in the exporter foundation by removing silent fallback behavior and enforcing explicit startup failures for invalid exporter configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;In Milestone M3-3, we routed output through the exporter interface and lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initialize()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;export(metrics)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shutdown()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That established the architecture.&lt;br&gt;&lt;br&gt;
M3-4 focused on correctness and operational safety: startup must fail early when exporter configuration is invalid or points to an unimplemented adapter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Before M3-4
&lt;/h2&gt;

&lt;p&gt;Prior behavior was permissive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;invalid &lt;code&gt;EXPORTER_TYPE&lt;/code&gt; values defaulted back to &lt;code&gt;console&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;unimplemented exporter types also downgraded to &lt;code&gt;console&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why this was risky:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;misconfiguration could go unnoticed in production&lt;/li&gt;
&lt;li&gt;users could think they were exporting to one backend while actually exporting to console&lt;/li&gt;
&lt;li&gt;behavior violated milestone acceptance criteria requiring explicit errors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  M3-4 Goals
&lt;/h2&gt;

&lt;p&gt;The implementation targeted three concrete outcomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;invalid &lt;code&gt;EXPORTER_TYPE&lt;/code&gt; must fail fast with a clear startup error&lt;/li&gt;
&lt;li&gt;configured but unimplemented exporter adapters must fail fast with a clear startup error&lt;/li&gt;
&lt;li&gt;docs must reflect strict validation (remove pre-M3-4 fallback messaging)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Implementation Summary
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1) Strict validation in runtime config
&lt;/h2&gt;

&lt;p&gt;Updated &lt;code&gt;src/config/runtime.py&lt;/code&gt; in &lt;code&gt;get_exporter_type(...)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Behavior now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing &lt;code&gt;EXPORTER_TYPE&lt;/code&gt; still defaults to &lt;code&gt;console&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;unsupported value now raises &lt;code&gt;RuntimeError&lt;/code&gt; with explicit supported values list&lt;/li&gt;
&lt;li&gt;optional logger records an error message before raising&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This changed exporter selection from “best-effort fallback” to deterministic validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Removed fallback from exporter factory
&lt;/h2&gt;

&lt;p&gt;Updated &lt;code&gt;src/exporters/factory.py&lt;/code&gt; in &lt;code&gt;create_exporter(...)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Behavior now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;console&lt;/code&gt; returns &lt;code&gt;ConsoleExporter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;other configured values currently raise &lt;code&gt;RuntimeError&lt;/code&gt; because adapters are not implemented yet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is intentional. It prevents false confidence and makes readiness of each exporter explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Documentation updated to M3-4 semantics
&lt;/h2&gt;

&lt;p&gt;Updated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docs/configuration.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both now state that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unsupported exporter values fail fast&lt;/li&gt;
&lt;li&gt;unimplemented exporters fail fast&lt;/li&gt;
&lt;li&gt;only missing value defaults to &lt;code&gt;console&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This removed the “fallback to console with warning” wording from the pre-M3-4 behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation Performed
&lt;/h2&gt;

&lt;p&gt;Validation included compile checks and runtime behavior checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compile validation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;python3 -m compileall src&lt;/code&gt; passed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Behavior validation
&lt;/h2&gt;

&lt;p&gt;Tested startup resolution paths for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing &lt;code&gt;EXPORTER_TYPE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EXPORTER_TYPE=console&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EXPORTER_TYPE=invalid_value&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXPORTER_TYPE=otlp_http&lt;/code&gt; (declared but not implemented adapter)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Observed results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing value -&amp;gt; resolves to &lt;code&gt;console&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;console&lt;/code&gt; -&amp;gt; exporter creation succeeds&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;invalid_value&lt;/code&gt; -&amp;gt; immediate &lt;code&gt;RuntimeError&lt;/code&gt; with supported-values message&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;otlp_http&lt;/code&gt; -&amp;gt; immediate &lt;code&gt;RuntimeError&lt;/code&gt; stating exporter not implemented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These outcomes align with M3-4 requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this change matters operationally
&lt;/h2&gt;

&lt;p&gt;Fail-fast startup validation improves reliability in real deployments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;misconfigurations are caught immediately&lt;/li&gt;
&lt;li&gt;no hidden routing to fallback output&lt;/li&gt;
&lt;li&gt;deployment behavior is explicit and auditable&lt;/li&gt;
&lt;li&gt;future exporter rollout can be gated by implementation readiness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially important when teams automate deployments and rely on env-based configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architectural Impact
&lt;/h2&gt;

&lt;p&gt;After M3-4, exporter behavior is now strictly layered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;config validates selector&lt;/li&gt;
&lt;li&gt;factory enforces implementation availability&lt;/li&gt;
&lt;li&gt;runtime starts only on valid+implemented exporter path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That gives us a clean foundation for adding real transports (&lt;code&gt;otlp_http&lt;/code&gt;, &lt;code&gt;datadog_native&lt;/code&gt;, &lt;code&gt;newrelic_otlp&lt;/code&gt;) without changing collector logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;p&gt;The natural next step after M3-4 is M3-5:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;document exporter lifecycle and responsibilities in architecture docs&lt;/li&gt;
&lt;li&gt;include startup validation expectations as part of operational guidance&lt;/li&gt;
&lt;li&gt;capture adapter implementation contract for future backend integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;M3-4 makes sure the system fails loudly when exporter config is wrong, which is exactly what a transport foundation should do before adding real outbound integrations.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>python</category>
      <category>telemetry</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Milestone M3-3: Refactoring Console Output Into an Exporter Pathway</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Fri, 24 Apr 2026 05:49:23 +0000</pubDate>
      <link>https://dev.to/munirfarhan/milestone-m3-3-refactoring-console-output-into-an-exporter-pathway-3c1k</link>
      <guid>https://dev.to/munirfarhan/milestone-m3-3-refactoring-console-output-into-an-exporter-pathway-3c1k</guid>
      <description>&lt;h1&gt;
  
  
  Milestone M3-3: Refactoring Console Output Into an Exporter Pathway
&lt;/h1&gt;

&lt;p&gt;On &lt;strong&gt;April 24, 2026&lt;/strong&gt;, I completed &lt;strong&gt;M3-3&lt;/strong&gt; for &lt;code&gt;heka-insights-agent&lt;/code&gt;: moving console output from direct printing in the main loop to a proper exporter lifecycle.&lt;/p&gt;

&lt;p&gt;This was part of Milestone #3 (&lt;code&gt;Transport And Exporter Foundation&lt;/code&gt;) and specifically targeted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;M3-3: Refactor console output to use exporter interface&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a cleaner delivery architecture where collectors remain untouched and output transport is now pluggable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why M3-3 mattered
&lt;/h2&gt;

&lt;p&gt;Before this change, the runtime loop handled collection, formatting, and printing in one place. That worked for a console-only stage, but it tightly coupled runtime behavior to one output path.&lt;/p&gt;

&lt;p&gt;For Milestone #3, the architecture needs to support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a canonical metric model&lt;/li&gt;
&lt;li&gt;reusable formatters&lt;/li&gt;
&lt;li&gt;exporter lifecycle boundaries&lt;/li&gt;
&lt;li&gt;future transport adapters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;M3-3 was the bridge from “it prints metrics” to “it exports metrics through a contract.”&lt;/p&gt;

&lt;h2&gt;
  
  
  What the code looked like before
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;src/main.py&lt;/code&gt; previously:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;collected CPU/memory/disk payloads&lt;/li&gt;
&lt;li&gt;formatted them with &lt;code&gt;PrometheusFormatter.format(...)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;called &lt;code&gt;print(prometheus_output, end="", flush=True)&lt;/code&gt; directly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That meant no exporter-owned lifecycle (&lt;code&gt;initialize&lt;/code&gt;, &lt;code&gt;shutdown&lt;/code&gt;), and no central place to swap output behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design goals for this refactor
&lt;/h2&gt;

&lt;p&gt;The implementation targeted four practical goals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep collectors unchanged.&lt;/li&gt;
&lt;li&gt;Remove direct console printing from &lt;code&gt;main.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Route output through &lt;code&gt;Exporter.initialize()&lt;/code&gt;, &lt;code&gt;Exporter.export(...)&lt;/code&gt;, and &lt;code&gt;Exporter.shutdown()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Preserve current Prometheus console output shape for backward compatibility.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What was implemented
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1) Console exporter implementation
&lt;/h2&gt;

&lt;p&gt;Created &lt;code&gt;src/exporters/console.py&lt;/code&gt; with &lt;code&gt;ConsoleExporter(Exporter)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Responsibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;initialize()&lt;/code&gt;: prepare exporter state&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;export(metrics)&lt;/code&gt;: format and emit canonical metrics to stdout&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shutdown()&lt;/code&gt;: close lifecycle cleanly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;ConsoleExporter&lt;/code&gt; now owns console writes. &lt;code&gt;main.py&lt;/code&gt; no longer writes metrics directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Exporter factory wiring
&lt;/h2&gt;

&lt;p&gt;Created &lt;code&gt;src/exporters/factory.py&lt;/code&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;create_exporter(exporter_type, logger=...) -&amp;gt; Exporter&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Current behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;returns &lt;code&gt;ConsoleExporter&lt;/code&gt; for &lt;code&gt;console&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;falls back to &lt;code&gt;ConsoleExporter&lt;/code&gt; for unimplemented exporter types with a warning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps runtime deterministic while other exporters are still pending.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Canonical metric normalization pipeline
&lt;/h2&gt;

&lt;p&gt;Created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/pipeline/canonical_metrics.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/pipeline/__init__.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Added &lt;code&gt;build_canonical_metrics(payloads, timestamp_unix_ms=...)&lt;/code&gt; to map collector payloads into canonical records.&lt;/p&gt;

&lt;p&gt;Canonical record fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;description&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;labels&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;optional &lt;code&gt;timestamp_unix_ms&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separated normalization from transport and moved us closer to the milestone’s delivery pipeline model.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Formatter support for canonical metrics
&lt;/h2&gt;

&lt;p&gt;Extended &lt;code&gt;src/formatters/prometheus.py&lt;/code&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;format_canonical(metrics)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets formatters operate on canonical data (not collector-specific payload dictionaries) while preserving the existing Prometheus text exposition output.&lt;/p&gt;

&lt;h2&gt;
  
  
  5) Main loop refactor to exporter lifecycle
&lt;/h2&gt;

&lt;p&gt;Updated &lt;code&gt;src/main.py&lt;/code&gt; so startup and runtime flow is now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;resolve &lt;code&gt;EXPORTER_TYPE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;create_exporter(...)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exporter.initialize()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;collect payloads each cycle&lt;/li&gt;
&lt;li&gt;normalize to canonical metrics&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exporter.export(canonical_metrics)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exporter.shutdown()&lt;/code&gt; in &lt;code&gt;finally&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Direct &lt;code&gt;print(...)&lt;/code&gt; of telemetry output was removed from &lt;code&gt;main.py&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6) Python 3.10 typing compatibility fix
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;src/exporters/base.py&lt;/code&gt; originally used &lt;code&gt;typing.NotRequired&lt;/code&gt;, which is not available in Python 3.10’s &lt;code&gt;typing&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CanonicalMetric&lt;/code&gt; TypedDict was adjusted to a Python-3.10-safe form using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;required base TypedDict&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;total=False&lt;/code&gt; extension for optional timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This kept type intent intact without requiring runtime upgrades.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation and runtime output
&lt;/h2&gt;

&lt;p&gt;Validation performed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;python3 -m compileall src&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;smoke execution path for exporter creation + canonical conversion + console export&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Observed runtime behavior after refactor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collector logs still emitted&lt;/li&gt;
&lt;li&gt;Prometheus lines still emitted each cycle&lt;/li&gt;
&lt;li&gt;timestamps populated in Unix milliseconds&lt;/li&gt;
&lt;li&gt;disk metrics emitted as aggregate and per-device series&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words: behavior stayed stable, but ownership moved to exporter architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What M3-3 achieved (and what it didn’t)
&lt;/h2&gt;

&lt;p&gt;Completed in M3-3:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;console output now runs through exporter interface&lt;/li&gt;
&lt;li&gt;runtime flow is wired to exporter lifecycle&lt;/li&gt;
&lt;li&gt;normalization and formatting layers are separated from collection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not part of M3-3 (handled in later items):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;strict fail-fast invalid exporter value handling (&lt;code&gt;M3-4&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;additional backend exporters (Datadog, OTLP HTTP, New Relic)&lt;/li&gt;
&lt;li&gt;retry/buffering semantics beyond base hooks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key lesson
&lt;/h2&gt;

&lt;p&gt;This milestone was less about adding features and more about installing architectural seams.&lt;/p&gt;

&lt;p&gt;The code now has explicit boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collectors collect&lt;/li&gt;
&lt;li&gt;pipeline normalizes&lt;/li&gt;
&lt;li&gt;formatter renders&lt;/li&gt;
&lt;li&gt;exporter delivers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That separation is what will let future backend integrations land without rewriting collectors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next up
&lt;/h2&gt;

&lt;p&gt;The immediate next step is &lt;code&gt;M3-4&lt;/code&gt;: enforce strict startup validation for unsupported &lt;code&gt;EXPORTER_TYPE&lt;/code&gt; values so runtime fails fast with explicit errors instead of warning + fallback.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>python</category>
      <category>telemetry</category>
      <category>devops</category>
    </item>
    <item>
      <title>Next Milestones for Heka Insights Agent: From Console Output to Real Telemetry Delivery</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Tue, 21 Apr 2026 08:48:33 +0000</pubDate>
      <link>https://dev.to/munirfarhan/next-milestones-for-heka-insights-agent-from-console-output-to-real-telemetry-delivery-jep</link>
      <guid>https://dev.to/munirfarhan/next-milestones-for-heka-insights-agent-from-console-output-to-real-telemetry-delivery-jep</guid>
      <description>&lt;p&gt;We’re moving beyond console-only output and into real telemetry delivery.&lt;/p&gt;

&lt;p&gt;Over the next few milestones, &lt;strong&gt;heka-insights-agent&lt;/strong&gt; will introduce a proper exporter layer, OTLP HTTP support, and first-class integrations for &lt;strong&gt;New Relic&lt;/strong&gt; and &lt;strong&gt;Datadog&lt;/strong&gt;. The focus is to keep the agent vendor-agnostic at its core while making it easier to route system metrics into modern observability platforms using clean, configurable dispatch patterns.&lt;/p&gt;

&lt;p&gt;Project board: &lt;a href="https://github.com/users/ronin1770/projects/3/views/1" rel="noopener noreferrer"&gt;https://github.com/users/ronin1770/projects/3/views/1&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  python #observability #opentelemetry #devops #monitoring #prometheus #datadog #newrelic #opensource
&lt;/h1&gt;

</description>
      <category>devops</category>
      <category>python</category>
      <category>datadog</category>
      <category>telemetry</category>
    </item>
    <item>
      <title>✅ Milestone Completed: Prometheus Data Format Integration</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Sun, 19 Apr 2026 07:36:58 +0000</pubDate>
      <link>https://dev.to/munirfarhan/milestone-completed-prometheus-data-format-integration-12l8</link>
      <guid>https://dev.to/munirfarhan/milestone-completed-prometheus-data-format-integration-12l8</guid>
      <description>&lt;h1&gt;
  
  
  ✅ Milestone Completed: Prometheus Data Format Integration
&lt;/h1&gt;

&lt;p&gt;This sprint focused on making telemetry output fully Prometheus-compatible while preserving our existing collector pipeline for CPU, memory, and disk I/O.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I implemented
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Added Prometheus text exposition format (v0.0.4) output&lt;/li&gt;
&lt;li&gt;Included &lt;code&gt;# HELP&lt;/code&gt; and &lt;code&gt;# TYPE&lt;/code&gt; metadata&lt;/li&gt;
&lt;li&gt;Supported &lt;code&gt;gauge&lt;/code&gt; and &lt;code&gt;counter&lt;/code&gt; metric families&lt;/li&gt;
&lt;li&gt;Added label-based dimensions (CPU modes, disk devices)&lt;/li&gt;
&lt;li&gt;Kept output deterministic and scrape-ready for a &lt;code&gt;/metrics&lt;/code&gt; style endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Metrics now covered
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CPU usage and per-mode CPU time distribution&lt;/li&gt;
&lt;li&gt;Virtual memory: used, available, total&lt;/li&gt;
&lt;li&gt;Swap memory: used, total&lt;/li&gt;
&lt;li&gt;Disk I/O bytes: read/write (aggregate + per-device)&lt;/li&gt;
&lt;li&gt;Disk I/O operations: read/write (aggregate + per-device)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Validation results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Output verified against Prometheus exposition rules&lt;/li&gt;
&lt;li&gt;No syntax violations found&lt;/li&gt;
&lt;li&gt;Metrics are parseable and scrape-ready&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prior milestone context (OpenMetrics)
&lt;/h2&gt;

&lt;p&gt;Before this, I shipped OpenMetrics-aligned output for the same core Linux host metrics with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;# HELP&lt;/code&gt;, &lt;code&gt;# TYPE&lt;/code&gt;, &lt;code&gt;# UNIT&lt;/code&gt; metadata&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;# EOF&lt;/code&gt; termination&lt;/li&gt;
&lt;li&gt;Valid CPU, memory, and disk payload output&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next improvements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Evaluate ratio-based CPU values (0–1) vs percentage&lt;/li&gt;
&lt;li&gt;Extend optional unit handling for stronger tooling interoperability&lt;/li&gt;
&lt;li&gt;Continue OpenMetrics alignment where needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;https://github.com/ronin1770/heka-insights-agent&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>telemetry</category>
      <category>openmetrics</category>
      <category>prometheus</category>
    </item>
    <item>
      <title>Milestone 2: Standardizing Telemetry Output with JSON, Prometheus, and OpenMetrics</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Thu, 16 Apr 2026 15:25:23 +0000</pubDate>
      <link>https://dev.to/munirfarhan/milestone-2-standardizing-telemetry-output-with-json-prometheus-and-openmetrics-22ec</link>
      <guid>https://dev.to/munirfarhan/milestone-2-standardizing-telemetry-output-with-json-prometheus-and-openmetrics-22ec</guid>
      <description>&lt;h1&gt;
  
  
  Milestone 2: Standardizing Telemetry Output with JSON, Prometheus, and OpenMetrics
&lt;/h1&gt;

&lt;p&gt;In this milestone, we are focusing on one thing only: &lt;strong&gt;data format standardization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Heka Insights Agent already collects CPU, memory, and disk telemetry.&lt;br&gt;&lt;br&gt;
Now the goal is to emit the same logical metrics in three standard output formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON&lt;/li&gt;
&lt;li&gt;Prometheus text exposition&lt;/li&gt;
&lt;li&gt;OpenMetrics text format&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Milestone Matters
&lt;/h2&gt;

&lt;p&gt;If an agent has no clear format strategy, every downstream integration becomes custom work.&lt;br&gt;&lt;br&gt;
That slows down adoption and increases maintenance cost.&lt;/p&gt;

&lt;p&gt;By standardizing format early, we get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stable contracts for integrations&lt;/li&gt;
&lt;li&gt;easier validation and testing&lt;/li&gt;
&lt;li&gt;portability across observability stacks&lt;/li&gt;
&lt;li&gt;clearer boundaries between collection and export&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Milestone Scope (Only Data Format)
&lt;/h2&gt;

&lt;p&gt;This milestone does not include transports, retry logic, or backend adapters.&lt;br&gt;&lt;br&gt;
It only covers how telemetry is represented and serialized.&lt;/p&gt;

&lt;p&gt;Included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;canonical internal metric model&lt;/li&gt;
&lt;li&gt;naming/type/unit rules&lt;/li&gt;
&lt;li&gt;serializers for &lt;code&gt;json&lt;/code&gt;, &lt;code&gt;prometheus&lt;/code&gt;, &lt;code&gt;openmetrics&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;deterministic output behavior&lt;/li&gt;
&lt;li&gt;contract tests with golden files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Out of scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Datadog/New Relic senders&lt;/li&gt;
&lt;li&gt;batching/compression/persistence&lt;/li&gt;
&lt;li&gt;new collector domains&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Canonical Metric Contract
&lt;/h2&gt;

&lt;p&gt;Every metric will be representable through one shared contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; (string)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; (string)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt; (&lt;code&gt;gauge&lt;/code&gt; or &lt;code&gt;counter&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unit&lt;/code&gt; (e.g. &lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;seconds&lt;/code&gt;, &lt;code&gt;percent&lt;/code&gt;, &lt;code&gt;count&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;value&lt;/code&gt; (number)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;labels&lt;/code&gt; (map of string to string; empty allowed)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;timestamp_unix_ms&lt;/code&gt; (optional integer)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This contract is the core design decision in Milestone 2.&lt;br&gt;&lt;br&gt;
Serializers consume this model and render format-specific output without changing metric meaning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming and Semantics Rules
&lt;/h2&gt;

&lt;p&gt;To keep the output stable and machine-friendly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;metric names are lowercase snake_case&lt;/li&gt;
&lt;li&gt;all names are prefixed with &lt;code&gt;heka_&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;counters end in &lt;code&gt;_total&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;unit suffixes are explicit (&lt;code&gt;_bytes&lt;/code&gt;, &lt;code&gt;_seconds&lt;/code&gt;, &lt;code&gt;_percent&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;label keys are lowercase snake_case&lt;/li&gt;
&lt;li&gt;metric identity must stay consistent across formats&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Current Metric Mapping
&lt;/h2&gt;

&lt;p&gt;Initial canonical mapping includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;heka_cpu_usage_percent&lt;/code&gt; (gauge)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_cpu_time_percent&lt;/code&gt; (gauge with &lt;code&gt;mode=&amp;lt;field&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_memory_virtual_used_bytes&lt;/code&gt; (gauge)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_memory_virtual_available_bytes&lt;/code&gt; (gauge)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_memory_virtual_total_bytes&lt;/code&gt; (gauge)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_memory_swap_used_bytes&lt;/code&gt; (gauge)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_memory_swap_total_bytes&lt;/code&gt; (gauge)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_disk_read_bytes_total&lt;/code&gt; (counter)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_disk_write_bytes_total&lt;/code&gt; (counter)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_disk_reads_total&lt;/code&gt; (counter)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heka_disk_writes_total&lt;/code&gt; (counter)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Format-Specific Requirements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JSON
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;UTF-8 JSON object&lt;/li&gt;
&lt;li&gt;includes &lt;code&gt;schema_version&lt;/code&gt; (starting at &lt;code&gt;v1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;includes &lt;code&gt;generated_at&lt;/code&gt; (RFC3339 UTC)&lt;/li&gt;
&lt;li&gt;includes top-level &lt;code&gt;metrics&lt;/code&gt; array&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prometheus
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus text exposition format (&lt;code&gt;0.0.4&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;include &lt;code&gt;# HELP&lt;/code&gt; and &lt;code&gt;# TYPE&lt;/code&gt; lines&lt;/li&gt;
&lt;li&gt;deterministic label ordering&lt;/li&gt;
&lt;li&gt;no OpenMetrics-only directives&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  OpenMetrics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;OpenMetrics text format&lt;/li&gt;
&lt;li&gt;include &lt;code&gt;# HELP&lt;/code&gt;, &lt;code&gt;# TYPE&lt;/code&gt;, and &lt;code&gt;# UNIT&lt;/code&gt; when known&lt;/li&gt;
&lt;li&gt;terminate payload with &lt;code&gt;# EOF&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;metric names and labels remain aligned with Prometheus mode&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configuration Contract
&lt;/h2&gt;

&lt;p&gt;One selector controls serialization:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OUTPUT_FORMAT=json|prometheus|openmetrics&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;default: &lt;code&gt;json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;invalid values: fail fast with a clear startup error&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Acceptance Criteria
&lt;/h2&gt;

&lt;p&gt;Milestone 2 is done when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;same logical metric set is emitted in all three formats&lt;/li&gt;
&lt;li&gt;names/types/units are consistent&lt;/li&gt;
&lt;li&gt;Prometheus and OpenMetrics outputs validate&lt;/li&gt;
&lt;li&gt;JSON includes schema metadata and metrics array&lt;/li&gt;
&lt;li&gt;output order is deterministic&lt;/li&gt;
&lt;li&gt;golden-file tests exist for each format&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GitHub Milestone Breakdown
&lt;/h2&gt;

&lt;p&gt;Work is tracked through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;M2-1 canonical metric model&lt;/li&gt;
&lt;li&gt;M2-2 collector-to-canonical mapping&lt;/li&gt;
&lt;li&gt;M2-3 JSON serializer&lt;/li&gt;
&lt;li&gt;M2-4 Prometheus serializer&lt;/li&gt;
&lt;li&gt;M2-5 OpenMetrics serializer&lt;/li&gt;
&lt;li&gt;M2-6 output format config + validation&lt;/li&gt;
&lt;li&gt;M2-7 fixture/contract tests&lt;/li&gt;
&lt;li&gt;M2-8 docs update&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Repo
&lt;/h2&gt;

</description>
      <category>telemetry</category>
      <category>opensource</category>
      <category>devops</category>
      <category>python</category>
    </item>
    <item>
      <title>Heka Insights Agent Update: Architecture + Configuration Docs Now Reflect Runtime Behavior</title>
      <dc:creator>Farhan Munir</dc:creator>
      <pubDate>Thu, 16 Apr 2026 05:37:17 +0000</pubDate>
      <link>https://dev.to/munirfarhan/heka-insights-agent-update-architecture-configuration-docs-now-reflect-runtime-behavior-2e8k</link>
      <guid>https://dev.to/munirfarhan/heka-insights-agent-update-architecture-configuration-docs-now-reflect-runtime-behavior-2e8k</guid>
      <description>&lt;h1&gt;
  
  
  Build Update (April 16, 2026)
&lt;/h1&gt;

&lt;p&gt;This week I focused on documentation quality and operational clarity for &lt;code&gt;heka-insights-agent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The goal was simple: make docs match the code exactly, so contributors and operators can reason about behavior without reading every module first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I updated
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rewrote &lt;code&gt;docs/architecture.md&lt;/code&gt; from scratch&lt;/li&gt;
&lt;li&gt;Rewrote &lt;code&gt;docs/configuration.md&lt;/code&gt; from scratch&lt;/li&gt;
&lt;li&gt;Expanded &lt;code&gt;README.md&lt;/code&gt; with project context, setup, and environment guidance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture documentation improvements
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docs/architecture.md&lt;/code&gt; now documents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the actual runtime topology and control loop in &lt;code&gt;src/main.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;collector boundaries and behavior (&lt;code&gt;CPUCollector&lt;/code&gt;, &lt;code&gt;MemoryCollector&lt;/code&gt;, &lt;code&gt;DiskCollector&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;logging subsystem behavior in &lt;code&gt;src/logger/config.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;current payload shapes emitted by collectors&lt;/li&gt;
&lt;li&gt;known gaps (no sender layer yet, no tests yet, no schema versioning yet)&lt;/li&gt;
&lt;li&gt;practical extension points for next phases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives a real “as-implemented” architecture baseline instead of aspirational text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration documentation improvements
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docs/configuration.md&lt;/code&gt; now includes exact behavior for the two active runtime settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LOG_LOCATION&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CPU_POLL_INTERVAL_SECONDS&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also documents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;source/precedence rules&lt;/li&gt;
&lt;li&gt;defaults and validation behavior&lt;/li&gt;
&lt;li&gt;failure modes&lt;/li&gt;
&lt;li&gt;local setup and production recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Important behavior clarified
&lt;/h2&gt;

&lt;p&gt;Current config loading is split across two env files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;root &lt;code&gt;.env&lt;/code&gt; is used for &lt;code&gt;LOG_LOCATION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/.env&lt;/code&gt; is used for &lt;code&gt;CPU_POLL_INTERVAL_SECONDS&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That split is now explicitly documented to reduce startup/debug confusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;For an agent project, docs are part of reliability.&lt;br&gt;&lt;br&gt;
Operators need to know what can fail at startup, where config is read from, and what telemetry shape to expect downstream.&lt;/p&gt;

&lt;p&gt;This update makes onboarding and future refactors safer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;add transport/sender layer (backend adapters)&lt;/li&gt;
&lt;li&gt;add collector-focused tests&lt;/li&gt;
&lt;li&gt;consolidate config loading into a single source&lt;/li&gt;
&lt;li&gt;define schema/versioning strategy for emitted payloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/ronin1770/heka-insights-agent" rel="noopener noreferrer"&gt;https://github.com/ronin1770/heka-insights-agent&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>linux</category>
      <category>devops</category>
      <category>observability</category>
    </item>
  </channel>
</rss>
