<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Katerina Patticha - Elastic Observability Labs]]></title>
    <description><![CDATA[Trusted security news & research from the team at Elastic.]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Katerina Patticha - Elastic Observability Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltad972c1c27dbefc6/6a88d9782904ea5e8511d473/observability-labs-thumbnail.png</url>
      <link>https://www.elastic.co/observability-labs/author/katerina-patticha</link>
    </image>
    <link>https://www.elastic.co/observability-labs/author/katerina-patticha</link>
    <atom:link href="https://www.elastic.co/observability-labs/rss/author/katerina-patticha.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[en]]></language>
    <lastBuildDate>Wed, 23 Sep 2026 21:00:20 GMT</lastBuildDate>
  <item>
    <title><![CDATA[How one ES|QL query builds a metric chart for every metric in Elasticsearch]]></title>
    <description><![CDATA[METRICS_INFO reports what metrics are in your data and how to aggregate each one, so Kibana Discover can chart counters,  gauges and histograms correctly with no configuration and no field names to look up.]]></description>
    <content:encoded><![CDATA[<p>Type <code>TS metrics-*</code> in Kibana Discover and you get a chart for every metric in your data, already using the right aggregation and unit. No field names, no per-metric setup.</p>
<p><code>METRICS_INFO</code>, an ES|QL command, reports which metrics and time series exist in the scope of your query, one row each. Discover appends it to your query behind the scenes, builds every metric chart from that single response, and can split those charts by any dimension your data exposes. Gauges are averaged, counters use <code>SUM(RATE())</code>, histograms take a percentile. You never need to know which aggregation a metric requires.</p>
<p>For the design and internals, including the per-series sibling command <code>TS_INFO</code>, see the <a href="https://www.elastic.co/search-labs/blog/esql-metrics-info-ts-info-time-series-catalog">METRICS_INFO and TS_INFO deep dive</a>.</p>
<h2 id="whatmetrics_inforeturns">What METRICS_INFO returns</h2>
<p><code>METRICS_INFO</code> retrieves information about the metrics available in your <a href="https://www.elastic.co/docs/manage-data/data-store/data-streams/time-series-data-stream-tsds">time series data streams</a>, together with applicable dimensions and other metadata, all scoped to the current <code>TS</code> query.</p>
<pre><code>TS metrics-* | METRICS_INFO
</code></pre>
<p>You get one row describing each metric in the query scope:</p>
<p>| metric_name                         | data_stream                       | unit      | metric_type | field_type | dimension_fields                   |
| ----------------------------------- | --------------------------------- | --------- | ----------- | ---------- | ---------------------------------- |
| <code>system.cpu.user.pct</code>               | <code>metrics-system.cpu-default</code>      | <code>percent</code> | <code>gauge</code>     | <code>double</code>   | <code>[host.name, cloud.region]</code>        |
| <code>activemq.broker.connections.count</code> | <code>metrics-activemq.broker-default</code> | <code>null</code>    | <code>counter</code>   | <code>long</code>     | <code>[activemq.broker.mbean,agent.id]</code> |</p>
<p>For syntax, see the <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/metrics-info">METRICS_INFO command</a>. For the design and internals, including the per-series sibling command <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/ts-info">TS_INFO</a>, see the <a href="https://www.elastic.co/search-labs/blog/esql-metrics-info-ts-info-time-series-catalog">METRICS_INFO and TS_INFO deep dive</a>.</p>
<h2 id="howdiscoverturnsatsqueryintometriccharts">How Discover turns a TS query into metric charts</h2>
<p>Discover provides a dedicated experience for exploring metrics data. When it detects a <code>TS</code> query, it automatically builds an inventory of charts for the metrics available in your data.</p>
<p>Your original query remains unchanged and continues to run as usual. Behind the scenes, Discover derives a second request from it by appending <code>| METRICS_INFO</code>.</p>
<p>For example, if you run:</p>
<pre><code>TS metrics-*
| WHERE `cloud.provider` == "gcp" AND `cloud.region` == "us-central1"
</code></pre>
<p>Discover derives a second request behind the scenes:</p>
<pre><code>TS metrics-*
| WHERE `cloud.provider` == "gcp" AND `cloud.region` == "us-central1"
| METRICS_INFO
</code></pre>
<p>The <code>METRICS_INFO</code> response is parsed once and becomes the source for the dedicated metrics experience in Discover.
From that inventory, Discover can generate charts and provide capabilities such as searching and filtering metrics, breaking them down by dimensions, inspecting the ES|QL query behind each chart, and adding metrics to dashboards.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4948cc2b03015e1a/6a96918fd29b4edf151d776b/metrics-grid-overview.png" alt="Kibana Discover metrics inventory with one chart panel per metric returned by ES|QL METRICS_INFO" /></p>
<h2 id="whateachmetrics_infocolumncontrols">What each METRICS_INFO column controls</h2>
<p>Discover uses one <code>METRICS_INFO</code> response to generate every chart in the inventory. The response tells Discover which metrics to render, where to find their data, how to aggregate their values and how to display them.</p>
<p>Each column in the response plays a specific role:</p>
<p>| Column name        | What it controls in the inventory                       |
| ------------------ | ------------------------------------------------------- |
| <code>metric_name</code>      | Which metric panels are rendered                        |
| <code>data_stream</code>      | Where each panel gets its data                          |
| <code>metric_type</code>      | How each metric is aggregated                           |
| <code>field_type</code>       | The type of the field, e.g., <code>double</code>, <code>long</code>           |
| <code>unit</code>             | How values are formatted                                |
| <code>dimension_fields</code> | Which dimensions can be used to filter and split charts |</p>
<h3 id="whichmetricchartsgetrenderedmetric_name">Which metric charts get rendered: metric_name</h3>
<p>Each entry in the <code>METRICS_INFO</code> response represents a metric that Discover can visualize.</p>
<p>Discover iterates over the parsed response and creates a chart panel for each metric. The inventory therefore reflects the contents of the response directly.</p>
<h3 id="whereeachchartgetsitsdatadata_stream">Where each chart gets its data: data_stream</h3>
<p>Each chart queries its data independently, even though all metric metadata comes from the same <code>METRICS_INFO</code> request.</p>
<p>The <code>data_stream</code> value determines the source used to construct the chart's ES|QL query.</p>
<p>For example:</p>
<pre><code>TS metrics-system.cpu-default
| STATS AVG(system.cpu.user.pct) BY TBUCKET(100)
</code></pre>
<p>Querying each data stream separately matters most for searches that span multiple projects.</p>
<p>When the same <code>metric_name</code> appears in multiple <code>data_stream</code> values, Discover creates a separate panel for each stream. For example, in a serverless environment with <a href="https://www.elastic.co/docs/explore-analyze/cross-project-search">cross-project search</a>, each panel queries its own backing data and identifies the stream it represents.</p>
<blockquote>
  <p>This metric exists in multiple data streams. This chart shows data from <code>metrics-system.cpu-default</code> only.</p>
</blockquote>
<p>Discover separates the panels intentionally. Combining results across streams could hide differences between them, which may be important when investigating metrics across projects or environments.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt06e3c620101fe303/6a9691a627a5315c5edc8e22/duplicate-metric-name.png" alt="Kibana Discover metrics  showing two panels for the same metric, one per data stream, with a duplicate warning subtitle" /></p>
<h3 id="howcountergaugeandhistogrammetricsareaggregatedmetric_typefield_type">How counter, gauge, and histogram metrics are aggregated: metric_type, field_type</h3>
<p>The <code>metric_type</code> tells <a href="https://www.elastic.co/kibana/kibana-lens">Lens charts</a> how to aggregate the metric, while the <code>field_type</code> describes the field.</p>
<p>Three metric types are currently supported:</p>
<p>| <code>metric_type</code> | What the chart computes                            | Example               |
| ------------- | -------------------------------------------------- | --------------------- |
| <code>gauge</code>       | <code>AVG(field)</code>, representing a point-in-time level   | CPU usage             |
| <code>counter</code>     | <code>SUM(RATE(field))</code>, representing a rate of change  | Bytes sent per second |
| <code>histogram</code>   | <code>PERCENTILE(field, p)</code>, summarizing a distribution | p99 latency           |</p>
<h3 id="howvaluesaredisplayedunit">How values are displayed: unit</h3>
<p>The <code>unit</code> column controls how values are formatted on the Y axis. <a href="https://www.elastic.co/kibana/kibana-lens">Lens</a>, the charting library behind each panel, applies the formatting.</p>
<p>For example:</p>
<ul>
<li><code>bytes</code>: <code>1,024</code> is displayed as <code>1 KB</code>.</li>
<li><code>percent</code>: <code>0.75</code> is displayed as <code>75%</code>.</li>
<li>No unit: the raw value is displayed without unit-specific formatting.</li>
</ul>
<h3 id="howchartsarefilteredandsplitbydimensiondimension_fields">How charts are filtered and split by dimension: dimension_fields</h3>
<p>The <code>dimension_fields</code> column identifies the dimensions associated with each metric, such as <code>host.name</code>, <code>cloud.region</code>, or <code>service.name</code>.</p>
<p>Discover combines these values across the <code>METRICS_INFO</code> response to populate the dimensions dropdown in the inventory toolbar.</p>
<p>Selecting a dimension affects the inventory in two ways:</p>
<ol>
<li><p><strong>It filters the inventory.</strong> Discover re-runs <code>METRICS_INFO</code> with a condition such as <code>WHERE MV_CONTAINS(dimension_fields, "host.name")</code>, removing metrics that do not support the selected dimension.</p></li>
<li><p><strong>It splits each chart.</strong> Discover adds the selected dimension to the <code>BY</code> clause of each chart's ES|QL query, producing one series for each dimension value.</p></li>
</ol>
<p>For example:</p>
<pre><code>TS metrics-system.cpu-default
| STATS AVG(system.cpu.user.pct)
  BY TBUCKET(100), host.name
</code></pre>
<p>The result is a chart with a separate series for each <code>host.name</code>, while the inventory ensures that only metrics supporting that dimension are included in the inventory.</p>
<p>When you query a different data stream, any previously selected dimensions that the new stream does not expose are automatically cleared, so the per-chart queries never reference fields that do not exist there.</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbf20c62e1f3c807f/6a9691bca163364278371e89/dimensions-dropdown.png" alt="Dimensions dropdown in the Kibana Discover metrics experience filtering the inventory and splitting charts by host.name" /></p>
<h2 id="tryitinkibanadiscover">Try it in Kibana Discover</h2>
<p>Visualizing your metrics requires no configuration, no dashboard setup, and no per-metric query to write.
One <code>TS</code> query is enough.</p>
<h3 id="step1ingestmetricsdata">Step 1: Ingest metrics data</h3>
<p>If you are starting from scratch, you can send Prometheus metrics to Elasticsearch using <a href="https://www.elastic.co/observability-labs/blog/prometheus-metrics-elasticsearch-getting-started">Prometheus Remote Write</a>.
Any <a href="https://www.elastic.co/integrations">Elastic integration</a> that collects system or application metrics works the same way.
Once data lands in a TSDB-backed <code>metrics-*</code> data stream, Discover picks it up without any extra setup.</p>
<h3 id="step2opendiscoverandrunatsquery">Step 2: Open Discover and run a TS query</h3>
<ol>
<li>Open <strong>Kibana -&gt; Discover</strong>.</li>
<li>Switch to <strong>ES|QL</strong> mode.</li>
<li>Type <code>TS metrics-*</code> and run the query.</li>
</ol>
<h3 id="step3exploreyourmetriccharts">Step 3: Explore your metric charts</h3>
<p>Discover builds the inventory automatically. From there, you can:</p>
<ul>
<li>Search for a metric by name to narrow the inventory.</li>
<li>Select a dimension from the toolbar to split every chart by <code>host.name</code>, <code>cloud.region</code>, or any dimension your data exposes.</li>
<li>Click a chart panel to open the full ES|QL query behind it.</li>
<li>Add individual panels to a dashboard.</li>
</ul>
<p>Your metrics are ready to explore immediately, so you can start investigating your data as soon as you run the query.</p>
<p>See the documentation for how to <a href="https://www.elastic.co/docs/solutions/observability/infra-and-hosts/discover-metrics">Explore metrics data with Discover in Kibana</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/observability-labs/blog/esql-metrics-info-kibana-metrics-charts</link>
    <guid isPermaLink="false">esql-metrics-info-kibana-metrics-charts</guid>
    <category><![CDATA[Metrics]]></category>
    <dc:creator><![CDATA[Katerina Patticha]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltae655f749e58482e/6a95587bd05d4cb65c5816fe/header.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 03 Sep 2026 15:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>