<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Fundamentals on Grafana Labs</title><link>https://grafana.com/docs/loki/v2.8.x/fundamentals/</link><description>Recent content in Fundamentals on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/loki/v2.8.x/fundamentals/index.xml" rel="self" type="application/rss+xml"/><item><title>Overview</title><link>https://grafana.com/docs/loki/v2.8.x/fundamentals/overview/</link><pubDate>Wed, 15 Apr 2026 06:27:12 +0000</pubDate><guid>https://grafana.com/docs/loki/v2.8.x/fundamentals/overview/</guid><content><![CDATA[&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;Grafana Loki is a log aggregation tool,
and it is the core of a fully-featured logging stack.&lt;/p&gt;
&lt;p&gt;Loki is a datastore optimized for efficiently holding log data.
The efficient indexing of log data
distinguishes Loki from other logging systems.
Unlike other logging systems, a Loki index is built from labels,
leaving the original log message unindexed.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;loki-overview-1.png&#34;
  alt=&#34;Loki overview&#34;/&gt;&lt;/p&gt;
&lt;p&gt;An agent (also called a client) acquires logs,
turns the logs into streams,
and pushes the streams to Loki through an HTTP API.
The Promtail agent is designed for Loki installations,
but many other &lt;a href=&#34;../../clients/&#34;&gt;Agents&lt;/a&gt; seamlessly integrate with Loki.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;loki-overview-2.png&#34;
  alt=&#34;Loki agent interaction&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Loki indexes streams.
Each stream identifies a set of logs associated with a unique set of labels.
A quality set of labels is key to the creation of an index that is both compact
and allows for efficient query execution.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;../../logql/&#34;&gt;LogQL&lt;/a&gt; is the query language for Loki.&lt;/p&gt;
&lt;h2 id=&#34;loki-features&#34;&gt;Loki features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Efficient memory usage for indexing the logs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By indexing on a set of labels, the index can be significantly smaller
than other log aggregation products.
Less memory makes it less expensive to operate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Multi-tenancy&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Loki allows multiple tenants to utilize a single Loki instance.
The data of distinct tenants is completely isolated from other tenants.
Multi-tenancy is configured by assigning a tenant ID in the agent.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LogQL, Loki&amp;rsquo;s query language&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Users of the Prometheus query language, PromQL, will find LogQL familiar
and flexible for generating queries against the logs.
The language also facilitates the generation of metrics from log data,
a powerful feature that goes well beyond log aggregation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Loki can be run as a single binary;
all the components run in one process.&lt;/p&gt;
&lt;p&gt;Loki is designed for scalability,
as each of Loki&amp;rsquo;s components can be run as microservices.
Configuration permits scaling the microservices individually,
permitting flexible large-scale installations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many agents (clients) have plugin support.
This allows a current observability structure
to add Loki as their log aggregation tool without needing
to switch existing portions of the observability stack.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Grafana integration&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Loki seamlessly integrates with Grafana,
providing a complete observability stack.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="overview">Overview&lt;/h1>
&lt;p>Grafana Loki is a log aggregation tool,
and it is the core of a fully-featured logging stack.&lt;/p>
&lt;p>Loki is a datastore optimized for efficiently holding log data.
The efficient indexing of log data
distinguishes Loki from other logging systems.
Unlike other logging systems, a Loki index is built from labels,
leaving the original log message unindexed.&lt;/p></description></item><item><title>Architecture</title><link>https://grafana.com/docs/loki/v2.8.x/fundamentals/architecture/</link><pubDate>Wed, 15 Apr 2026 06:27:12 +0000</pubDate><guid>https://grafana.com/docs/loki/v2.8.x/fundamentals/architecture/</guid><content><![CDATA[&lt;h1 id=&#34;architecture&#34;&gt;Architecture&lt;/h1&gt;
&lt;h2 id=&#34;multi-tenancy&#34;&gt;Multi-tenancy&lt;/h2&gt;
&lt;p&gt;All data, both in memory and in long-term storage, may be partitioned by a
tenant ID, pulled from the &lt;code&gt;X-Scope-OrgID&lt;/code&gt; HTTP header in the request when Grafana Loki
is running in multi-tenant mode. When Loki is &lt;strong&gt;not&lt;/strong&gt; in multi-tenant mode, the
header is ignored and the tenant ID is set to &amp;ldquo;fake&amp;rdquo;, which will appear in the
index and in stored chunks.&lt;/p&gt;
&lt;h2 id=&#34;chunk-format&#34;&gt;Chunk Format&lt;/h2&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&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&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;  -------------------------------------------------------------------
  |                               |                                 |
  |        MagicNumber(4b)        |           version(1b)           |
  |                               |                                 |
  -------------------------------------------------------------------
  |         block-1 bytes         |          checksum (4b)          |
  -------------------------------------------------------------------
  |         block-2 bytes         |          checksum (4b)          |
  -------------------------------------------------------------------
  |         block-n bytes         |          checksum (4b)          |
  -------------------------------------------------------------------
  |                        #blocks (uvarint)                        |
  -------------------------------------------------------------------
  | #entries(uvarint) | mint, maxt (varint) | offset, len (uvarint) |
  -------------------------------------------------------------------
  | #entries(uvarint) | mint, maxt (varint) | offset, len (uvarint) |
  -------------------------------------------------------------------
  | #entries(uvarint) | mint, maxt (varint) | offset, len (uvarint) |
  -------------------------------------------------------------------
  | #entries(uvarint) | mint, maxt (varint) | offset, len (uvarint) |
  -------------------------------------------------------------------
  |                      checksum(from #blocks)                     |
  -------------------------------------------------------------------
  |                    #blocks section byte offset                  |
  -------------------------------------------------------------------&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;mint&lt;/code&gt; and &lt;code&gt;maxt&lt;/code&gt; describe the minimum and maximum Unix nanosecond timestamp,
respectively.&lt;/p&gt;
&lt;h3 id=&#34;block-format&#34;&gt;Block Format&lt;/h3&gt;
&lt;p&gt;A block is comprised of a series of entries, each of which is an individual log
line.&lt;/p&gt;
&lt;p&gt;Note that the bytes of a block are stored compressed using Gzip. The following
is their form when uncompressed:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&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&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;  -------------------------------------------------------------------
  |    ts (varint)    |     len (uvarint)    |     log-1 bytes      |
  -------------------------------------------------------------------
  |    ts (varint)    |     len (uvarint)    |     log-2 bytes      |
  -------------------------------------------------------------------
  |    ts (varint)    |     len (uvarint)    |     log-3 bytes      |
  -------------------------------------------------------------------
  |    ts (varint)    |     len (uvarint)    |     log-n bytes      |
  -------------------------------------------------------------------&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;ts&lt;/code&gt; is the Unix nanosecond timestamp of the logs, while len is the length in
bytes of the log entry.&lt;/p&gt;
&lt;h2 id=&#34;storage&#34;&gt;Storage&lt;/h2&gt;
&lt;h3 id=&#34;single-store&#34;&gt;Single Store&lt;/h3&gt;
&lt;p&gt;Loki stores all data in a single object storage backend. This mode of operation became generally available with Loki 2.0 and is fast, cost-effective, and simple, not to mention where all current and future development lies. This mode uses an adapter called &lt;a href=&#34;../../operations/storage/boltdb-shipper/&#34;&gt;&lt;code&gt;boltdb_shipper&lt;/code&gt;&lt;/a&gt; to store the &lt;code&gt;index&lt;/code&gt; in object storage (the same way we store &lt;code&gt;chunks&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id=&#34;deprecated-multi-store&#34;&gt;Deprecated: Multi-store&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;chunk store&lt;/strong&gt; is Loki&amp;rsquo;s long-term data store, designed to support
interactive querying and sustained writing without the need for background
maintenance tasks. It consists of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An index for the chunks. This index can be backed by:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://aws.amazon.com/dynamodb&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Amazon DynamoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cloud.google.com/bigtable&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Google Bigtable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cassandra.apache.org&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Apache Cassandra&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A key-value (KV) store for the chunk data itself, which can be:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://aws.amazon.com/dynamodb&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Amazon DynamoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cloud.google.com/bigtable&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Google Bigtable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cassandra.apache.org&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Apache Cassandra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://aws.amazon.com/s3&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Amazon S3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cloud.google.com/storage/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Google Cloud Storage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Unlike the other core components of Loki, the chunk store is not a separate
service, job, or process, but rather a library embedded in the two services
that need to access Loki data: the &lt;a href=&#34;components/#ingester&#34;&gt;ingester&lt;/a&gt; and &lt;a href=&#34;components/#querier&#34;&gt;querier&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The chunk store relies on a unified interface to the
&amp;ldquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/NoSQL&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;NoSQL&lt;/a&gt;&amp;rdquo; stores (DynamoDB, Bigtable, and
Cassandra) that can be used to back the chunk store index. This interface
assumes that the index is a collection of entries keyed by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;hash key&lt;/strong&gt;. This is required for &lt;em&gt;all&lt;/em&gt; reads and writes.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;range key&lt;/strong&gt;. This is required for writes and can be omitted for reads,
which can be queried by prefix or range.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The interface works somewhat differently across the supported databases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DynamoDB supports range and hash keys natively. Index entries are thus
modelled directly as DynamoDB entries, with the hash key as the distribution
key and the range as the DynamoDB range key.&lt;/li&gt;
&lt;li&gt;For Bigtable and Cassandra, index entries are modelled as individual column
values. The hash key becomes the row key and the range key becomes the column
key.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A set of schemas are used to map the matchers and label sets used on reads and
writes to the chunk store into appropriate operations on the index. Schemas have
been added as Loki has evolved, mainly in an attempt to better load balance
writes and improve query performance.&lt;/p&gt;
&lt;h2 id=&#34;read-path&#34;&gt;Read Path&lt;/h2&gt;
&lt;p&gt;To summarize, the read path works as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The querier receives an HTTP/1 request for data.&lt;/li&gt;
&lt;li&gt;The querier passes the query to all ingesters for in-memory data.&lt;/li&gt;
&lt;li&gt;The ingesters receive the read request and return data matching the query, if
any.&lt;/li&gt;
&lt;li&gt;The querier lazily loads data from the backing store and runs the query
against it if no ingesters returned data.&lt;/li&gt;
&lt;li&gt;The querier iterates over all received data and deduplicates, returning a
final set of data over the HTTP/1 connection.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;write-path&#34;&gt;Write Path&lt;/h2&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;./chunks_diagram.png&#34;
  alt=&#34;chunk_diagram&#34;/&gt;&lt;/p&gt;
&lt;p&gt;To summarize, the write path works as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The distributor receives an HTTP/1 request to store data for streams.&lt;/li&gt;
&lt;li&gt;Each stream is hashed using the hash ring.&lt;/li&gt;
&lt;li&gt;The distributor sends each stream to the appropriate ingesters and their
replicas (based on the configured replication factor).&lt;/li&gt;
&lt;li&gt;Each ingester will create a chunk or append to an existing chunk for the
stream&amp;rsquo;s data. A chunk is unique per tenant and per labelset.&lt;/li&gt;
&lt;li&gt;The distributor responds with a success code over the HTTP/1 connection.&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="architecture">Architecture&lt;/h1>
&lt;h2 id="multi-tenancy">Multi-tenancy&lt;/h2>
&lt;p>All data, both in memory and in long-term storage, may be partitioned by a
tenant ID, pulled from the &lt;code>X-Scope-OrgID&lt;/code> HTTP header in the request when Grafana Loki
is running in multi-tenant mode. When Loki is &lt;strong>not&lt;/strong> in multi-tenant mode, the
header is ignored and the tenant ID is set to &amp;ldquo;fake&amp;rdquo;, which will appear in the
index and in stored chunks.&lt;/p></description></item><item><title>Understanding labels</title><link>https://grafana.com/docs/loki/v2.8.x/fundamentals/labels/</link><pubDate>Wed, 15 Apr 2026 06:27:12 +0000</pubDate><guid>https://grafana.com/docs/loki/v2.8.x/fundamentals/labels/</guid><content><![CDATA[&lt;h1 id=&#34;understanding-labels&#34;&gt;Understanding labels&lt;/h1&gt;
&lt;p&gt;Labels are key value pairs and can be defined as anything! We like to refer to them as metadata to describe a log stream. If you are familiar with Prometheus, there are a few labels you are used to seeing like &lt;code&gt;job&lt;/code&gt; and &lt;code&gt;instance&lt;/code&gt;, and I will use those in the coming examples.&lt;/p&gt;
&lt;p&gt;The scrape configs we provide with Grafana Loki define these labels, too. If you are using Prometheus, having consistent labels between Loki and Prometheus is one of Loki&amp;rsquo;s superpowers, making it incredibly &lt;a href=&#34;/blog/2019/05/06/how-loki-correlates-metrics-and-logs--and-saves-you-money/&#34;&gt;easy to correlate your application metrics with your log data&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-loki-uses-labels&#34;&gt;How Loki uses labels&lt;/h2&gt;
&lt;p&gt;Labels in Loki perform a very important task: They define a stream. More specifically, the combination of every label key and value defines the stream. If just one label value changes, this creates a new stream.&lt;/p&gt;
&lt;p&gt;If you are familiar with Prometheus, the term used there is series; however, Prometheus has an additional dimension: metric name. Loki simplifies this in that there are no metric names, just labels, and we decided to use streams instead of series.&lt;/p&gt;
&lt;h2 id=&#34;format&#34;&gt;Format&lt;/h2&gt;
&lt;p&gt;Loki places the same restrictions on label naming as &lt;a href=&#34;https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It may contain ASCII letters and digits, as well as underscores and colons. It must match the regex &lt;code&gt;[a-zA-Z_:][a-zA-Z0-9_:]*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note: The colons are reserved for user defined recording rules. They should not be used by exporters or direct instrumentation.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id=&#34;loki-labels-demo&#34;&gt;Loki labels demo&lt;/h2&gt;
&lt;p&gt;This series of examples will illustrate basic use cases and concepts for labeling in Loki.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take an example:&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;scrape_configs:
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: syslog
      __path__: /var/log/syslog&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This config will tail one file and assign one label: &lt;code&gt;job=syslog&lt;/code&gt;. You could query it like this:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&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&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;{job=&amp;#34;syslog&amp;#34;}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will create one stream in Loki.&lt;/p&gt;
&lt;p&gt;Now let’s expand the example a little:&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;scrape_configs:
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: syslog
      __path__: /var/log/syslog
 - job_name: apache
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: apache
      __path__: /var/log/apache.log&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now we are tailing two files. Each file gets just one label with one value so Loki will now be storing two streams.&lt;/p&gt;
&lt;p&gt;We can query these streams in a few ways:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&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&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;{job=&amp;#34;apache&amp;#34;} &amp;lt;- show me logs where the job label is apache
{job=&amp;#34;syslog&amp;#34;} &amp;lt;- show me logs where the job label is syslog
{job=~&amp;#34;apache|syslog&amp;#34;} &amp;lt;- show me logs where the job is apache **OR** syslog&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In that last example, we used a regex label matcher to log streams that use the job label with two values. Now consider how an additional label could also be used:&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;scrape_configs:
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: syslog
      env: dev
      __path__: /var/log/syslog
 - job_name: apache
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: apache
      env: dev
      __path__: /var/log/apache.log&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now instead of a regex, we could do this:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&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&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;{env=&amp;#34;dev&amp;#34;} &amp;lt;- will return all logs with env=dev, in this case this includes both log streams&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Hopefully now you are starting to see the power of labels. By using a single label, you can query many streams. By combining several different labels, you can create very flexible log queries.&lt;/p&gt;
&lt;p&gt;Labels are the index to Loki&amp;rsquo;s log data. They are used to find the compressed log content, which is stored separately as chunks. Every unique combination of label and values defines a stream, and logs for a stream are batched up, compressed, and stored as chunks.&lt;/p&gt;
&lt;p&gt;For Loki to be efficient and cost-effective, we have to use labels responsibly. The next section will explore this in more detail.&lt;/p&gt;
&lt;h2 id=&#34;cardinality&#34;&gt;Cardinality&lt;/h2&gt;
&lt;p&gt;The two previous examples use statically defined labels with a single value; however, there are ways to dynamically define labels. Let&amp;rsquo;s take a look using the Apache log and a massive regex you could use to parse such a 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;nohighlight&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-nohighlight&#34;&gt;11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] &amp;#34;GET /1986.js HTTP/1.1&amp;#34; 200 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&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;- job_name: system
   pipeline_stages:
      - regex:
        expression: &amp;#34;^(?P&amp;lt;ip&amp;gt;\\S&amp;#43;) (?P&amp;lt;identd&amp;gt;\\S&amp;#43;) (?P&amp;lt;user&amp;gt;\\S&amp;#43;) \\[(?P&amp;lt;timestamp&amp;gt;[\\w:/]&amp;#43;\\s[&amp;#43;\\-]\\d{4})\\] \&amp;#34;(?P&amp;lt;action&amp;gt;\\S&amp;#43;)\\s?(?P&amp;lt;path&amp;gt;\\S&amp;#43;)?\\s?(?P&amp;lt;protocol&amp;gt;\\S&amp;#43;)?\&amp;#34; (?P&amp;lt;status_code&amp;gt;\\d{3}|-) (?P&amp;lt;size&amp;gt;\\d&amp;#43;|-)\\s?\&amp;#34;?(?P&amp;lt;referer&amp;gt;[^\&amp;#34;]*)\&amp;#34;?\\s?\&amp;#34;?(?P&amp;lt;useragent&amp;gt;[^\&amp;#34;]*)?\&amp;#34;?$&amp;#34;
    - labels:
        action:
        status_code:
   static_configs:
   - targets:
      - localhost
     labels:
      job: apache
      env: dev
      __path__: /var/log/apache.log&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This regex matches every component of the log line and extracts the value of each component into a capture group. Inside the pipeline code, this data is placed in a temporary data structure that allows using it for several purposes during the processing of that log line (at which point that temp data is discarded). Much more detail about this can be found in the &lt;a href=&#34;../../clients/promtail/pipelines/&#34;&gt;Promtail pipelines&lt;/a&gt; documentation.&lt;/p&gt;
&lt;p&gt;From that regex, we will be using two of the capture groups to dynamically set two labels based on content from the log line itself:&lt;/p&gt;
&lt;p&gt;action (for example, &lt;code&gt;action=&amp;quot;GET&amp;quot;&lt;/code&gt;, &lt;code&gt;action=&amp;quot;POST&amp;quot;&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;status_code (for example, &lt;code&gt;status_code=&amp;quot;200&amp;quot;&lt;/code&gt;, &lt;code&gt;status_code=&amp;quot;400&amp;quot;&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;And now let&amp;rsquo;s walk through a few example lines:&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;nohighlight&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-nohighlight&#34;&gt;11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] &amp;#34;GET /1986.js HTTP/1.1&amp;#34; 200 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;
11.11.11.12 - frank [25/Jan/2000:14:00:02 -0500] &amp;#34;POST /1986.js HTTP/1.1&amp;#34; 200 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;
11.11.11.13 - frank [25/Jan/2000:14:00:03 -0500] &amp;#34;GET /1986.js HTTP/1.1&amp;#34; 400 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;
11.11.11.14 - frank [25/Jan/2000:14:00:04 -0500] &amp;#34;POST /1986.js HTTP/1.1&amp;#34; 400 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In Loki the following streams would be created:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&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&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;{job=&amp;#34;apache&amp;#34;,env=&amp;#34;dev&amp;#34;,action=&amp;#34;GET&amp;#34;,status_code=&amp;#34;200&amp;#34;} 11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] &amp;#34;GET /1986.js HTTP/1.1&amp;#34; 200 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;
{job=&amp;#34;apache&amp;#34;,env=&amp;#34;dev&amp;#34;,action=&amp;#34;POST&amp;#34;,status_code=&amp;#34;200&amp;#34;} 11.11.11.12 - frank [25/Jan/2000:14:00:02 -0500] &amp;#34;POST /1986.js HTTP/1.1&amp;#34; 200 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;
{job=&amp;#34;apache&amp;#34;,env=&amp;#34;dev&amp;#34;,action=&amp;#34;GET&amp;#34;,status_code=&amp;#34;400&amp;#34;} 11.11.11.13 - frank [25/Jan/2000:14:00:03 -0500] &amp;#34;GET /1986.js HTTP/1.1&amp;#34; 400 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;
{job=&amp;#34;apache&amp;#34;,env=&amp;#34;dev&amp;#34;,action=&amp;#34;POST&amp;#34;,status_code=&amp;#34;400&amp;#34;} 11.11.11.14 - frank [25/Jan/2000:14:00:04 -0500] &amp;#34;POST /1986.js HTTP/1.1&amp;#34; 400 932 &amp;#34;-&amp;#34; &amp;#34;Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Those four log lines would become four separate streams and start filling four separate chunks.&lt;/p&gt;
&lt;p&gt;Any additional log lines that match those combinations of label/values would be added to the existing stream. If another unique combination of labels comes in (for example, &lt;code&gt;status_code=&amp;quot;500&amp;quot;&lt;/code&gt;) another new stream is created.&lt;/p&gt;
&lt;p&gt;Imagine now if you set a label for &lt;code&gt;ip&lt;/code&gt;. Not only does every request from a user become a unique stream. Every request with a different action or status_code from the same user will get its own stream.&lt;/p&gt;
&lt;p&gt;Doing some quick math, if there are maybe four common actions (GET, PUT, POST, DELETE) and maybe four common status codes (although there could be more than four!), this would be 16 streams and 16 separate chunks. Now multiply this by every user if we use a label for &lt;code&gt;ip&lt;/code&gt;.  You can quickly have thousands or tens of thousands of streams.&lt;/p&gt;
&lt;p&gt;This is high cardinality. This can kill Loki.&lt;/p&gt;
&lt;p&gt;When we talk about &lt;em&gt;cardinality&lt;/em&gt; we are referring to the combination of labels and values and the number of streams they create. High cardinality is using labels with a large range of possible values, such as &lt;code&gt;ip&lt;/code&gt;, &lt;strong&gt;or&lt;/strong&gt; combining many labels, even if they have a small and finite set of values, such as using &lt;code&gt;status_code&lt;/code&gt; and &lt;code&gt;action&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;High cardinality causes Loki to build a huge index (read: $$$$) and to flush thousands of tiny chunks to the object store (read: slow). Loki currently performs very poorly in this configuration and will be the least cost-effective and least fun to run and use.&lt;/p&gt;
&lt;h2 id=&#34;optimal-loki-performance-with-parallelization&#34;&gt;Optimal Loki performance with parallelization&lt;/h2&gt;
&lt;p&gt;Now you may be asking: If using lots of labels or labels with lots of values is bad, how am I supposed to query my logs? If none of the data is indexed, won&amp;rsquo;t queries be really slow?&lt;/p&gt;
&lt;p&gt;As we see people using Loki who are accustomed to other index-heavy solutions, it seems like they feel obligated to define a lot of labels in order to query their logs effectively. After all, many other logging solutions are all about the index, and this is the common way of thinking.&lt;/p&gt;
&lt;p&gt;When using Loki, you may need to forget what you know and look to see how the problem can be solved differently with parallelization. Loki&amp;rsquo;s superpower is breaking up queries into small pieces and dispatching them in parallel so that you can query huge amounts of log data in small amounts of time.&lt;/p&gt;
&lt;p&gt;This kind of brute force approach might not sound ideal, but let me explain why it is.&lt;/p&gt;
&lt;p&gt;Large indexes are complicated and expensive. Often a full-text index of your log data is the same size or bigger than the log data itself. To query your log data, you need this index loaded, and for performance, it should probably be in memory. This is difficult to scale, and as you ingest more logs, your index gets larger quickly.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s talk about Loki, where the index is typically an order of magnitude smaller than your ingested log volume. So if you are doing a good job of keeping your streams and stream churn to a minimum, the index grows very slowly compared to the ingested logs.&lt;/p&gt;
&lt;p&gt;Loki will effectively keep your static costs as low as possible (index size and memory requirements as well as static log storage) and make the query performance something you can control at runtime with horizontal scaling.&lt;/p&gt;
&lt;p&gt;To see how this works, let&amp;rsquo;s look back at our example of querying your access log data for a specific IP address. We don&amp;rsquo;t want to use a label to store the IP address. Instead we use a &lt;a href=&#34;../../logql/log_queries/#line-filter-expression&#34;&gt;filter expression&lt;/a&gt; to query for it:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&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&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;{job=&amp;#34;apache&amp;#34;} |= &amp;#34;11.11.11.11&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Behind the scenes, Loki will break up that query into smaller pieces (shards), and open up each chunk for the streams matched by the labels and start looking for this IP address.&lt;/p&gt;
&lt;p&gt;The size of those shards and the amount of parallelization is configurable and based on the resources you provision. If you want to, you can configure the shard interval down to 5m, deploy 20 queriers, and process gigabytes of logs in seconds. Or you can go crazy and provision 200 queriers and process terabytes of logs!&lt;/p&gt;
&lt;p&gt;This trade-off of smaller index and parallel brute force querying vs. a larger/faster full-text index is what allows Loki to save on costs versus other systems. The cost and complexity of operating a large index is high and is typically fixed &amp;ndash; you pay for it 24 hours a day if you are querying it or not.&lt;/p&gt;
&lt;p&gt;The benefits of this design mean you can make the decision about how much query power you want to have, and you can change that on demand. Query performance becomes a function of how much money you want to spend on it. Meanwhile, the data is heavily compressed and stored in low-cost object stores like S3 and GCS. This drives the fixed operating costs to a minimum while still allowing for incredibly fast query capability.&lt;/p&gt;
]]></content><description>&lt;h1 id="understanding-labels">Understanding labels&lt;/h1>
&lt;p>Labels are key value pairs and can be defined as anything! We like to refer to them as metadata to describe a log stream. If you are familiar with Prometheus, there are a few labels you are used to seeing like &lt;code>job&lt;/code> and &lt;code>instance&lt;/code>, and I will use those in the coming examples.&lt;/p></description></item></channel></rss>