<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Flow by example on Grafana Labs</title><link>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/</link><description>Recent content in Flow by example on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/agent/v0.44/flow/tutorials/flow-by-example/index.xml" rel="self" type="application/rss+xml"/><item><title>Get started</title><link>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/get-started/</link><pubDate>Tue, 10 Mar 2026 03:19:46 +0000</pubDate><guid>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/get-started/</guid><content><![CDATA[&lt;h1 id=&#34;get-started&#34;&gt;Get started&lt;/h1&gt;
&lt;p&gt;This set of tutorials contains a collection of examples that build on each other to demonstrate how to configure and use &lt;a href=&#34;/docs/agent/latest/flow/&#34;&gt;Grafana Agent Flow&lt;/a&gt;. It assumes you have a basic understanding of what Grafana Agent is and telemetry collection in general. It also assumes a base level of familiarity with Prometheus and PromQL, Loki and LogQL, and basic Grafana navigation. It assumes no knowledge of Grafana Agent Flow or River concepts.&lt;/p&gt;
&lt;h2 id=&#34;what-is-flow&#34;&gt;What is Flow?&lt;/h2&gt;
&lt;p&gt;Flow is a new way to configure Grafana Agent Flow. It is a declarative configuration language that allows you to define a pipeline of telemetry collection, processing, and output. It is built on top of the &lt;a href=&#34;https://github.com/grafana/river&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;River&lt;/a&gt; configuration language, which is designed to be fast, simple, and debuggable.&lt;/p&gt;
&lt;h2 id=&#34;what-do-i-need-to-get-started&#34;&gt;What do I need to get started?&lt;/h2&gt;
&lt;p&gt;You will need a Linux or Unix environment with Docker installed. The examples are designed to be run on a single host so that you can run them on your laptop or in a VM. You are encouraged to follow along with the examples using a &lt;code&gt;config.river&lt;/code&gt; file and experiment with the examples yourself.&lt;/p&gt;
&lt;p&gt;To run the examples, you should have a Grafana Agent binary available. You can follow the instructions on how to &lt;a href=&#34;/docs/agent/latest/flow/setup/install/binary/#install-grafana-agent-in-flow-mode-as-a-standalone-binary&#34;&gt;Install Grafana Agent as a Standalone Binary&lt;/a&gt; to get a binary.&lt;/p&gt;
&lt;h2 id=&#34;how-should-i-follow-along&#34;&gt;How should I follow along?&lt;/h2&gt;
&lt;p&gt;You can use this docker-compose file to set up a local Grafana instance alongside Loki and Prometheus pre-configured as datasources. The examples are designed to be run locally, so you can follow along and experiment with them yourself.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: &amp;#39;3&amp;#39;
services:
  loki:
    image: grafana/loki:2.9.0
    ports:
      - &amp;#34;3100:3100&amp;#34;
    command: -config.file=/etc/loki/local-config.yaml
  prometheus:
    image: prom/prometheus:v2.47.0
    command:
      - --web.enable-remote-write-receiver
      - --config.file=/etc/prometheus/prometheus.yml
    ports:
      - &amp;#34;9090:9090&amp;#34;
  grafana:
    environment:
      - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
    entrypoint:
      - sh
      - -euc
      - |
        mkdir -p /etc/grafana/provisioning/datasources
        cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/grafana/provisioning/datasources/ds.yaml
        apiVersion: 1
        datasources:
        - name: Loki
          type: loki
          access: proxy
          orgId: 1
          url: http://loki:3100
          basicAuth: false
          isDefault: false
          version: 1
          editable: false
        - name: Prometheus
          type: prometheus
          orgId: 1
          url: http://prometheus:9090
          basicAuth: false
          isDefault: true
          version: 1
          editable: false
        EOF
        /run.sh
    image: grafana/grafana:latest
    ports:
      - &amp;#34;3000:3000&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After running &lt;code&gt;docker-compose up&lt;/code&gt;, open &lt;a href=&#34;http://localhost:3000&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;http://localhost:3000&lt;/a&gt; in your browser to view the Grafana UI.&lt;/p&gt;
&lt;p&gt;The tutorials are designed to be followed in order and generally build on each other. Each example explains what it does and how it works. They are designed to be run locally, so you can follow along and experiment with them yourself.&lt;/p&gt;
&lt;p&gt;The Recommended Reading sections in each tutorial provide a list of documentation topics. To help you understand the concepts used in the example, read the recommended topics in the order given.&lt;/p&gt;
]]></content><description>&lt;h1 id="get-started">Get started&lt;/h1>
&lt;p>This set of tutorials contains a collection of examples that build on each other to demonstrate how to configure and use &lt;a href="/docs/agent/latest/flow/">Grafana Agent Flow&lt;/a>. It assumes you have a basic understanding of what Grafana Agent is and telemetry collection in general. It also assumes a base level of familiarity with Prometheus and PromQL, Loki and LogQL, and basic Grafana navigation. It assumes no knowledge of Grafana Agent Flow or River concepts.&lt;/p></description></item><item><title>First components and introducing the standard library</title><link>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/first-components-and-stdlib/</link><pubDate>Tue, 10 Mar 2026 03:19:46 +0000</pubDate><guid>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/first-components-and-stdlib/</guid><content><![CDATA[&lt;h1 id=&#34;first-components-and-the-standard-library&#34;&gt;First components and the standard library&lt;/h1&gt;
&lt;p&gt;This tutorial covers the basics of the River language and the standard library. It introduces a basic pipeline that collects metrics from the host and sends them to Prometheus.&lt;/p&gt;
&lt;h2 id=&#34;river-basics&#34;&gt;River basics&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/concepts/config-language/&#34;&gt;Configuration language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/concepts/configuration_language/&#34;&gt;Configuration language concepts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/grafana/river&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;River&lt;/a&gt; is an HCL-inspired configuration language used to configure Grafana Agent Flow. A River file is comprised of three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Attributes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;key = value&lt;/code&gt; pairs used to configure individual settings.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;url = &amp;#34;http://localhost:9090&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Expressions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Expressions are used to compute values. They can be constant values (for example, &lt;code&gt;&amp;quot;localhost:9090&amp;quot;&lt;/code&gt;), or they can be more complex (for example, referencing a component&amp;rsquo;s export: &lt;code&gt;prometheus.exporter.unix.targets&lt;/code&gt;. They can also be a mathematical expression: &lt;code&gt;(1 &#43; 2) * 3&lt;/code&gt;, or a standard library function call: &lt;code&gt;env(&amp;quot;HOME&amp;quot;)&lt;/code&gt;). We will use more expressions as we go along the examples. If you are curious, you can find a list of available standard library functions in the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/stdlib/&#34;&gt;Standard library documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Blocks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Blocks are used to configure components with groups of attributes or nested blocks. The following example block can be used to configure the logging output of Grafana Agent Flow:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;logging {
    level  = &amp;#34;debug&amp;#34;
    format = &amp;#34;json&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The default log level is &lt;code&gt;info&lt;/code&gt; and the default log format is &lt;code&gt;logfmt&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Try pasting this into &lt;code&gt;config.river&lt;/code&gt; and running &lt;code&gt;/path/to/agent run config.river&lt;/code&gt; to see what happens.&lt;/p&gt;
&lt;p&gt;Congratulations, you&amp;rsquo;ve just written your first River file! You&amp;rsquo;ve also just written your first Grafana Agent Flow configuration file. This configuration won&amp;rsquo;t do anything, so let&amp;rsquo;s add some components to it.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Comments in River are prefixed with &lt;code&gt;//&lt;/code&gt; and are single-line only. For example: &lt;code&gt;// This is a comment&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;components&#34;&gt;Components&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/concepts/components/&#34;&gt;Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/concepts/config-language/components/&#34;&gt;Components configuration language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/concepts/component_controller/&#34;&gt;Component controller&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Components are the building blocks of a Grafana Agent Flow configuration. They are configured and linked to create pipelines that collect, process, and output your telemetry data. Components are configured with &lt;code&gt;Arguments&lt;/code&gt; and have &lt;code&gt;Exports&lt;/code&gt; that may be referenced by other components.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at a simple example pipeline:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;local.file &amp;#34;example&amp;#34; {
    path = env(&amp;#34;HOME&amp;#34;) &amp;#43; &amp;#34;file.txt&amp;#34;
}

prometheus.remote_write &amp;#34;local_prom&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:9090/api/v1/write&amp;#34;

        basic_auth {
            username = &amp;#34;admin&amp;#34;
            password = local.file.example.content
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;A list of all available components can be found in the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/&#34;&gt;Component reference&lt;/a&gt;. Each component has a link to its documentation, which contains a description of what the component does, its arguments, its exports, and examples.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;This pipeline has two components: &lt;code&gt;local.file&lt;/code&gt; and &lt;code&gt;prometheus.remote_write&lt;/code&gt;. The &lt;code&gt;local.file&lt;/code&gt; component is configured with a single argument, &lt;code&gt;path&lt;/code&gt;, which is set by calling the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/stdlib/env/&#34;&gt;env&lt;/a&gt; standard library function to retrieve the value of the &lt;code&gt;HOME&lt;/code&gt; environment variable and concatenating it with the string &lt;code&gt;&amp;quot;file.txt&amp;quot;&lt;/code&gt;. The &lt;code&gt;local.file&lt;/code&gt; component has a single export, &lt;code&gt;content&lt;/code&gt;, which contains the contents of the file.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;prometheus.remote_write&lt;/code&gt; component is configured with an &lt;code&gt;endpoint&lt;/code&gt; block, containing the &lt;code&gt;url&lt;/code&gt; attribute and a &lt;code&gt;basic_auth&lt;/code&gt; block. The &lt;code&gt;url&lt;/code&gt; attribute is set to the URL of the Prometheus remote write endpoint. The &lt;code&gt;basic_auth&lt;/code&gt; block contains the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; attributes, which are set to the string &lt;code&gt;&amp;quot;admin&amp;quot;&lt;/code&gt; and the &lt;code&gt;content&lt;/code&gt; export of the &lt;code&gt;local.file&lt;/code&gt; component, respectively. The &lt;code&gt;content&lt;/code&gt; export is referenced by using the syntax &lt;code&gt;local.file.example.content&lt;/code&gt;, where &lt;code&gt;local.file.example&lt;/code&gt; is the fully qualified name of the component (the component&amp;rsquo;s type &#43; its label) and &lt;code&gt;content&lt;/code&gt; is the name of the export.&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
&lt;img src=&#34;/media/docs/agent/diagram-flow-by-example-basic-0.svg&#34; alt=&#34;Flow of example pipeline with local.file and prometheus.remote_write components&#34; width=&#34;200&#34; /&gt;
&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The &lt;code&gt;local.file&lt;/code&gt; component&amp;rsquo;s label is set to &lt;code&gt;&amp;quot;example&amp;quot;&lt;/code&gt;, so the fully qualified name of the component is &lt;code&gt;local.file.example&lt;/code&gt;. The &lt;code&gt;prometheus.remote_write&lt;/code&gt; component&amp;rsquo;s label is set to &lt;code&gt;&amp;quot;local_prom&amp;quot;&lt;/code&gt;, so the fully qualified name of the component is &lt;code&gt;prometheus.remote_write.local_prom&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;This example pipeline still doesn&amp;rsquo;t do anything, so let&amp;rsquo;s add some more components to it.&lt;/p&gt;
&lt;h2 id=&#34;shipping-your-first-metrics&#34;&gt;Shipping your first metrics&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/prometheus.exporter.unix/&#34;&gt;prometheus.exporter.unix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/prometheus.scrape/&#34;&gt;prometheus.scrape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/prometheus.remote_write/&#34;&gt;prometheus.remote_write&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Make a simple pipeline with a &lt;code&gt;prometheus.exporter.unix&lt;/code&gt; component, a &lt;code&gt;prometheus.scrape&lt;/code&gt; component to scrape it, and a &lt;code&gt;prometheus.remote_write&lt;/code&gt; component to send the scraped metrics to Prometheus.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;prometheus.exporter.unix &amp;#34;localhost&amp;#34; {
    // This component exposes a lot of metrics by default, so we will keep all of the default arguments.
}

prometheus.scrape &amp;#34;default&amp;#34; {
    // Setting the scrape interval lower to make it faster to be able to see the metrics
    scrape_interval = &amp;#34;10s&amp;#34;

    targets    = prometheus.exporter.unix.localhost.targets
    forward_to = [
        prometheus.remote_write.local_prom.receiver,
    ]
}

prometheus.remote_write &amp;#34;local_prom&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:9090/api/v1/write&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Run Grafana Agent Flow with:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;/path/to/agent run config.river&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Navigate to &lt;a href=&#34;http://localhost:3000/explore&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;http://localhost:3000/explore&lt;/a&gt; in your browser. After ~15-20 seconds, you should be able to see the metrics from the &lt;code&gt;prometheus.exporter.unix&lt;/code&gt; component! Try querying for &lt;code&gt;node_memory_Active_bytes&lt;/code&gt; to see the active memory of your host.&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
&lt;img src=&#34;/media/docs/agent/screenshot-flow-by-example-memory-usage.png&#34; alt=&#34;Screenshot of node_memory_Active_bytes query in Grafana&#34; /&gt;
&lt;/p&gt;
&lt;h2 id=&#34;visualizing-the-relationship-between-components&#34;&gt;Visualizing the relationship between components&lt;/h2&gt;
&lt;p&gt;The following diagram is an example pipeline:&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
&lt;img src=&#34;/media/docs/agent/diagram-flow-by-example-full-0.svg&#34; alt=&#34;Flow of example pipeline with a prometheus.scrape, prometheus.exporter.unix, and prometheus.remote_write components&#34; width=&#34;400&#34; /&gt;
&lt;/p&gt;
&lt;p&gt;The preceding configuration defines three components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheus.scrape&lt;/code&gt; - A component that scrapes metrics from components that export targets.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus.exporter.unix&lt;/code&gt; - A component that exports metrics from the host, built around &lt;a href=&#34;https://github.com/prometheus/node_exporter&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;node_exporter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus.remote_write&lt;/code&gt; - A component that sends metrics to a Prometheus remote-write compatible endpoint.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;prometheus.scrape&lt;/code&gt; component references the &lt;code&gt;prometheus.exporter.unix&lt;/code&gt; component&amp;rsquo;s targets export, which is a list of scrape targets. The &lt;code&gt;prometheus.scrape&lt;/code&gt; component then forwards the scraped metrics to the &lt;code&gt;prometheus.remote_write&lt;/code&gt; component.&lt;/p&gt;
&lt;p&gt;One rule is that components can&amp;rsquo;t form a cycle. This means that a component can&amp;rsquo;t reference itself directly or indirectly. This is to prevent infinite loops from forming in the pipeline.&lt;/p&gt;
&lt;h2 id=&#34;exercise-for-the-reader&#34;&gt;Exercise for the reader&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended Reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/prometheus.exporter.redis/&#34;&gt;prometheus.exporter.redis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s start a container running Redis and configure Grafana Agent Flow to scrape metrics from it.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;docker container run -d --name flow-redis -p 6379:6379 --rm redis&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Try modifying the pipeline to scrape metrics from the Redis exporter. You can refer to the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/prometheus.exporter.redis/&#34;&gt;prometheus.exporter.redis&lt;/a&gt; component documentation for more information on how to configure it.&lt;/p&gt;
&lt;p&gt;To give a visual hint, you want to create a pipeline that looks like this:&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;
&lt;img src=&#34;/media/docs/agent/diagram-flow-by-example-exercise-0.svg&#34; alt=&#34;Flow of exercise pipeline, with a scrape, unix_exporter, redis_exporter, and remote_write component&#34; width=&#34;600&#34; /&gt;
&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;You may find the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/stdlib/concat/&#34;&gt;concat&lt;/a&gt; standard library function useful.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;You can run Grafana Agent Flow with the new configuration file by running:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;/path/to/agent run config.river&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Navigate to &lt;a href=&#34;http://localhost:3000/explore&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;http://localhost:3000/explore&lt;/a&gt; in your browser. After the first scrape, you should be able to query for &lt;code&gt;redis&lt;/code&gt; metrics as well as &lt;code&gt;node&lt;/code&gt; metrics.&lt;/p&gt;
&lt;p&gt;To shut down the Redis container, run:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;docker container stop flow-redis&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you get stuck, you can always view a solution here:
&lt;div class=&#34;collapse&#34; x-data=&#34;app_collapse()&#34;&gt;
  &lt;button class=&#34;collapse-trigger&#34; @click=&#34;toggle()&#34;&gt;
    &lt;span class=&#34;body-large&#34;&gt;Solution&lt;/span&gt;
    &lt;span class=&#34;collapse-trigger__icon&#34; :class=&#34;{ &#39;collapse-trigger__icon-open&#39; : open }&#34;&gt;
      
  &lt;svg width=&#34;27&#34; height=&#34;26&#34; viewBox=&#34;0 0 27 26&#34; fill=&#34;none&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;
&lt;path opacity=&#34;0.2&#34; d=&#34;M1.73047 12.8359C1.73047 19.4634 7.10305 24.8359 13.7305 24.8359C20.3579 24.8359 25.7305 19.4634 25.7305 12.8359C25.7305 6.20852 20.3579 0.835937 13.7305 0.835937C7.10305 0.835937 1.73047 6.20852 1.73047 12.8359Z&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M18.2344 12.8359L9.23438 12.8359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M13.7344 8.33594L13.7344 17.3359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;/svg&gt;


    &lt;/span&gt;
  &lt;/button&gt;
  &lt;div class=&#34;collapse-content&#34; x-ref=&#34;content&#34; hidden=&#34;until-found&#34;&gt;
    &lt;div class=&#34;collapse-content__inner&#34; x-ref=&#34;content-inner&#34;&gt;
&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;// Configure your first components, learn about the standard library, and learn how to run Grafana Agent

// prometheus.exporter.redis collects information about Redis and exposes
// targets for other components to use
prometheus.exporter.redis &amp;#34;local_redis&amp;#34; {
    redis_addr = &amp;#34;localhost:6379&amp;#34;
}

prometheus.exporter.unix &amp;#34;localhost&amp;#34; { }

// prometheus.scrape scrapes the targets that it is configured with and forwards
// the metrics to other components (typically prometheus.relabel or prometheus.remote_write)
prometheus.scrape &amp;#34;default&amp;#34; {
    // This is scraping too often for typical use-cases, but is easier for testing and demo-ing!
    scrape_interval = &amp;#34;10s&amp;#34;

    // Here, prometheus.exporter.redis.local_redis.targets refers to the &amp;#39;targets&amp;#39; export
    // of the prometheus.exporter.redis component with the label &amp;#34;local_redis&amp;#34;.
    //
    // If you have more than one set of targets that you would like to scrape, you can use
    // the &amp;#39;concat&amp;#39; function from the standard library to combine them.
    targets    = concat(prometheus.exporter.redis.local_redis.targets, prometheus.exporter.unix.localhost.targets)
    forward_to = [prometheus.remote_write.local_prom.receiver]
}

// prometheus.remote_write exports a &amp;#39;receiver&amp;#39;, which other components can forward
// metrics to and it will remote_write them to the configured endpoint(s)
prometheus.remote_write &amp;#34;local_prom&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:9090/api/v1/write&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;h2 id=&#34;finishing-up-and-next-steps&#34;&gt;Finishing up and next steps&lt;/h2&gt;
&lt;p&gt;You might have noticed that running Grafana Agent Flow with the configurations created a directory called &lt;code&gt;data-agent&lt;/code&gt; in the directory you ran Grafana Agent Flow from. This directory is where components can store data, such as the &lt;code&gt;prometheus.exporter.unix&lt;/code&gt; component storing its WAL (Write Ahead Log). If you look in the directory, do you notice anything interesting? The directory for each component is the fully qualified name.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d like to store the data elsewhere, you can specify a different directory by supplying the &lt;code&gt;--storage.path&lt;/code&gt; flag to Grafana Agent&amp;rsquo;s run command, for example, &lt;code&gt;/path/to/agent run config.river --storage.path /etc/grafana-agent&lt;/code&gt;. Generally, you can use a persistent directory for this, as some components may use the data stored in this directory to perform their function.&lt;/p&gt;
&lt;p&gt;In the next tutorial, you will look at how to configure Grafana Agent Flow to collect logs from a file and send them to Loki. You will also look at using different components to process metrics and logs before sending them.&lt;/p&gt;
]]></content><description>&lt;h1 id="first-components-and-the-standard-library">First components and the standard library&lt;/h1>
&lt;p>This tutorial covers the basics of the River language and the standard library. It introduces a basic pipeline that collects metrics from the host and sends them to Prometheus.&lt;/p></description></item><item><title>Logs and relabeling basics</title><link>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/logs-and-relabeling-basics/</link><pubDate>Tue, 10 Mar 2026 03:19:46 +0000</pubDate><guid>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/logs-and-relabeling-basics/</guid><content><![CDATA[&lt;h1 id=&#34;logs-and-relabeling-basics&#34;&gt;Logs and relabeling basics&lt;/h1&gt;
&lt;p&gt;This tutorial assumes you have completed the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/tutorials/flow-by-example/first-components-and-stdlib/&#34;&gt;First components and introducing the standard library&lt;/a&gt; tutorial, or are at least familiar with the concepts of components, attributes, and expressions and how to use them. You will cover some basic metric relabeling, followed by how to send logs to Loki.&lt;/p&gt;
&lt;h2 id=&#34;relabel-metrics&#34;&gt;Relabel metrics&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/prometheus.relabel/&#34;&gt;prometheus.relabel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before moving on to logs, let&amp;rsquo;s look at how we can use the &lt;code&gt;prometheus.relabel&lt;/code&gt; component to relabel metrics. The &lt;code&gt;prometheus.relabel&lt;/code&gt; component allows you to perform Prometheus relabeling on metrics and is similar to the &lt;code&gt;relabel_configs&lt;/code&gt; section of a Prometheus scrape config.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s add a &lt;code&gt;prometheus.relabel&lt;/code&gt; component to a basic pipeline and see how to add labels.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;prometheus.exporter.unix &amp;#34;localhost&amp;#34; { }

prometheus.scrape &amp;#34;default&amp;#34; {
    scrape_interval = &amp;#34;10s&amp;#34;

    targets    = prometheus.exporter.unix.localhost.targets
    forward_to = [
        prometheus.relabel.example.receiver,
    ]
}

prometheus.relabel &amp;#34;example&amp;#34; {
    forward_to = [
        prometheus.remote_write.local_prom.receiver,
    ]

    rule {
        action       = &amp;#34;replace&amp;#34;
        target_label = &amp;#34;os&amp;#34;
        replacement  = constants.os
    }
}

prometheus.remote_write &amp;#34;local_prom&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:9090/api/v1/write&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We have now created the following pipeline:&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/agent/diagram-flow-by-example-relabel-0.svg&#34;
  alt=&#34;Diagram of pipeline that scrapes prometheus.exporter.unix, relabels the metrics, and remote_writes them&#34;/&gt;&lt;/p&gt;
&lt;p&gt;This pipeline has a &lt;code&gt;prometheus.relabel&lt;/code&gt; component that has a single rule.
This rule has the &lt;code&gt;replace&lt;/code&gt; action, which will replace the value of the &lt;code&gt;os&lt;/code&gt; label with a special value: &lt;code&gt;constants.os&lt;/code&gt;.
This value is a special constant that is replaced with the OS of the host Grafana Agent is running on.
You can see the other available constants in the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/stdlib/constants/&#34;&gt;constants&lt;/a&gt; documentation.
This example has one rule block, but you can have as many as you want.
Each rule block is applied in order.&lt;/p&gt;
&lt;p&gt;If you run Grafana Agent and navigate to &lt;a href=&#34;http://localhost:3000/explore&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;localhost:3000/explore&lt;/a&gt;, you can see the &lt;code&gt;os&lt;/code&gt; label on the metrics. Try querying for &lt;code&gt;node_context_switches_total&lt;/code&gt; and look at the labels.&lt;/p&gt;
&lt;p&gt;Relabeling uses the same rules as Prometheus. You can always refer to the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/prometheus.relabel/#rule-block&#34;&gt;prometheus.relabel documentation&lt;/a&gt; for a full list of available options.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;You can forward multiple components to one &lt;code&gt;prometheus.relabel&lt;/code&gt; component. This allows you to apply the same relabeling rules to multiple pipelines.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;



&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;There is an issue commonly faced when relabeling and using labels that start with &lt;code&gt;__&lt;/code&gt; (double underscore). These labels are considered internal and are dropped before relabeling rules from a &lt;code&gt;prometheus.relabel&lt;/code&gt; component are applied. If you would like to keep or act on these kinds of labels, use a 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/discovery.relabel/&#34;&gt;discovery.relabel&lt;/a&gt; component.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;send-logs-to-loki&#34;&gt;Send logs to Loki&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/local.file_match/&#34;&gt;local.file_match&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.source.file/&#34;&gt;loki.source.file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.write/&#34;&gt;loki.write&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that you&amp;rsquo;re comfortable creating components and chaining them together, let&amp;rsquo;s collect some logs and send them to Loki. We will use the &lt;code&gt;local.file_match&lt;/code&gt; component to perform file discovery, the &lt;code&gt;loki.source.file&lt;/code&gt; to collect the logs, and the &lt;code&gt;loki.write&lt;/code&gt; component to send the logs to Loki.&lt;/p&gt;
&lt;p&gt;Before doing this, we need to ensure we have a log file to scrape. We will use the &lt;code&gt;echo&lt;/code&gt; command to create a file with some log content.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir -p /tmp/flow-logs
echo &amp;#34;This is a log line&amp;#34; &amp;gt; /tmp/flow-logs/log.log&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now that we have a log file, let&amp;rsquo;s create a pipeline to scrape it.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;local.file_match &amp;#34;tmplogs&amp;#34; {
    path_targets = [{&amp;#34;__path__&amp;#34; = &amp;#34;/tmp/flow-logs/*.log&amp;#34;}]
}

loki.source.file &amp;#34;local_files&amp;#34; {
    targets    = local.file_match.tmplogs.targets
    forward_to = [loki.write.local_loki.receiver]
}

loki.write &amp;#34;local_loki&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:3100/loki/api/v1/push&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The rough flow of this pipeline is:&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/agent/diagram-flow-by-example-logs-0.svg&#34;
  alt=&#34;Diagram of pipeline that collects logs from /tmp/flow-logs and writes them to a local Loki instance&#34;/&gt;&lt;/p&gt;
&lt;p&gt;If you navigate to &lt;a href=&#34;http://localhost:3000/explore&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;localhost:3000/explore&lt;/a&gt; and switch the Datasource to &lt;code&gt;Loki&lt;/code&gt;, you can query for &lt;code&gt;{filename=&amp;quot;/tmp/flow-logs/log.log&amp;quot;}&lt;/code&gt; and see the log line we created earlier. Try running the following command to add more logs to the file.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;#34;This is another log line!&amp;#34; &amp;gt;&amp;gt; /tmp/flow-logs/log.log&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you re-execute the query, you can see the new log lines.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/agent/screenshot-flow-by-example-log-lines.png&#34;
  alt=&#34;Grafana Explore view of example log lines&#34; width=&#34;2531&#34;
     height=&#34;905&#34;/&gt;&lt;/p&gt;
&lt;p&gt;If you are curious how Grafana Agent keeps track of where it is in a log file, you can look at &lt;code&gt;data-agent/loki.source.file.local_files/positions.yml&lt;/code&gt;.
If you delete this file, Grafana Agent starts reading from the beginning of the file again, which is why keeping the Grafana Agent&amp;rsquo;s data directory in a persistent location is desirable.&lt;/p&gt;
&lt;h2 id=&#34;exercise&#34;&gt;Exercise&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.relabel/&#34;&gt;loki.relabel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.process/&#34;&gt;loki.process&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;add-a-label-to-logs&#34;&gt;Add a Label to Logs&lt;/h3&gt;
&lt;p&gt;This exercise will have two parts, building on the previous example. Let&amp;rsquo;s start by adding an &lt;code&gt;os&lt;/code&gt; label (just like the Prometheus example) to all of the logs we collect.&lt;/p&gt;
&lt;p&gt;Modify the following snippet to add the label &lt;code&gt;os&lt;/code&gt; with the value of the &lt;code&gt;os&lt;/code&gt; constant.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;local.file_match &amp;#34;tmplogs&amp;#34; {
    path_targets = [{&amp;#34;__path__&amp;#34; = &amp;#34;/tmp/flow-logs/*.log&amp;#34;}]
}

loki.source.file &amp;#34;local_files&amp;#34; {
    targets    = local.file_match.tmplogs.targets
    forward_to = [loki.write.local_loki.receiver]
}

loki.write &amp;#34;local_loki&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:3100/loki/api/v1/push&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;You can use the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.relabel&#34;&gt;loki.relabel&lt;/a&gt; component to relabel and add labels, just like you can with the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/prometheus.relabel&#34;&gt;prometheus.relabel&lt;/a&gt; component.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Once you have your completed configuration, run Grafana Agent and execute the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;#39;level=info msg=&amp;#34;INFO: This is an info level log!&amp;#34;&amp;#39; &amp;gt;&amp;gt; /tmp/flow-logs/log.log
echo &amp;#39;level=warn msg=&amp;#34;WARN: This is a warn level log!&amp;#34;&amp;#39; &amp;gt;&amp;gt; /tmp/flow-logs/log.log
echo &amp;#39;level=debug msg=&amp;#34;DEBUG: This is a debug level log!&amp;#34;&amp;#39; &amp;gt;&amp;gt; /tmp/flow-logs/log.log&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Navigate to &lt;a href=&#34;http://localhost:3000/explore&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;localhost:3000/explore&lt;/a&gt; and switch the Datasource to &lt;code&gt;Loki&lt;/code&gt;. Try querying for &lt;code&gt;{filename=&amp;quot;/tmp/flow-logs/log.log&amp;quot;}&lt;/code&gt; and see if you can find the new label!&lt;/p&gt;
&lt;p&gt;Now that we have added new labels, we can also filter on them. Try querying for &lt;code&gt;{os!=&amp;quot;&amp;quot;}&lt;/code&gt;. You should only see the lines you added in the previous step.&lt;/p&gt;
&lt;div class=&#34;collapse&#34; x-data=&#34;app_collapse()&#34;&gt;
  &lt;button class=&#34;collapse-trigger&#34; @click=&#34;toggle()&#34;&gt;
    &lt;span class=&#34;body-large&#34;&gt;Solution&lt;/span&gt;
    &lt;span class=&#34;collapse-trigger__icon&#34; :class=&#34;{ &#39;collapse-trigger__icon-open&#39; : open }&#34;&gt;
      
  &lt;svg width=&#34;27&#34; height=&#34;26&#34; viewBox=&#34;0 0 27 26&#34; fill=&#34;none&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;
&lt;path opacity=&#34;0.2&#34; d=&#34;M1.73047 12.8359C1.73047 19.4634 7.10305 24.8359 13.7305 24.8359C20.3579 24.8359 25.7305 19.4634 25.7305 12.8359C25.7305 6.20852 20.3579 0.835937 13.7305 0.835937C7.10305 0.835937 1.73047 6.20852 1.73047 12.8359Z&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M18.2344 12.8359L9.23438 12.8359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M13.7344 8.33594L13.7344 17.3359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;/svg&gt;


    &lt;/span&gt;
  &lt;/button&gt;
  &lt;div class=&#34;collapse-content&#34; x-ref=&#34;content&#34; hidden=&#34;until-found&#34;&gt;
    &lt;div class=&#34;collapse-content__inner&#34; x-ref=&#34;content-inner&#34;&gt;
&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;// Let&amp;#39;s learn about relabeling and send logs to Loki!

local.file_match &amp;#34;tmplogs&amp;#34; {
    path_targets = [{&amp;#34;__path__&amp;#34; = &amp;#34;/tmp/flow-logs/*.log&amp;#34;}]
}

loki.source.file &amp;#34;local_files&amp;#34; {
    targets    = local.file_match.tmplogs.targets
    forward_to = [loki.relabel.add_static_label.receiver]
}

loki.relabel &amp;#34;add_static_label&amp;#34; {
    forward_to = [loki.write.local_loki.receiver]

    rule {
        target_label = &amp;#34;os&amp;#34;
        replacement  = constants.os
    }
}

loki.write &amp;#34;local_loki&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:3100/loki/api/v1/push&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&#34;extract-and-add-a-label-from-logs&#34;&gt;Extract and add a Label from Logs&lt;/h3&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;This exercise is more challenging than the previous one. If you are having trouble, skip it and move to the next section, which will cover some of the concepts used here. You can always come back to this exercise later.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;This exercise will build on the previous one, though it&amp;rsquo;s more involved.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say we want to extract the &lt;code&gt;level&lt;/code&gt; from the logs and add it as a label. As a starting point, look at 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.process/&#34;&gt;loki.process&lt;/a&gt;.
This component allows you to perform processing on logs, including extracting values from log contents.&lt;/p&gt;
&lt;p&gt;Try modifying your configuration from the previous section to extract the &lt;code&gt;level&lt;/code&gt; from the logs and add it as a label.
If needed, you can find a solution to the previous exercise at the end of the &lt;a href=&#34;#add-a-label-to-logs&#34;&gt;previous section&lt;/a&gt;.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The &lt;code&gt;stage.logfmt&lt;/code&gt; and &lt;code&gt;stage.labels&lt;/code&gt; blocks for &lt;code&gt;loki.process&lt;/code&gt; may be helpful.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Once you have your completed config, run Grafana Agent and execute the following:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;#39;level=info msg=&amp;#34;INFO: This is an info level log!&amp;#34;&amp;#39; &amp;gt;&amp;gt; /tmp/flow-logs/log.log
echo &amp;#39;level=warn msg=&amp;#34;WARN: This is a warn level log!&amp;#34;&amp;#39; &amp;gt;&amp;gt; /tmp/flow-logs/log.log
echo &amp;#39;level=debug msg=&amp;#34;DEBUG: This is a debug level log!&amp;#34;&amp;#39; &amp;gt;&amp;gt; /tmp/flow-logs/log.log&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Navigate to &lt;a href=&#34;http://localhost:3000/explore&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;localhost:3000/explore&lt;/a&gt; and switch the Datasource to &lt;code&gt;Loki&lt;/code&gt;. Try querying for &lt;code&gt;{level!=&amp;quot;&amp;quot;}&lt;/code&gt; to see the new labels in action.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/agent/screenshot-flow-by-example-log-line-levels.png&#34;
  alt=&#34;Grafana Explore view of example log lines, now with the extracted &amp;rsquo;level&amp;rsquo; label&#34; width=&#34;2528&#34;
     height=&#34;902&#34;/&gt;&lt;/p&gt;
&lt;div class=&#34;collapse&#34; x-data=&#34;app_collapse()&#34;&gt;
  &lt;button class=&#34;collapse-trigger&#34; @click=&#34;toggle()&#34;&gt;
    &lt;span class=&#34;body-large&#34;&gt;Solution&lt;/span&gt;
    &lt;span class=&#34;collapse-trigger__icon&#34; :class=&#34;{ &#39;collapse-trigger__icon-open&#39; : open }&#34;&gt;
      
  &lt;svg width=&#34;27&#34; height=&#34;26&#34; viewBox=&#34;0 0 27 26&#34; fill=&#34;none&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;
&lt;path opacity=&#34;0.2&#34; d=&#34;M1.73047 12.8359C1.73047 19.4634 7.10305 24.8359 13.7305 24.8359C20.3579 24.8359 25.7305 19.4634 25.7305 12.8359C25.7305 6.20852 20.3579 0.835937 13.7305 0.835937C7.10305 0.835937 1.73047 6.20852 1.73047 12.8359Z&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M18.2344 12.8359L9.23438 12.8359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M13.7344 8.33594L13.7344 17.3359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;/svg&gt;


    &lt;/span&gt;
  &lt;/button&gt;
  &lt;div class=&#34;collapse-content&#34; x-ref=&#34;content&#34; hidden=&#34;until-found&#34;&gt;
    &lt;div class=&#34;collapse-content__inner&#34; x-ref=&#34;content-inner&#34;&gt;
&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;// Let&amp;#39;s learn about relabeling and send logs to Loki!

local.file_match &amp;#34;tmplogs&amp;#34; {
    path_targets = [{&amp;#34;__path__&amp;#34; = &amp;#34;/tmp/flow-logs/*.log&amp;#34;}]
}

loki.source.file &amp;#34;local_files&amp;#34; {
    targets    = local.file_match.tmplogs.targets
    forward_to = [loki.process.add_new_label.receiver]
}

loki.process &amp;#34;add_new_label&amp;#34; {
    // Extract the value of &amp;#34;level&amp;#34; from the log line and add it to the extracted map as &amp;#34;extracted_level&amp;#34;
    // You could also use &amp;#34;level&amp;#34; = &amp;#34;&amp;#34;, which would extract the value of &amp;#34;level&amp;#34; and add it to the extracted map as &amp;#34;level&amp;#34;
    // but to make it explicit for this example, we will use a different name.
    //
    // The extracted map will be covered in more detail in the next section.
    stage.logfmt {
        mapping = {
            &amp;#34;extracted_level&amp;#34; = &amp;#34;level&amp;#34;,
        }
    }

    // Add the value of &amp;#34;extracted_level&amp;#34; from the extracted map as a &amp;#34;level&amp;#34; label
    stage.labels {
        values = {
            &amp;#34;level&amp;#34; = &amp;#34;extracted_level&amp;#34;,
        }
    }

    forward_to = [loki.relabel.add_static_label.receiver]
}

loki.relabel &amp;#34;add_static_label&amp;#34; {
    forward_to = [loki.write.local_loki.receiver]

    rule {
        target_label = &amp;#34;os&amp;#34;
        replacement  = constants.os
    }
}

loki.write &amp;#34;local_loki&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:3100/loki/api/v1/push&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&#34;finishing-up-and-next-steps&#34;&gt;Finishing up and next steps&lt;/h2&gt;
&lt;p&gt;You have learned the concepts of components, attributes, and expressions. You have also seen how to use some standard library components to collect metrics and logs. In the next tutorial, you will learn more about how to use the &lt;code&gt;loki.process&lt;/code&gt; component to extract values from logs and use them.&lt;/p&gt;
]]></content><description>&lt;h1 id="logs-and-relabeling-basics">Logs and relabeling basics&lt;/h1>
&lt;p>This tutorial assumes you have completed the
&lt;a href="/docs/agent/v0.44/flow/tutorials/flow-by-example/first-components-and-stdlib/">First components and introducing the standard library&lt;/a> tutorial, or are at least familiar with the concepts of components, attributes, and expressions and how to use them. You will cover some basic metric relabeling, followed by how to send logs to Loki.&lt;/p></description></item><item><title>Processing Logs</title><link>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/processing-logs/</link><pubDate>Tue, 10 Mar 2026 03:19:46 +0000</pubDate><guid>https://grafana.com/docs/agent/v0.44/flow/tutorials/flow-by-example/processing-logs/</guid><content><![CDATA[&lt;h1 id=&#34;processing-logs&#34;&gt;Processing Logs&lt;/h1&gt;
&lt;p&gt;This tutorial assumes you are familiar with setting up and connecting components.
It covers using &lt;code&gt;loki.source.api&lt;/code&gt; to receive logs over HTTP, processing and filtering them, and sending them to Loki.&lt;/p&gt;
&lt;h2 id=&#34;receive-logs-over-http-and-process&#34;&gt;Receive logs over HTTP and Process&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optional: 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.source.api/&#34;&gt;loki.source.api&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;loki.source.api&lt;/code&gt; component can receive logs over HTTP.
It can be useful for receiving logs from other Grafana Agents or collectors, or directly from applications that can send logs over HTTP, and then processing them centrally.&lt;/p&gt;
&lt;p&gt;Your pipeline is going to look like this:&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/agent/diagram-flow-by-example-logs-pipeline.svg&#34;
  alt=&#34;Loki Source API Pipeline&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start by setting up the &lt;code&gt;loki.source.api&lt;/code&gt; component:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;loki.source.api &amp;#34;listener&amp;#34; {
    http {
        listen_address = &amp;#34;127.0.0.1&amp;#34;
        listen_port    = 9999
    }

    labels = { &amp;#34;source&amp;#34;: &amp;#34;api&amp;#34; }

    forward_to = [loki.process.process_logs.receiver]
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is a simple configuration.
You are configuring the &lt;code&gt;loki.source.api&lt;/code&gt; component to listen on &lt;code&gt;127.0.0.1:9999&lt;/code&gt; and attach a &lt;code&gt;source=&amp;quot;api&amp;quot;&lt;/code&gt; label to the received log entries, which are then forwarded to the &lt;code&gt;loki.process.process_logs&lt;/code&gt; component&amp;rsquo;s exported receiver.
Next, you can configure the &lt;code&gt;loki.process&lt;/code&gt; and &lt;code&gt;loki.write&lt;/code&gt; components.&lt;/p&gt;
&lt;h2 id=&#34;process-and-write-logs&#34;&gt;Process and Write Logs&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Recommended reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.process/#stagedrop-block&#34;&gt;loki.process#stage.drop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.process/#stagejson-block&#34;&gt;loki.process#stage.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.process/#stagelabels-block&#34;&gt;loki.process#stage.labels&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;// Let&amp;#39;s send and process more logs!

loki.source.api &amp;#34;listener&amp;#34; {
    http {
        listen_address = &amp;#34;127.0.0.1&amp;#34;
        listen_port    = 9999
    }

    labels = { &amp;#34;source&amp;#34; = &amp;#34;api&amp;#34; }

    forward_to = [loki.process.process_logs.receiver]
}

loki.process &amp;#34;process_logs&amp;#34; {

    // Stage 1
    stage.json {
        expressions = {
            log = &amp;#34;&amp;#34;,
            ts  = &amp;#34;timestamp&amp;#34;,
        }
    }

    // Stage 2
    stage.timestamp {
        source = &amp;#34;ts&amp;#34;
        format = &amp;#34;RFC3339&amp;#34;
    }

    // Stage 3
    stage.json {
        source = &amp;#34;log&amp;#34;

        expressions = {
            is_secret = &amp;#34;&amp;#34;,
            level     = &amp;#34;&amp;#34;,
            log_line  = &amp;#34;message&amp;#34;,
        }
    }

    // Stage 4
    stage.drop {
        source = &amp;#34;is_secret&amp;#34;
        value  = &amp;#34;true&amp;#34;
    }

    // Stage 5
    stage.labels {
        values = {
            level = &amp;#34;&amp;#34;,
        }
    }

    // Stage 6
    stage.output {
        source = &amp;#34;log_line&amp;#34;
    }

    // This stage adds static values to the labels on the log line
    stage.static_labels {
        values = {
            source = &amp;#34;demo-api&amp;#34;,
        }
    }

    forward_to = [loki.write.local_loki.receiver]
}

loki.write &amp;#34;local_loki&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:3100/loki/api/v1/push&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You can skip to the next section if you successfully completed the previous section&amp;rsquo;s exercises.
If not, or if you were unsure how things worked, let&amp;rsquo;s break down what is happening in the &lt;code&gt;loki.process&lt;/code&gt; component.&lt;/p&gt;
&lt;p&gt;Many of the &lt;code&gt;stage.*&lt;/code&gt; blocks in &lt;code&gt;loki.process&lt;/code&gt; act on reading or writing a shared map of values extracted from the logs.
You can think of this extracted map as a hashmap or table that each stage has access to, and it is referred to as the &amp;ldquo;extracted map&amp;rdquo; from here on.
In subsequent stages, you can use the extracted map to filter logs, add or remove labels, or even modify the log line.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;&lt;code&gt;stage.*&lt;/code&gt; blocks are executed in the order they appear in the component, top down.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s use an example log line to illustrate this, then go stage by stage, showing the contents of the extracted map. Here is our example log line:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JSON&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;#34;log&amp;#34;: {
        &amp;#34;is_secret&amp;#34;: &amp;#34;true&amp;#34;,
        &amp;#34;level&amp;#34;: &amp;#34;info&amp;#34;,
        &amp;#34;message&amp;#34;: &amp;#34;This is a secret message!&amp;#34;,
    },
    &amp;#34;timestamp&amp;#34;: &amp;#34;2023-11-16T06:01:50Z&amp;#34;,
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;stage-1&#34;&gt;Stage 1&lt;/h3&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;stage.json {
    expressions = {
        log = &amp;#34;&amp;#34;,
        ts  = &amp;#34;timestamp&amp;#34;,
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This stage parses the log line as JSON, extracts two values from it, &lt;code&gt;log&lt;/code&gt; and &lt;code&gt;timestamp&lt;/code&gt;, and puts them into the extracted map with keys &lt;code&gt;log&lt;/code&gt; and &lt;code&gt;ts&lt;/code&gt;, respectively.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Supplying an empty string is shorthand for using the same key as in the input log line (so &lt;code&gt;log = &amp;quot;&amp;quot;&lt;/code&gt; is the same as &lt;code&gt;log = &amp;quot;log&amp;quot;&lt;/code&gt;). The &lt;em&gt;keys&lt;/em&gt; of the &lt;code&gt;expressions&lt;/code&gt; object end up as the keys in the extracted map, and the &lt;em&gt;values&lt;/em&gt; are used as keys to look up in the parsed log line.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;If this were Python, it would be roughly equivalent to:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Python&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;extracted_map = {}
log_line      = {&amp;#34;log&amp;#34;: {&amp;#34;is_secret&amp;#34;: &amp;#34;true&amp;#34;, &amp;#34;level&amp;#34;: &amp;#34;info&amp;#34;, &amp;#34;message&amp;#34;: &amp;#34;This is a secret message!&amp;#34;}, &amp;#34;timestamp&amp;#34;: &amp;#34;2023-11-16T06:01:50Z&amp;#34;}

extracted_map[&amp;#34;log&amp;#34;] = log_line[&amp;#34;log&amp;#34;]
extracted_map[&amp;#34;ts&amp;#34;]  = log_line[&amp;#34;timestamp&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Extracted map &lt;em&gt;before&lt;/em&gt; performing this stage:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JSON&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;{}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Extracted map &lt;em&gt;after&lt;/em&gt; performing this stage:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JSON&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;#34;log&amp;#34;: {
        &amp;#34;is_secret&amp;#34;: &amp;#34;true&amp;#34;,
        &amp;#34;level&amp;#34;: &amp;#34;info&amp;#34;,
        &amp;#34;message&amp;#34;: &amp;#34;This is a secret message!&amp;#34;,
    },
    &amp;#34;ts&amp;#34;: &amp;#34;2023-11-16T06:01:50Z&amp;#34;,
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;stage-2&#34;&gt;Stage 2&lt;/h3&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;stage.timestamp {
    source = &amp;#34;ts&amp;#34;
    format = &amp;#34;RFC3339&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This stage acts on the &lt;code&gt;ts&lt;/code&gt; value in the map you extracted in the previous stage.
The value of &lt;code&gt;ts&lt;/code&gt; is parsed in the format of &lt;code&gt;RFC3339&lt;/code&gt; and added as the timestamp to be ingested by Loki.
This is useful if you want to use the timestamp present in the log itself, rather than the time the log is ingested.
This stage does not modify the extracted map.&lt;/p&gt;
&lt;h3 id=&#34;stage-3&#34;&gt;Stage 3&lt;/h3&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;stage.json {
    source = &amp;#34;log&amp;#34;

    expressions = {
        is_secret = &amp;#34;&amp;#34;,
        level     = &amp;#34;&amp;#34;,
        log_line  = &amp;#34;message&amp;#34;,
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This stage acts on the &lt;code&gt;log&lt;/code&gt; value in the extracted map, which is a value that you extracted in the previous stage.
This value is also a JSON object, so you can extract values from it as well.
This stage extracts three values from the &lt;code&gt;log&lt;/code&gt; value, &lt;code&gt;is_secret&lt;/code&gt;, &lt;code&gt;level&lt;/code&gt;, and &lt;code&gt;log_line&lt;/code&gt;, and puts them into the extracted map with keys &lt;code&gt;is_secret&lt;/code&gt;, &lt;code&gt;level&lt;/code&gt;, and &lt;code&gt;log_line&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If this were Python, it would be roughly equivalent to:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Python&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;extracted_map = {
    &amp;#34;log&amp;#34;: {
        &amp;#34;is_secret&amp;#34;: &amp;#34;true&amp;#34;,
        &amp;#34;level&amp;#34;: &amp;#34;info&amp;#34;,
        &amp;#34;message&amp;#34;: &amp;#34;This is a secret message!&amp;#34;,
    },
    &amp;#34;ts&amp;#34;: &amp;#34;2023-11-16T06:01:50Z&amp;#34;,
}

source = extracted_map[&amp;#34;log&amp;#34;]

extracted_map[&amp;#34;is_secret&amp;#34;] = source[&amp;#34;is_secret&amp;#34;]
extracted_map[&amp;#34;level&amp;#34;]     = source[&amp;#34;level&amp;#34;]
extracted_map[&amp;#34;log_line&amp;#34;]  = source[&amp;#34;message&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Extracted map &lt;em&gt;before&lt;/em&gt; performing this stage:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JSON&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;#34;log&amp;#34;: {
        &amp;#34;is_secret&amp;#34;: &amp;#34;true&amp;#34;,
        &amp;#34;level&amp;#34;: &amp;#34;info&amp;#34;,
        &amp;#34;message&amp;#34;: &amp;#34;This is a secret message!&amp;#34;,
    },
    &amp;#34;ts&amp;#34;: &amp;#34;2023-11-16T06:01:50Z&amp;#34;,
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Extracted map &lt;em&gt;after&lt;/em&gt; performing this stage:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JSON&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;#34;log&amp;#34;: {
        &amp;#34;is_secret&amp;#34;: &amp;#34;true&amp;#34;,
        &amp;#34;level&amp;#34;: &amp;#34;info&amp;#34;,
        &amp;#34;message&amp;#34;: &amp;#34;This is a secret message!&amp;#34;,
    },
    &amp;#34;ts&amp;#34;: &amp;#34;2023-11-16T06:01:50Z&amp;#34;,
    &amp;#34;is_secret&amp;#34;: &amp;#34;true&amp;#34;,
    &amp;#34;level&amp;#34;: &amp;#34;info&amp;#34;,
    &amp;#34;log_line&amp;#34;: &amp;#34;This is a secret message!&amp;#34;,
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;stage-4&#34;&gt;Stage 4&lt;/h3&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;stage.drop {
    source = &amp;#34;is_secret&amp;#34;
    value  = &amp;#34;true&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This stage acts on the &lt;code&gt;is_secret&lt;/code&gt; value in the extracted map, which is a value that you extracted in the previous stage.
This stage drops the log line if the value of &lt;code&gt;is_secret&lt;/code&gt; is &lt;code&gt;&amp;quot;true&amp;quot;&lt;/code&gt; and does not modify the extracted map.
There are many other ways to filter logs, but this is a simple example.
Refer to the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.process/#stagedrop-block&#34;&gt;loki.process#stage.drop&lt;/a&gt; documentation for more information.&lt;/p&gt;
&lt;h3 id=&#34;stage-5&#34;&gt;Stage 5&lt;/h3&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;stage.labels {
    values = {
        level = &amp;#34;&amp;#34;,
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This stage adds a label to the log using the same shorthand as above (so this is equivalent to using &lt;code&gt;values = { level = &amp;quot;level&amp;quot; }&lt;/code&gt;).
This stage adds a label with key &lt;code&gt;level&lt;/code&gt; and the value of &lt;code&gt;level&lt;/code&gt; in the extracted map to the log (&lt;code&gt;&amp;quot;info&amp;quot;&lt;/code&gt; from our example log line).
This stage does not modify the extracted map.&lt;/p&gt;
&lt;h3 id=&#34;stage-6&#34;&gt;Stage 6&lt;/h3&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;stage.output {
    source = &amp;#34;log_line&amp;#34;
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This stage uses the &lt;code&gt;log_line&lt;/code&gt; value in the extracted map to set the actual log line that is forwarded to Loki.
Rather than sending the entire JSON blob to Loki, you are only sending &lt;code&gt;original_log_line[&amp;quot;log&amp;quot;][&amp;quot;message&amp;quot;]&lt;/code&gt;, along with some labels that you attached.&lt;/p&gt;
&lt;p&gt;This stage does not modify the extracted map.&lt;/p&gt;
&lt;h2 id=&#34;putting-it-all-together&#34;&gt;Putting it all together&lt;/h2&gt;
&lt;p&gt;Now that you have all of the pieces, let&amp;rsquo;s run the Grafana Agent and send some logs to it.
Modify &lt;code&gt;config.river&lt;/code&gt; with the config from the previous example and start the Grafana Agent with:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;/path/to/agent run config.river&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To get the current time in &lt;code&gt;RFC3339&lt;/code&gt; format, you can run:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;date -u &amp;#43;&amp;#34;%Y-%m-%dT%H:%M:%SZ&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Try executing the following, replacing the &lt;code&gt;&amp;quot;timestamp&amp;quot;&lt;/code&gt; value:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;curl localhost:9999/loki/api/v1/raw -XPOST -H &amp;#34;Content-Type: application/json&amp;#34; -d &amp;#39;{&amp;#34;log&amp;#34;: {&amp;#34;is_secret&amp;#34;: &amp;#34;false&amp;#34;, &amp;#34;level&amp;#34;: &amp;#34;debug&amp;#34;, &amp;#34;message&amp;#34;: &amp;#34;This is a debug message!&amp;#34;}, &amp;#34;timestamp&amp;#34;: &amp;lt;YOUR TIMESTAMP HERE&amp;gt;}&amp;#39;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now that you have sent some logs, let&amp;rsquo;s see how they look in Grafana.
Navigate to &lt;a href=&#34;http://localhost:3000/explore&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;localhost:3000/explore&lt;/a&gt; and switch the Datasource to &lt;code&gt;Loki&lt;/code&gt;.
Try querying for &lt;code&gt;{source=&amp;quot;demo-api&amp;quot;}&lt;/code&gt; and see if you can find the logs you sent.&lt;/p&gt;
&lt;p&gt;Try playing around with the values of &lt;code&gt;&amp;quot;level&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;message&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;timestamp&amp;quot;&lt;/code&gt;, and &lt;code&gt;&amp;quot;is_secret&amp;quot;&lt;/code&gt; and see how the logs change.
You can also try adding more stages to the &lt;code&gt;loki.process&lt;/code&gt; component to extract more values from the logs, or add more labels.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/agent/screenshot-flow-by-example-processed-log-lines.png&#34;
  alt=&#34;Example Loki Logs&#34; width=&#34;2529&#34;
     height=&#34;901&#34;/&gt;&lt;/p&gt;
&lt;h2 id=&#34;exercise&#34;&gt;Exercise&lt;/h2&gt;
&lt;p&gt;Since you are already using Docker and Docker exports logs, let&amp;rsquo;s get those logs into Loki.
You can refer to the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/discovery.docker/&#34;&gt;discovery.docker&lt;/a&gt; and 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/loki.source.docker/&#34;&gt;loki.source.docker&lt;/a&gt; documentation for more information.&lt;/p&gt;
&lt;p&gt;To ensure proper timestamps and other labels, make sure you use a &lt;code&gt;loki.process&lt;/code&gt; component to process the logs before sending them to Loki.&lt;/p&gt;
&lt;p&gt;Although you have not used it before, let&amp;rsquo;s use a &lt;code&gt;discovery.relabel&lt;/code&gt; component to attach the container name as a label to the logs.
You can refer to the 
    &lt;a href=&#34;/docs/agent/v0.44/flow/reference/components/discovery.relabel/&#34;&gt;discovery.relabel&lt;/a&gt; documentation for more information.
The &lt;code&gt;discovery.relabel&lt;/code&gt; component is very similar to the &lt;code&gt;prometheus.relabel&lt;/code&gt; component, but is used to relabel discovered targets rather than metrics.&lt;/p&gt;
&lt;div class=&#34;collapse&#34; x-data=&#34;app_collapse()&#34;&gt;
  &lt;button class=&#34;collapse-trigger&#34; @click=&#34;toggle()&#34;&gt;
    &lt;span class=&#34;body-large&#34;&gt;Solution&lt;/span&gt;
    &lt;span class=&#34;collapse-trigger__icon&#34; :class=&#34;{ &#39;collapse-trigger__icon-open&#39; : open }&#34;&gt;
      
  &lt;svg width=&#34;27&#34; height=&#34;26&#34; viewBox=&#34;0 0 27 26&#34; fill=&#34;none&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;
&lt;path opacity=&#34;0.2&#34; d=&#34;M1.73047 12.8359C1.73047 19.4634 7.10305 24.8359 13.7305 24.8359C20.3579 24.8359 25.7305 19.4634 25.7305 12.8359C25.7305 6.20852 20.3579 0.835937 13.7305 0.835937C7.10305 0.835937 1.73047 6.20852 1.73047 12.8359Z&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M18.2344 12.8359L9.23438 12.8359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M13.7344 8.33594L13.7344 17.3359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;/svg&gt;


    &lt;/span&gt;
  &lt;/button&gt;
  &lt;div class=&#34;collapse-content&#34; x-ref=&#34;content&#34; hidden=&#34;until-found&#34;&gt;
    &lt;div class=&#34;collapse-content__inner&#34; x-ref=&#34;content-inner&#34;&gt;
&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Alloy&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-alloy&#34;&gt;// Discover docker containers to collect logs from
discovery.docker &amp;#34;docker_containers&amp;#34; {
    // Note that if you are using Docker Desktop Engine this may need to be changed to
    // something like &amp;#34;unix:///${HOME}/.docker/desktop/docker.sock&amp;#34;
    host = &amp;#34;unix:///var/run/docker.sock&amp;#34;
}

// Extract container name from __meta_docker_container_name label and add as label
discovery.relabel &amp;#34;docker_containers&amp;#34; {
    targets = discovery.docker.docker_containers.targets

    rule {
        source_labels = [&amp;#34;__meta_docker_container_name&amp;#34;]
        target_label  = &amp;#34;container&amp;#34;
    }
}

// Scrape logs from docker containers and send to be processed
loki.source.docker &amp;#34;docker_logs&amp;#34; {
    host    = &amp;#34;unix:///var/run/docker.sock&amp;#34;
    targets = discovery.relabel.docker_containers.output
    forward_to = [loki.process.process_logs.receiver]
}

// Process logs and send to Loki
loki.process &amp;#34;process_logs&amp;#34; {
    stage.docker { }

    forward_to = [loki.write.local_loki.receiver]
}

loki.write &amp;#34;local_loki&amp;#34; {
    endpoint {
        url = &amp;#34;http://localhost:3100/loki/api/v1/push&amp;#34;
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

]]></content><description>&lt;h1 id="processing-logs">Processing Logs&lt;/h1>
&lt;p>This tutorial assumes you are familiar with setting up and connecting components.
It covers using &lt;code>loki.source.api&lt;/code> to receive logs over HTTP, processing and filtering them, and sending them to Loki.&lt;/p></description></item></channel></rss>