<?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: Christophe Chaussat</title>
    <description>The latest articles on DEV Community by Christophe Chaussat (@christophe_chaussat_01ef4).</description>
    <link>https://dev.to/christophe_chaussat_01ef4</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%2F4119555%2F7cd41ed5-f4c2-474f-a320-1af93e108f82.png</url>
      <title>DEV Community: Christophe Chaussat</title>
      <link>https://dev.to/christophe_chaussat_01ef4</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/christophe_chaussat_01ef4"/>
    <language>en</language>
    <item>
      <title>Processing Heterogeneous IoT Logs with Fluent Bit and Elasticsearch</title>
      <dc:creator>Christophe Chaussat</dc:creator>
      <pubDate>Thu, 10 Sep 2026 15:41:55 +0000</pubDate>
      <link>https://dev.to/christophe_chaussat_01ef4/processing-heterogeneous-iot-logs-with-fluent-bit-and-elasticsearch-4i8l</link>
      <guid>https://dev.to/christophe_chaussat_01ef4/processing-heterogeneous-iot-logs-with-fluent-bit-and-elasticsearch-4i8l</guid>
      <description>&lt;h2&gt;
  
  
  A lightweight two-stage approach for parsing, preprocessing and storing semi-structured home automation data
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The full configuration example is available on GitHub.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Home automation systems tend to generate a surprisingly heterogeneous collection of logs and measurements.&lt;/p&gt;

&lt;p&gt;In this project, most data originates from Domoticz, but additional information is produced by ESP8266/D1 devices, alarm scripts, monitoring tools and other IoT components. Some records are plain text, some contain timestamps and metadata, while others contain JSON embedded inside a log line.&lt;/p&gt;

&lt;p&gt;Rather than forcing every producer into a single format, I use a two-stage processing architecture based on &lt;strong&gt;Fluent Bit and Elasticsearch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The complete chain is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    IoT / home automation sources
                              |
             +----------------+----------------+
             |                |                |
          Domoticz          ESP/D1         Other scripts
             |                |                |
             +----------------+----------------+
                              |
                         Fluent Bit
                              |
                    parsing + preprocessing
                              |
                              v
                        Elasticsearch
                              |
                       ingest pipeline
                              |
                     final JSON decoding
                              |
                              v
                         dom_v3 index
                              |
                   +----------+----------+
                   |                     |
                 Kibana               Grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete pipeline normally has a latency of less than one minute in the author's installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why two processing stages?
&lt;/h2&gt;

&lt;p&gt;The main design decision is to avoid making Fluent Bit responsible for every transformation.&lt;/p&gt;

&lt;p&gt;Fluent Bit performs the first level of processing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reading the various log files;&lt;/li&gt;
&lt;li&gt;recognizing several recurring line formats;&lt;/li&gt;
&lt;li&gt;extracting timestamps and metadata;&lt;/li&gt;
&lt;li&gt;decoding JSON when it is directly available;&lt;/li&gt;
&lt;li&gt;removing intermediate fields;&lt;/li&gt;
&lt;li&gt;forwarding the resulting records to Elasticsearch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Elasticsearch then performs the final JSON decoding through an ingest pipeline.&lt;/p&gt;

&lt;p&gt;This separation keeps the Fluent Bit configuration relatively simple while giving Elasticsearch responsibility for the final document transformation.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Fluent Bit parsers
&lt;/h2&gt;

&lt;p&gt;The incoming data belongs to several recurring families. Instead of trying to recognize all of them with one very large regular expression, the configuration uses several smaller parsers.&lt;/p&gt;

&lt;p&gt;A typical Domoticz format is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[PARSER]&lt;/span&gt;
    &lt;span class="err"&gt;Name&lt;/span&gt;    &lt;span class="err"&gt;domoticz_parser_1&lt;/span&gt;
    &lt;span class="err"&gt;Format&lt;/span&gt;  &lt;span class="err"&gt;regex&lt;/span&gt;
    &lt;span class="err"&gt;Time_Key&lt;/span&gt;    &lt;span class="err"&gt;dom_timestamp&lt;/span&gt;
    &lt;span class="err"&gt;Time_Format&lt;/span&gt; &lt;span class="err"&gt;%Y-%m-%d&lt;/span&gt; &lt;span class="err"&gt;%H:%M:%S.%L&lt;/span&gt;
    &lt;span class="err"&gt;Time_Offset&lt;/span&gt; &lt;span class="err"&gt;+0200&lt;/span&gt;
    &lt;span class="err"&gt;Regex&lt;/span&gt;   &lt;span class="err"&gt;^(?&amp;lt;dom_timestamp&amp;gt;.*)&lt;/span&gt;  &lt;span class="err"&gt;(?&amp;lt;dom_source&amp;gt;\w+)\:&lt;/span&gt; &lt;span class="err"&gt;(?&amp;lt;msgtxt&amp;gt;.*)$&lt;/span&gt;
    &lt;span class="err"&gt;Decode_Field&lt;/span&gt; &lt;span class="err"&gt;json&lt;/span&gt; &lt;span class="err"&gt;msgtxt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This extracts the timestamp and source and decodes the JSON contained in &lt;code&gt;msgtxt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another Domoticz format is handled separately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[PARSER]&lt;/span&gt;
    &lt;span class="err"&gt;Name&lt;/span&gt;    &lt;span class="err"&gt;domoticz_parser_2&lt;/span&gt;
    &lt;span class="err"&gt;Format&lt;/span&gt;  &lt;span class="err"&gt;regex&lt;/span&gt;
    &lt;span class="err"&gt;Time_Key&lt;/span&gt;    &lt;span class="err"&gt;dom_timestamp&lt;/span&gt;
    &lt;span class="err"&gt;Time_Format&lt;/span&gt; &lt;span class="err"&gt;%Y-%m-%d&lt;/span&gt; &lt;span class="err"&gt;%H:%M:%S.%L&lt;/span&gt;
    &lt;span class="err"&gt;Time_Offset&lt;/span&gt; &lt;span class="err"&gt;+0200&lt;/span&gt;
    &lt;span class="err"&gt;Regex&lt;/span&gt;   &lt;span class="err"&gt;^(?&amp;lt;dom_timestamp&amp;gt;.*)&lt;/span&gt;  &lt;span class="err"&gt;\((?&amp;lt;dom_hardware&amp;gt;\w+)\)&lt;/span&gt; &lt;span class="err"&gt;(?&amp;lt;dom_category&amp;gt;.*)&lt;/span&gt; &lt;span class="err"&gt;\((?&amp;lt;dom_device&amp;gt;\w+)\)$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generic JSON-bearing records are covered by additional parsers, including a final fallback for pure JSON.&lt;/p&gt;

&lt;p&gt;The complete examples are provided in &lt;code&gt;fluent-bit/parsers.conf&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Collecting the different sources
&lt;/h2&gt;

&lt;p&gt;Fluent Bit's &lt;code&gt;tail&lt;/code&gt; input monitors the individual log files. Each source receives its own tag and persistent database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[INPUT]&lt;/span&gt;
    &lt;span class="err"&gt;Name&lt;/span&gt;   &lt;span class="err"&gt;tail&lt;/span&gt;
    &lt;span class="err"&gt;Tag&lt;/span&gt;    &lt;span class="err"&gt;domoticz&lt;/span&gt;
    &lt;span class="err"&gt;Path&lt;/span&gt;   &lt;span class="err"&gt;/path/to/domoticz.log&lt;/span&gt;
    &lt;span class="err"&gt;DB&lt;/span&gt;     &lt;span class="err"&gt;/var/spool/fb_domoticz.db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real installation contains several additional sources for ESP/D1 devices, alarms, metrics, monitoring and Tuya-related data.&lt;/p&gt;

&lt;p&gt;The tag provides a simple way of retaining the origin of each record.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Applying several parsers
&lt;/h2&gt;

&lt;p&gt;The Domoticz records are processed with the parser filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[FILTER]&lt;/span&gt;
    &lt;span class="err"&gt;Name&lt;/span&gt;      &lt;span class="err"&gt;parser&lt;/span&gt;
    &lt;span class="err"&gt;Match&lt;/span&gt;     &lt;span class="err"&gt;domoticz&lt;/span&gt;
    &lt;span class="err"&gt;Key_Name&lt;/span&gt;  &lt;span class="err"&gt;log&lt;/span&gt;
    &lt;span class="err"&gt;Parser&lt;/span&gt;    &lt;span class="err"&gt;domoticz_parser_1&lt;/span&gt;
    &lt;span class="err"&gt;Parser&lt;/span&gt;    &lt;span class="err"&gt;domoticz_parser_2&lt;/span&gt;
    &lt;span class="err"&gt;Parser&lt;/span&gt;    &lt;span class="err"&gt;domoticz_parser_3&lt;/span&gt;
    &lt;span class="err"&gt;Parser&lt;/span&gt;    &lt;span class="err"&gt;domoticz_parser_4&lt;/span&gt;
    &lt;span class="err"&gt;Parser&lt;/span&gt;    &lt;span class="err"&gt;domoticz_parser_5&lt;/span&gt;
    &lt;span class="err"&gt;Reserve_Data&lt;/span&gt; &lt;span class="err"&gt;On&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The individual expressions act as recognizers for recurring formats. This is easier to maintain than one large regular expression attempting to describe every possible record.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Reserve_Data On&lt;/code&gt; keeps the original record available while parsed fields are added.&lt;/p&gt;

&lt;p&gt;Intermediate fields can then be removed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[FILTER]&lt;/span&gt;
    &lt;span class="err"&gt;Name&lt;/span&gt;        &lt;span class="err"&gt;record_modifier&lt;/span&gt;
    &lt;span class="err"&gt;Match&lt;/span&gt;       &lt;span class="err"&gt;domoticz&lt;/span&gt;
    &lt;span class="err"&gt;Remove_key&lt;/span&gt;  &lt;span class="err"&gt;msgtxt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Sending the preprocessed data to Elasticsearch
&lt;/h2&gt;

&lt;p&gt;The resulting records are sent to a common Elasticsearch index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[OUTPUT]&lt;/span&gt;
    &lt;span class="err"&gt;Name&lt;/span&gt;                &lt;span class="err"&gt;es&lt;/span&gt;
    &lt;span class="err"&gt;Match&lt;/span&gt;               &lt;span class="err"&gt;*&lt;/span&gt;
    &lt;span class="err"&gt;Host&lt;/span&gt;                &lt;span class="err"&gt;127.0.0.1&lt;/span&gt;
    &lt;span class="err"&gt;Port&lt;/span&gt;                &lt;span class="err"&gt;9200&lt;/span&gt;
    &lt;span class="err"&gt;HTTP_User&lt;/span&gt;           &lt;span class="err"&gt;elastic&lt;/span&gt;
    &lt;span class="err"&gt;HTTP_Passwd&lt;/span&gt;         &lt;span class="err"&gt;&amp;lt;set-securely&amp;gt;&lt;/span&gt;
    &lt;span class="err"&gt;tls&lt;/span&gt;                 &lt;span class="err"&gt;On&lt;/span&gt;
    &lt;span class="err"&gt;tls.verify&lt;/span&gt;          &lt;span class="err"&gt;Off&lt;/span&gt;
    &lt;span class="err"&gt;Include_Tag_Key&lt;/span&gt;     &lt;span class="err"&gt;On&lt;/span&gt;
    &lt;span class="err"&gt;Tag_Key&lt;/span&gt;             &lt;span class="err"&gt;fb_tag&lt;/span&gt;
    &lt;span class="err"&gt;Index&lt;/span&gt;               &lt;span class="err"&gt;dom_v3&lt;/span&gt;
    &lt;span class="err"&gt;Type&lt;/span&gt;                &lt;span class="err"&gt;_doc&lt;/span&gt;
    &lt;span class="err"&gt;Suppress_Type_Name&lt;/span&gt;  &lt;span class="err"&gt;On&lt;/span&gt;
    &lt;span class="err"&gt;Retry_Limit&lt;/span&gt;         &lt;span class="err"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example deliberately does not contain a real password.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;tls.verify Off&lt;/code&gt; setting is specific to the author's local installation and should not be copied blindly. A network-accessible Elasticsearch instance should normally use proper certificate verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Final JSON processing in Elasticsearch
&lt;/h2&gt;

&lt;p&gt;The second stage is implemented as an Elasticsearch ingest pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dom_v3 ingestion pipeline v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"processors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"json"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ignore_failure"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"add_to_root"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"log"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The purpose is to decode JSON that remains in the &lt;code&gt;log&lt;/code&gt; field and add the decoded fields to the document root.&lt;/p&gt;

&lt;p&gt;For example, a simplified intermediate document can contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"log"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;temperature&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:21.7,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;humidity&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:48}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dom_timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-10 10:23:41.123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dom_source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sensor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fb_tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"domoticz"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the ingest pipeline, the document can contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dom_timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-10 10:23:41.123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dom_source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sensor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;21.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"humidity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fb_tag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"domoticz"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is deliberately simplified; the actual records may contain substantially more nested information.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Why not do everything in Fluent Bit?
&lt;/h2&gt;

&lt;p&gt;It would be possible to push more processing into Fluent Bit. In this application, however, the separation proved more convenient.&lt;/p&gt;

&lt;p&gt;Fluent Bit is used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collection;&lt;/li&gt;
&lt;li&gt;line-oriented recognition;&lt;/li&gt;
&lt;li&gt;regular-expression parsing;&lt;/li&gt;
&lt;li&gt;timestamp extraction;&lt;/li&gt;
&lt;li&gt;first-level JSON decoding;&lt;/li&gt;
&lt;li&gt;metadata and filtering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Elasticsearch is used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;final document transformation;&lt;/li&gt;
&lt;li&gt;JSON decoding;&lt;/li&gt;
&lt;li&gt;indexing and mapping;&lt;/li&gt;
&lt;li&gt;subsequent search and visualization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps each component focused on the type of work it handles well.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Mappings matter
&lt;/h2&gt;

&lt;p&gt;JSON decoding does not automatically guarantee that every field will have the desired Elasticsearch type.&lt;/p&gt;

&lt;p&gt;Measurements such as temperature and humidity should be indexed as numeric fields, while timestamps should use an appropriate date mapping.&lt;/p&gt;

&lt;p&gt;This is especially important when the resulting data is queried or visualized by Grafana.&lt;/p&gt;

&lt;p&gt;For a production deployment, index mappings should therefore be designed explicitly for the metrics expected from the installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Why this approach works well for home automation
&lt;/h2&gt;

&lt;p&gt;Home automation installations rarely produce perfectly homogeneous data.&lt;/p&gt;

&lt;p&gt;A single installation may contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;application logs;&lt;/li&gt;
&lt;li&gt;sensor measurements;&lt;/li&gt;
&lt;li&gt;alarm events;&lt;/li&gt;
&lt;li&gt;device status;&lt;/li&gt;
&lt;li&gt;network information;&lt;/li&gt;
&lt;li&gt;JSON APIs;&lt;/li&gt;
&lt;li&gt;diagnostic messages;&lt;/li&gt;
&lt;li&gt;custom scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trying to force every producer to emit exactly the same format can require unnecessary changes to individual applications.&lt;/p&gt;

&lt;p&gt;The approach described here instead accepts heterogeneity at the input and progressively transforms it into structured Elasticsearch documents.&lt;/p&gt;

&lt;p&gt;Adding another source generally requires another Fluent Bit input and, when necessary, another parser.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Result
&lt;/h2&gt;

&lt;p&gt;The architecture has proved sufficient for the author's home automation environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Various IoT sources
        |
        v
   Fluent Bit
        |
        +-- regex parsing
        +-- timestamp extraction
        +-- JSON preprocessing
        +-- metadata
        +-- filtering
        |
        v
  Elasticsearch
        |
        +-- ingest pipeline
              |
              +-- final JSON decoding
        |
        v
      dom_v3
        |
   +----+----+
   |         |
 Kibana    Grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete chain normally has a latency of less than one minute in this installation.&lt;/p&gt;

&lt;p&gt;The main advantage is not raw processing complexity, but keeping the architecture understandable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fluent Bit collects and recognizes.&lt;br&gt;&lt;br&gt;
Elasticsearch structures and stores.&lt;br&gt;&lt;br&gt;
Kibana and Grafana visualize.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For heterogeneous IoT and home automation data, combining Fluent Bit with Elasticsearch ingest pipelines provides a practical way of progressively converting unstructured log streams into structured data.&lt;/p&gt;

&lt;p&gt;The key design principle is to avoid making any single component responsible for the complete transformation.&lt;/p&gt;

&lt;p&gt;The resulting architecture is small enough for a home automation environment while remaining flexible enough to accommodate additional sensors, scripts and data sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;p&gt;This article was prepared by &lt;strong&gt;Christophe Chaussat&lt;/strong&gt;, based on his own home automation installation, configuration and experiments.&lt;/p&gt;

&lt;p&gt;ChatGPT (OpenAI) assisted with the structuring, editing and technical writing of this documentation. The technical architecture and configuration described here are based on the author's own installation and experiments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Licensing
&lt;/h2&gt;

&lt;p&gt;The configuration and software examples available on GitHub (cchaussat/fluent-bit-elasticsearch-iot-logging) are released under the MIT License.&lt;/p&gt;

&lt;p&gt;This article and the accompanying documentation are released under the Creative Commons Attribution 4.0 International License (CC BY 4.0).&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>automation</category>
      <category>iot</category>
      <category>monitoring</category>
    </item>
  </channel>
</rss>
