<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Perses Blog</title>
    <link>https://perses.dev/blog/</link>
    <description>News, release notes and stories from the Perses community.</description>
    <atom:link href="https://perses.dev/blog/rss.xml" rel="self" type="application/rss+xml"/>
    <language>en</language>
    <lastBuildDate>Wed, 21 Oct 2026 00:00:00 GMT</lastBuildDate>
    <image><url>https://perses.dev/assets/images/favicon.png</url><title>Perses Blog</title><link>https://perses.dev/blog/</link></image>
    <item>
      <title>Release v0.55.0</title>
      <link>https://perses.dev/blog/2026/10/21/release-v0550/</link>
      <guid isPermaLink="true">https://perses.dev/blog/2026/10/21/release-v0550/</guid>
      <pubDate>Wed, 21 Oct 2026 00:00:00 GMT</pubDate>
      <category>Release notes</category>
      <description>Welcome to the v0.55.0 release!</description>
      <content:encoded><![CDATA[
<p>Welcome to the v0.55.0 release!</p>
<p>This release first comes with a large number of security fixes, several of them critical, so we strongly recommend
upgrading as soon as possible.</p>
<p>On the dashboard side, you can now repeat a single panel, define annotations per panel, drag and drop panels between
groups and lock the plugin versions used by a dashboard. Prometheus exemplars are supported, the search has been
rewritten on the backend, and two new plugins are available: Canvas and JSON.</p>
<p>As usual, this blog post doesn't cover every change. For the complete list, check the
<a href="https://github.com/perses/perses/releases/tag/v0.55.0">changelog</a>.</p>
<!-- more -->
<h2 id="security">Security</h2>
<p>This release fixes a significant number of security vulnerabilities, several of them critical. Most of them can be
exploited without authentication when Perses runs with its default configuration (<code>security.enable_auth: false</code>).
We strongly recommend upgrading as soon as possible.</p>
<p>Some of these fixes are breaking changes, check the <a href="https://perses.dev/docs/perses/latest/upgrade/v0.55.0/">upgrade guide</a>
before upgrading and or the section <a href="https://perses.dev/blog/2026/10/21/release-v0550/#breaking-changes">Breaking changes</a> below for more details.</p>
<p>We also published a <a href="https://perses.dev/docs/perses/latest/security/">security considerations</a> page
(<a href="https://github.com/perses/perses/pull/4512">#4512</a>) describing how to deploy Perses safely.</p>
<h3 id="authentication-bypass-via-forged-jwts-ghsa-mpfg-6jh9-3jmg">Authentication bypass via forged JWTs (<a href="https://github.com/perses/perses/security/advisories/GHSA-mpfg-6jh9-3jmg">GHSA-mpfg-6jh9-3jmg</a>)</h3>
<p>When authentication was enabled without setting <code>security.encryption_key</code> (or <code>security.encryption_key_file</code>), Perses
fell back to a key hardcoded in its public source code. This key is also used to sign the JWTs, so anyone could forge a
valid token for any user, including an admin.</p>
<p>Perses now refuses to start when authentication is enabled and no encryption key is provided.</p>
<h3 id="server-side-request-forgery-in-the-datasource-proxy-ghsa-58wc-w2cq-7vf3">Server-Side Request Forgery in the datasource proxy (<a href="https://github.com/perses/perses/security/advisories/GHSA-58wc-w2cq-7vf3">GHSA-58wc-w2cq-7vf3</a>)</h3>
<p>The datasource proxy (HTTP and SQL) connected to whatever destination the datasource defined. Combined with the
"unsaved" proxy endpoints, Perses could be used to read any service reachable from the server: loopback, cloud metadata
endpoints, the Kubernetes API, etc.</p>
<p>The destination of the proxy is now verified when a datasource is saved and before each request, including on every
resolved IP address. Loopback, link-local, the cloud metadata endpoints and the Kubernetes API are denied by default.
Private networks remain allowed. The restrictions can be adjusted in the new <code>datasource.proxy</code> configuration section:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">datasource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  proxy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    allowed_networks</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"127.0.0.0/8"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"::1/128"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span></code></pre>
<h3 id="arbitrary-file-read-through-secrets-ghsa-2qpg-wfx2-frv2">Arbitrary file read through secrets (<a href="https://github.com/perses/perses/security/advisories/GHSA-2qpg-wfx2-frv2">GHSA-2qpg-wfx2-frv2</a>)</h3>
<p>Secrets can reference files (<code>passwordFile</code>, <code>credentialsFile</code>, <code>clientSecretFile</code>, <code>caFile</code>, <code>certFile</code>, <code>keyFile</code>).
These files could be anywhere on the server, so a user able to create a secret could exfiltrate any file readable by
Perses through the datasource proxy.</p>
<p>File references are now rejected by default. They are only allowed in the directories listed in the new
<code>security.secret_file_allowed_directories</code> configuration.</p>
<h3 id="caller-credentials-forwarded-to-the-datasource-ghsa-phr8-237x-w7mj">Caller credentials forwarded to the datasource (<a href="https://github.com/perses/perses/security/advisories/GHSA-phr8-237x-w7mj">GHSA-phr8-237x-w7mj</a>)</h3>
<p>The HTTP datasource proxy forwarded the <code>Cookie</code> and <code>Authorization</code> headers of the caller to the datasource. Anyone
controlling a datasource could steal the Perses session of its users (including the refresh token) and take over their
account.</p>
<p>The <code>Cookie</code> header of the caller is no longer forwarded, and neither is the <code>Authorization</code> header when the native
authorization is enabled. To authenticate against a datasource, use a secret or the <code>oauthPassthrough</code> option.</p>
<h3 id="stored-xss-through-the-datasource-proxy-ghsa-8hm2-fqjh-pgj2">Stored XSS through the datasource proxy (<a href="https://github.com/perses/perses/security/advisories/GHSA-8hm2-fqjh-pgj2">GHSA-8hm2-fqjh-pgj2</a>)</h3>
<p>The responses of the datasource proxy are served from the Perses origin, almost unchanged. A malicious datasource could
serve HTML and JavaScript running with the session of any user opening a link to it, set cookies on the Perses domain,
or redirect users anywhere.</p>
<p>The proxy responses are now sandboxed with a strict <code>Content-Security-Policy</code>, and the headers that apply to the Perses
origin (<code>Set-Cookie</code>, CORS headers, absolute redirections, etc.) are removed. As a consequence, the UI of a datasource
(e.g. the Prometheus UI) can no longer be browsed through the proxy.</p>
<h3 id="sql-proxy-vulnerabilities">SQL proxy vulnerabilities</h3>
<p>Several vulnerabilities have been fixed in the SQL proxy:</p>
<ul>
<li><strong>Read-only restriction bypass</strong> (<a href="https://github.com/perses/perses/security/advisories/GHSA-r457-39g6-wpc6">GHSA-r457-39g6-wpc6</a>):
queries modifying the data or the schema could get through the keyword check. Queries must now start with a read
keyword (<code>SELECT</code>, <code>WITH</code>, <code>SHOW</code>, etc.) and are executed in a read-only transaction. MySQL <code>multiStatements</code>, as
well as <code>SELECT ... INTO OUTFILE / DUMPFILE</code>, are rejected.</li>
<li><strong>Arbitrary file read with MySQL/MariaDB</strong> (<a href="https://github.com/perses/perses/security/advisories/GHSA-92jg-r5jf-x5fh">GHSA-92jg-r5jf-x5fh</a>):
the <code>allowAllFiles</code> driver option could be enabled from the datasource params, letting the database server read any
file of the Perses server. This option, as well as <code>allowCleartextPasswords</code> and <code>allowOldPasswords</code>, is now always
disabled.</li>
<li><strong>MySQL/MariaDB TLS config mix-up</strong> (<a href="https://github.com/perses/perses/security/advisories/GHSA-jg7f-c7hw-wxgw">GHSA-jg7f-c7hw-wxgw</a>):
two datasources with colliding names could use each other's TLS configuration (CA, client certificate, verification
settings). The TLS configuration is now set per connection.</li>
</ul>
<h3 id="missing-secret-authorization-in-dashboard-datasources-ghsa-mc34-vgvh-gpr7">Missing secret authorization in dashboard datasources (<a href="https://github.com/perses/perses/security/advisories/GHSA-mc34-vgvh-gpr7">GHSA-mc34-vgvh-gpr7</a>)</h3>
<p>A user allowed to edit a dashboard, but not to read secrets, could embed a datasource referencing any secret of the
project and make the proxy send it to a server they control. Perses now checks that the user can read the secret used
by a datasource embedded in a dashboard.</p>
<h3 id="wiping-the-database-with-a-single-request-ghsa-j8hv-r356-hfw6">Wiping the database with a single request (<a href="https://github.com/perses/perses/security/advisories/GHSA-j8hv-r356-hfw6">GHSA-j8hv-r356-hfw6</a>)</h3>
<p>With the file system database, deleting the project <code>..</code> (<code>DELETE /api/v1/projects/..</code>) deleted the entire database.
The name of the resource in the URL was never validated. Every parameter of the URL is now validated before being used.</p>
<h3 id="path-traversal-in-the-file-system-database-ghsa-63qw-3pm6-j4f3-ghsa-2wxp-jhwc-h2ff">Path traversal in the file system database (<a href="https://github.com/perses/perses/security/advisories/GHSA-63qw-3pm6-j4f3">GHSA-63qw-3pm6-j4f3</a>, <a href="https://github.com/perses/perses/security/advisories/GHSA-2wxp-jhwc-h2ff">GHSA-2wxp-jhwc-h2ff</a>)</h3>
<p>The fix released in v0.54.0 for <a href="https://github.com/perses/perses/security/advisories/GHSA-vr5f-w35q-98jp">CVE-2026-63445</a>
could be bypassed with a project named <code>..</code> (e.g. <code>GET /api/v1/variables?project=..</code>), returning the whole database. The
anonymous endpoint <code>POST /api/validate/dashboards</code> was also using the <code>metadata.project</code> of the dashboard without any
validation.</p>
<p>The project name is now validated for every HTTP method and in the body of the requests, and the file system database
itself rejects any key that would escape its directory.</p>
<p>Note that these issues (as well as the previous one) don't affect the SQL database.</p>
<aside class="admonition" data-type="info" data-severity="info" data-title="Implementation details">
<p>If you want to see how these vulnerabilities have been fixed, here are the related pull requests:</p>























































<table><thead><tr><th>Vulnerability</th><th>Pull request(s)</th><th>Advisory</th></tr></thead><tbody><tr><td>Forged JWTs (default encryption key)</td><td><a href="https://github.com/perses/perses/pull/4550">#4550</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-mpfg-6jh9-3jmg">GHSA-mpfg-6jh9-3jmg</a></td></tr><tr><td>SSRF in the datasource proxy</td><td><a href="https://github.com/perses/perses/pull/4518">#4518</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-58wc-w2cq-7vf3">GHSA-58wc-w2cq-7vf3</a></td></tr><tr><td>Arbitrary file read through secrets</td><td><a href="https://github.com/perses/perses/pull/4503">#4503</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-2qpg-wfx2-frv2">GHSA-2qpg-wfx2-frv2</a></td></tr><tr><td>Caller credentials forwarded to the datasource</td><td><a href="https://github.com/perses/perses/pull/4553">#4553</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-phr8-237x-w7mj">GHSA-phr8-237x-w7mj</a></td></tr><tr><td>Stored XSS through the datasource proxy</td><td><a href="https://github.com/perses/perses/pull/4558">#4558</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-8hm2-fqjh-pgj2">GHSA-8hm2-fqjh-pgj2</a></td></tr><tr><td>SQL proxy vulnerabilities</td><td><a href="https://github.com/perses/perses/pull/4522">#4522</a>, <a href="https://github.com/perses/perses/pull/4535">#4535</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-r457-39g6-wpc6">GHSA-r457-39g6-wpc6</a>, <a href="https://github.com/perses/perses/security/advisories/GHSA-92jg-r5jf-x5fh">GHSA-92jg-r5jf-x5fh</a>, <a href="https://github.com/perses/perses/security/advisories/GHSA-jg7f-c7hw-wxgw">GHSA-jg7f-c7hw-wxgw</a></td></tr><tr><td>Missing secret authorization in dashboard datasources</td><td><a href="https://github.com/perses/perses/pull/4487">#4487</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-mc34-vgvh-gpr7">GHSA-mc34-vgvh-gpr7</a></td></tr><tr><td>Wiping the database with a single request</td><td><a href="https://github.com/perses/perses/pull/4499">#4499</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-j8hv-r356-hfw6">GHSA-j8hv-r356-hfw6</a></td></tr><tr><td>Path traversal in the file system database</td><td><a href="https://github.com/perses/perses/pull/4485">#4485</a>, <a href="https://github.com/perses/perses/pull/4488">#4488</a>, <a href="https://github.com/perses/perses/pull/4491">#4491</a>, <a href="https://github.com/perses/perses/pull/4492">#4492</a></td><td><a href="https://github.com/perses/perses/security/advisories/GHSA-63qw-3pm6-j4f3">GHSA-63qw-3pm6-j4f3</a>, <a href="https://github.com/perses/perses/security/advisories/GHSA-2wxp-jhwc-h2ff">GHSA-2wxp-jhwc-h2ff</a></td></tr></tbody></table>
</aside>
<h2 id="breaking-changes">Breaking changes</h2>
<h3 id="removal-of-the-package-perses-devcore">Removal of the package <code>@perses-dev/core</code></h3>
<p>As announced in v0.54.0, <code>@perses-dev/core</code> is no longer published
(<a href="https://github.com/perses/perses/pull/4325">#4325</a>). Its code has been dispatched in <code>@perses-dev/spec</code>,
<code>@perses-dev/client</code>, <code>@perses-dev/plugin-system</code> and <code>@perses-dev/components</code>. It is also no longer shared with the
plugins at runtime (<a href="https://github.com/perses/shared/pull/246">perses/shared#246</a>), so plugins still importing it must
be migrated.</p>
<h3 id="dependency-upgrades-react-17-dropped-node-24-typescript-7-and-end-of-commonjs">Dependency upgrades: React 17 dropped, Node 24, TypeScript 7 and end of CommonJS</h3>
<p>The frontend toolchain has been modernized across all the repositories:</p>
<ul>
<li><strong>React 17 is no longer supported</strong> (<a href="https://github.com/perses/perses/pull/4391">#4391</a>,
<a href="https://github.com/perses/shared/pull/269">perses/shared#269</a>, <a href="https://github.com/perses/plugins/pull/790">perses/plugins#790</a>),
as planned in the <a href="https://github.com/perses/perses/blob/main/ROADMAP.md">roadmap</a>.</li>
<li><strong>Node.js 24 (LTS) and ES2023</strong> are now the target (<a href="https://github.com/perses/perses/pull/4380">#4380</a>,
<a href="https://github.com/perses/shared/pull/248">perses/shared#248</a>, <a href="https://github.com/perses/spec/pull/78">perses/spec#78</a>,
<a href="https://github.com/perses/plugins/pull/779">perses/plugins#779</a>).</li>
<li><strong>Packages are published as ESM only</strong>: the CommonJS output has been removed.</li>
<li><strong>TypeScript 7</strong>, as well as newer versions of Zod and React Hook Form (<a href="https://github.com/perses/perses/pull/4421">#4421</a>).</li>
</ul>
<p>If you embed Perses in your own application, you now have to register the Perses packages shared with the plugins
before rendering your app (<a href="https://github.com/perses/shared/pull/268">perses/shared#268</a>):</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-typescript"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> *</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PersesClient </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@perses-dev/client'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> *</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PersesComponents </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@perses-dev/components'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> *</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PersesDashboards </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@perses-dev/dashboards'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> *</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PersesExplore </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@perses-dev/explore'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> *</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PersesPluginSystem </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@perses-dev/plugin-system'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { registerHostSharedModules } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@perses-dev/plugin-system'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> *</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PersesSpec </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> '@perses-dev/spec'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">registerHostSharedModules</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  '@perses-dev/spec'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: PersesSpec,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  '@perses-dev/client'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: PersesClient,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  '@perses-dev/components'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: PersesComponents,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  '@perses-dev/plugin-system'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: PersesPluginSystem,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  '@perses-dev/explore'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: PersesExplore,</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  '@perses-dev/dashboards'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: PersesDashboards,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">});</span></span></code></pre>
<h3 id="removal-of-the-old-dashboard-and-datasource-specification">Removal of the old dashboard and datasource specification</h3>
<p>Since v0.54.0, the dashboard and datasource specifications live in <a href="https://github.com/perses/spec">perses/spec</a>. The
deprecated copies remaining in Perses have been removed (<a href="https://github.com/perses/perses/pull/4326">#4326</a>): the Go
packages <code>pkg/model/api/v1/{common,dashboard,datasource,plugin,variable}</code> and their CUE equivalents. If you still import
them, switch to the ones provided by <code>github.com/perses/spec</code> (e.g. <code>github.com/perses/spec/go/dashboard</code>).</p>
<h3 id="go-sdk-datasourceselector-is-now-a-union-type">Go SDK: <code>datasource.Selector</code> is now a union type</h3>
<p>A datasource selector can now reference a variable, which is serialized as a plain string (e.g. <code>"$myDatasource"</code>)
(<a href="https://github.com/perses/perses/pull/4545">#4545</a>). As a result, <code>datasource.Selector</code> no longer has the <code>Kind</code> and
<code>Name</code> fields, but a <code>Static</code> or a <code>Variable</code> selector. Use the new constructors instead of a struct literal
(<a href="https://github.com/perses/perses/pull/4557">#4557</a>):</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-go"><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Before</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sel </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x26;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">datasource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Selector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{Kind: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"PrometheusDatasource"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, Name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"myPrometheus"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// After</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">static </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datasource.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NewStaticSelector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"PrometheusDatasource"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"myPrometheus"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">variable, err </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datasource.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NewVariableSelector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"myDatasource"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Or let the SDK detect a variable reference ("$foo" or "${foo}")</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">auto, err </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> datasource.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NewSelector</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"PrometheusDatasource"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, name)</span></span></code></pre>
<p>The official plugins have been updated (<a href="https://github.com/perses/plugins/pull/857">perses/plugins#857</a>): their
<code>Selector</code> helper now detects variable references, and a new <code>VariableSelector</code> helper is available. If you maintain
your own datasource plugin with a <code>Selector</code> helper, update it the same way.</p>
<p>Likewise, the deprecated CUE package <code>cue/common/proxy</code> has been removed from perses/shared
(<a href="https://github.com/perses/shared/pull/327">perses/shared#327</a>). Use <code>github.com/perses/spec/cue/datasource/proxy/http</code>
and <code>github.com/perses/spec/cue/datasource/proxy/sql</code> instead.</p>
<h3 id="api-changes-in-the-typescript-packages">API changes in the TypeScript packages</h3>
<p>If you develop plugins or embed Perses, these changes in the <code>@perses-dev/*</code> packages may require an update:</p>
<ul>
<li><code>useDeepMemo</code> and <code>useMemoized</code> are removed, use React <code>useMemo</code> instead. The <code>spec</code> of a <code>Resource</code> and the cell
values of <code>TableColumnConfig</code> are now <code>unknown</code> instead of <code>any</code> (<a href="https://github.com/perses/shared/pull/310">perses/shared#310</a>).</li>
<li><code>useId</code> is no longer exported from <code>@perses-dev/components</code>, use React <code>useId()</code> instead
(<a href="https://github.com/perses/shared/pull/348">perses/shared#348</a>).</li>
<li>Zod schemas are typed with <code>z.ZodType&#x3C;T, T></code> instead of <code>z.ZodType&#x3C;T></code> or the deprecated <code>z.ZodSchema&#x3C;T></code>
(<a href="https://github.com/perses/shared/pull/282">perses/shared#282</a>, <a href="https://github.com/perses/spec/pull/95">perses/spec#95</a>).</li>
<li>The <code>PanelEditorValues</code> type and its schema are removed from <code>@perses-dev/spec</code>, use the ones from
<code>@perses-dev/plugin-system</code> (<a href="https://github.com/perses/spec/pull/59">perses/spec#59</a>).</li>
<li>Annotations are now fetched on demand, only by the panels displaying them
(<a href="https://github.com/perses/shared/pull/330">perses/shared#330</a>). The <code>annotationState</code> store field and the
<code>setAnnotationState</code> action are removed, and <code>usePanelAnnotationsWithData</code> no longer returns hidden annotations.</li>
</ul>
<h3 id="security-changes">Security changes</h3>
<p>Some of the <a href="https://perses.dev/blog/2026/10/21/release-v0550/#security">security fixes</a> require a configuration change on your side:</p>
<ul>
<li><strong>Encryption key</strong>: if authentication is enabled, <code>security.encryption_key</code> (or <code>security.encryption_key_file</code>) must be
set, otherwise Perses won't start. If you were relying on the default key, the secrets previously stored can no longer
be decrypted and must be re-created, and users will have to log in again.</li>
<li><strong>Datasource proxy destinations</strong>: datasources pointing to loopback, link-local addresses, cloud metadata endpoints or
the Kubernetes API are now rejected. If you rely on such datasources (e.g. a Prometheus running next to Perses on
<code>localhost</code>), allow them through <code>datasource.proxy.allowed_networks</code> or <code>datasource.proxy.allowed_hosts</code>. URLs
containing credentials (<code>https://user:password@host</code>) are also refused: use a secret instead.</li>
<li><strong>Files referenced in secrets</strong>: they are rejected by default. List the directories containing them in
<code>security.secret_file_allowed_directories</code>.</li>
<li><strong>Resource names</strong>: a name can no longer contain <code>..</code>, nor start or end with <code>.</code>
(<a href="https://github.com/perses/spec/pull/102">perses/spec#102</a>). Rename the resources using such a name.</li>
<li><strong>Proxy headers</strong>: the <code>Authorization</code> header of the caller is no longer forwarded to the datasource when the native
authorization is enabled, and the UI of a datasource can no longer be browsed through the proxy.</li>
</ul>
<p>See the <a href="https://perses.dev/docs/perses/latest/upgrade/v0.55.0/">upgrade guide</a> for more details.</p>
<h2 id="performance-improvements">Performance improvements</h2>
<p>This release comes with several performance improvements on the backend. The numbers below come from the benchmarks
shared in the corresponding pull requests.</p>
<h3 id="datasource-proxy-reuses-its-connections">Datasource proxy reuses its connections</h3>
<p>Until now, the proxy created a new HTTP transport for every proxied request, so no TCP or TLS connection was ever
reused. Perses now keeps one transport per saved datasource
(<a href="https://github.com/perses/perses/pull/4521">#4521</a>), which is particularly visible with HTTPS datasources:</p>



































<table><thead><tr><th>Case</th><th>Before</th><th>After</th><th>Gain</th></tr></thead><tbody><tr><td>HTTP, sequential</td><td>153 µs/op</td><td>70 µs/op</td><td>~2.2x</td></tr><tr><td>HTTP, parallel (10 CPUs)</td><td>60 µs/op</td><td>22 µs/op</td><td>~2.8x</td></tr><tr><td>HTTPS, sequential</td><td>1.69 ms/op</td><td>72 µs/op</td><td><strong>~23x</strong></td></tr><tr><td>HTTPS, parallel (10 CPUs)</td><td>295 µs/op</td><td>23 µs/op</td><td><strong>~13x</strong></td></tr></tbody></table>
<p>It also uses ~4x less memory per request. On a real network, each request additionally saves the round trips of the
TCP and TLS handshakes. The connection limits can be tuned with the new <code>datasource.proxy.http</code> configuration:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">datasource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  proxy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    http</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      max_conns_per_host</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # 0 = no limit</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      max_idle_conns</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">100</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      max_idle_conns_per_host</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span></span></code></pre>
<h3 id="faster-native-authorization">Faster native authorization</h3>
<p>The permission cache of the native authorization is rebuilt at startup, periodically, on every RBAC change and on the
first login of every OAuth/OIDC user. Its build now runs in linear time
(<a href="https://github.com/perses/perses/pull/4540">#4540</a>). With 10,000 users and 1,000 projects:</p>























<table><thead><tr><th>Benchmark</th><th>Before</th><th>After</th><th>Delta</th></tr></thead><tbody><tr><td>Cache refresh</td><td>2.81 s</td><td>21 ms</td><td><strong>−99.25%</strong></td></tr><tr><td>25 simultaneous first OAuth logins</td><td>12.68 s</td><td>149 ms</td><td><strong>−98.82%</strong></td></tr></tbody></table>
<p>The cache is now also an immutable snapshot read without any lock
(<a href="https://github.com/perses/perses/pull/4537">#4537</a>). It fixes a deadlock that could hang every authorization check
until a restart, and makes permission checks under concurrent load <strong>~7x faster</strong> (from ~145 ns to ~20 ns per check).</p>
<h3 id="faster-plugin-extraction-at-startup">Faster plugin extraction at startup</h3>
<p>Plugin archives are now extracted in parallel (<a href="https://github.com/perses/perses/pull/4507">#4507</a>), and the ones
already extracted are skipped (<a href="https://github.com/perses/perses/pull/4534">#4534</a>). With the default plugins (32
archives, ~9,000 files), the extraction step goes from <strong>~1–2 s to ~1 ms</strong> when the archives are already extracted, and
the whole plugin initialization from ~1.35 s to ~0.3 s.</p>
<p>Skipping the archives benefits binary installations and deployments where the plugin folder is kept between restarts
(e.g. mounted on a volume). With the official container image and its default setup, every new container still extracts
all archives, but in parallel.</p>
<h3 id="better-browser-caching-of-static-assets">Better browser caching of static assets</h3>
<p>Content-hashed JS and CSS bundles (<a href="https://github.com/perses/perses/pull/4475">#4475</a>), as well as fonts and images
from the app and the plugins (<a href="https://github.com/perses/perses/pull/4533">#4533</a>), are now served as immutable assets.
Browsers no longer download or revalidate them on every page load.</p>
<h2 id="dashboard-lock-mode">Dashboard lock mode</h2>
<p>Dashboards don't pin the version of the plugins they use, so a plugin upgrade can change how a panel looks. The new lock
mode (<a href="https://github.com/perses/shared/pull/243">perses/shared#243</a>) pins every plugin of a dashboard to the latest
installed version. When a newer version is available, a button lets you update the plugins, with a preview of the
change based on the first panel using it. If a pinned version is no longer installed, an error is displayed.</p>
<p>The panel type selector also shows the plugin version when several versions are installed.</p>
<p>The feature is disabled by default (<a href="https://github.com/perses/perses/pull/4370">#4370</a>):</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">frontend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  enable_lock_mode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span></code></pre>
<p><img src="https://perses.dev/assets/images/blog/v055/lock-mode-update.png" alt="Update locked plugins"></p>
<h2 id="drag-and-drop-panels-between-panel-groups">Drag and drop panels between panel groups</h2>
<p>The grid layout library has been replaced by Snapgrid (<a href="https://github.com/perses/shared/pull/296">perses/shared#296</a>),
so panels can now be dragged from one panel group to another. Drag and drop in lists (e.g. item actions) is also only
triggered from the drag handle, so you can select text again (<a href="https://github.com/perses/shared/pull/335">perses/shared#335</a>).</p>
<p><img src="https://perses.dev/assets/images/blog/v055/drag-and-drop.gif" alt="Drag and drop panels between panel groups"></p>
<h2 id="panel-repeat">Panel repeat</h2>
<p>Until now, only a panel group could be repeated over the values of a variable. A single panel can now be repeated as
well (<a href="https://github.com/perses/spec/pull/32">perses/spec#32</a>,
<a href="https://github.com/perses/shared/pull/149">perses/shared#149</a>). In the <code>Layout</code> tab of the panel editor, choose the
variable, the alignment (<code>horizontal</code> or <code>vertical</code>) and the maximum number of panels per row or column:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">layouts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">kind</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Grid</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    spec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      items</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">x</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">          y</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          width</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">12</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          height</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">6</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          content</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">            $ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'#/spec/panels/cpu'</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          repeatVariable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">            value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">instance</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">            alignment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">horizontal</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">            maxPer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">4</span></span></code></pre>
<p>Only the selected values are used, and a group repeat takes precedence over a panel repeat. Repeated panels are also
supported by the Grafana migration (<a href="https://github.com/perses/perses/pull/4328">#4328</a>).</p>
<video controls>
  <source src="https://perses.dev/assets/images/blog/v055/panel-repeat.mp4" type="video/mp4">
  Your browser does not support the video tag.
</video>
<h2 id="panel-level-annotations">Panel-level annotations</h2>
<p>v0.54.0 introduced annotations at the dashboard level. They can now be defined on a panel as well
(<a href="https://github.com/perses/spec/pull/61">perses/spec#61</a>, <a href="https://github.com/perses/shared/pull/206">perses/shared#206</a>,
<a href="https://github.com/perses/perses/pull/4356">#4356</a>). The panel displays the dashboard annotations plus its own ones.</p>
<p>A new <code>Annotations</code> tab is available in the panel editor for the plugins supporting it. For now, only the
<code>TimeSeriesChart</code> does (<a href="https://github.com/perses/plugins/pull/754">perses/plugins#754</a>). Panel annotations are
validated by the backend like the dashboard ones (<a href="https://github.com/perses/perses/pull/4299">#4299</a>), and the Go SDK
can now build both of them (<a href="https://github.com/perses/perses/pull/4448">#4448</a>).</p>
<p><img src="https://perses.dev/assets/images/blog/v055/panel-annotations.png" alt="Panel annotations editor"></p>
<h2 id="exemplars-support">Exemplars support</h2>
<p>The Prometheus datasource can now fetch <a href="https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage">exemplars</a>
(<a href="https://github.com/perses/plugins/pull/799">perses/plugins#799</a>). It is disabled by default and must be enabled per
datasource:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">kind</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">GlobalDatasource</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">metadata</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">prometheus</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">spec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  plugin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    kind</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">PrometheusDatasource</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    spec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      exemplars</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        enable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      proxy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        kind</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">HTTPProxy</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        spec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          url</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">https://prometheus.example.com</span></span></code></pre>
<p>Exemplars are then fetched with range queries and displayed by the <code>TimeSeriesChart</code> as diamonds on top of their series
(<a href="https://github.com/perses/plugins/pull/800">perses/plugins#800</a>). Hovering one shows its labels (e.g. the trace ID),
value and timestamp, and clicking it pins the tooltip (<a href="https://github.com/perses/shared/pull/278">perses/shared#278</a>).</p>
<p><img src="https://perses.dev/assets/images/blog/v055/exemplars.png" alt="Exemplars in a TimeSeriesChart"></p>
<h2 id="improved-search-experience">Improved search experience</h2>
<p>The search is now done by the backend, through the new endpoint <code>/api/v1/search/dashboards</code>
(<a href="https://github.com/perses/perses/pull/4355">#4355</a>). Dashboards are indexed in memory and matched with a fuzzy search.
With a SQL database, every Perses instance periodically checks for changes to keep its index in sync. By default, the
name and the display name are indexed, but you can index any attribute, like the panel names:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">search</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  index_keys</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    dashboard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">metadata.name</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">spec.display.name</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">spec.panels.@dig:display.name</span></span></code></pre>
<p>The project view also uses this endpoint to list the dashboards, without loading their full definition
(<a href="https://github.com/perses/perses/pull/4366">#4366</a>), and its search bar now matches tags too
(<a href="https://github.com/perses/perses/pull/4446">#4446</a>).</p>
<p>Finally, the important dashboards of the home page can be organized in groups, and an entire project can be marked as
important (<a href="https://github.com/perses/perses/pull/4506">#4506</a>). The previous flat list is still supported but
deprecated.</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">frontend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  important_dashboards</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Perses demos</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      dashboards</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">project</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">perses</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">project</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">testing</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Quick links</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      description</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Highlighted dashboards</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      dashboards</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">project</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">perses</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          dashboard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">nodeexporter</span></span></code></pre>
<p><img src="https://perses.dev/assets/images/blog/v055/important-dashboards.png" alt="Grouped important dashboards"></p>
<h2 id="authentication-authorization">Authentication &#x26; authorization</h2>
<ul>
<li>
<p><strong>Roles from OAuth/OIDC claims</strong> (<a href="https://github.com/perses/perses/pull/4172">#4172</a>): roles can be assigned from the
claims of the identity provider token, without creating any RoleBinding. Without <code>project</code>, the role is a GlobalRole.</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">security</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  authentication</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    providers</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      oidc</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">slug_id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">keycloak</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">          # ...</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          claims</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">claim_name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">roles</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">              mappings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">claim_value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">admin</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">                  role_name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">admin</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">                - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">claim_value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">ops</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">                  role_name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">editor</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">                  project</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">platform</span></span></code></pre>
</li>
<li>
<p><strong>OAuth pass-through</strong> (<a href="https://github.com/perses/perses/pull/4404">#4404</a>): with <code>oauthPassThrough: true</code> in its
<code>HTTPProxy</code>, a datasource is queried with the OAuth/OIDC token of the current user. The token is refreshed when needed.</p>
</li>
<li>
<p><strong>Kubernetes impersonation</strong> (<a href="https://github.com/perses/perses/pull/4339">#4339</a>): with the Kubernetes authorization,
the <code>Impersonate-User</code> header is honored if the caller is allowed to impersonate this user.</p>
</li>
<li>
<p><strong>Pre-hashed passwords</strong> (<a href="https://github.com/perses/perses/pull/4423">#4423</a>): users can be provisioned with a bcrypt
hash (<code>spec.nativeProvider.passwordHash</code>) instead of a cleartext password.</p>
</li>
<li>
<p><strong>OIDC login property</strong> (<a href="https://github.com/perses/perses/pull/4468">#4468</a>): like the OAuth provider, the OIDC
provider supports <code>custom_login_property</code> to choose the user info field used as login (e.g. <code>preferred_username</code>).</p>
</li>
</ul>
<h2 id="http-proxy-improvements">HTTP proxy improvements</h2>
<p>The HTTP proxy used by the datasources received a lot of attention in this release: it is safer, faster and more
configurable.</p>
<h3 id="header-filtering-policies">Header filtering policies</h3>
<p>Some datasources don't play well with certain headers sent by the browser or added by Perses (e.g. <code>X-Forwarded-For</code>).
The <code>HTTPProxy</code> spec now supports two optional header policies
(<a href="https://github.com/perses/perses/pull/4428">#4428</a>):</p>
<ul>
<li><code>allowHeaders</code>: only the listed headers are forwarded to the datasource.</li>
<li><code>dropHeaders</code>: the listed headers are removed, and the others are forwarded.</li>
</ul>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">kind</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">Datasource</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">metadata</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">prometheus</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  project</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">my-project</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">spec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  plugin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    kind</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">PrometheusDatasource</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    spec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      proxy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        kind</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">HTTPProxy</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        spec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          url</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">https://prometheus.example.com</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          dropHeaders</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">X-Forwarded-For</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">User-Agent</span></span></code></pre>
<p>Header names are case-insensitive and only one of the two lists can be set. The filtering is applied after the headers
defined in the datasource, but before the secret authentication, so there is no need to allow <code>Authorization</code> when the
datasource uses a secret.</p>
<h3 id="configurable-timeout">Configurable timeout</h3>
<p>The <code>HTTPProxy</code> spec also accepts a new optional <code>timeout</code> field, available in the datasource editor as well
(<a href="https://github.com/perses/perses/pull/4525">#4525</a>). To avoid letting users hold goroutines and sockets against
unreachable hosts for too long, the timeout of a datasource is bounded by the server configuration:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">datasource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  proxy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    http</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      default_timeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">30s</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # used when the datasource doesn't define a timeout</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      max_timeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">1m</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> # highest timeout a datasource can define</span></span></code></pre>
<p>A datasource defining a timeout greater than <code>max_timeout</code> is rejected when it is saved, and its timeout is clamped when
it is used.</p>
<h3 id="security-hardening">Security hardening</h3>
<p>As described in the <a href="https://perses.dev/blog/2026/10/21/release-v0550/#security">Security</a> section, the proxy has been hardened in many ways:</p>
<ul>
<li>its destination is verified against a list of allowed and denied networks/hosts (loopback, link-local, cloud metadata
endpoints and Kubernetes API denied by default), configurable through <code>datasource.proxy</code>. The allowed schemes can be
restricted with <code>datasource.proxy.http.allowed_schemes</code>;</li>
<li>the <code>Cookie</code> header of the caller is never forwarded, and neither is the <code>Authorization</code> header when the native
authorization is enabled. An <code>Authorization</code> header defined in the <code>headers</code> of a datasource is ignored: use a secret
instead;</li>
<li>its responses are sandboxed with a strict <code>Content-Security-Policy</code>, and the headers applying to the Perses origin are
removed.</li>
</ul>
<p>Some of these changes may require a configuration update, check the <a href="https://perses.dev/blog/2026/10/21/release-v0550/#security-changes">Security changes</a> section and
the <a href="https://perses.dev/docs/perses/latest/concepts/proxy/">proxy documentation</a> for more details.</p>
<h3 id="connection-reuse">Connection reuse</h3>
<p>Finally, the proxy now keeps one HTTP transport per datasource and reuses its connections, making HTTPS requests up to
~23x faster. See <a href="https://perses.dev/blog/2026/10/21/release-v0550/#datasource-proxy-reuses-its-connections">Datasource proxy reuses its connections</a> for the numbers
and the new connection limits.</p>
<h2 id="refresh-interval-configuration">Refresh interval configuration</h2>
<p>The auto-refresh options of the dashboards can now be configured (<a href="https://github.com/perses/perses/pull/4432">#4432</a>),
or the auto-refresh can be disabled entirely (<a href="https://github.com/perses/perses/pull/4338">#4338</a>). In that case, the
interval picker is hidden and the <code>refreshInterval</code> of the dashboards, as well as the <code>?refresh=</code> URL parameter, are
ignored.</p>
<p>Similarly, administrators can define the default timezone, theme and number of rows per page, used when a user hasn't
chosen their own (<a href="https://github.com/perses/perses/pull/4268">#4268</a>).</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">frontend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  auto_refresh</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    disable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    options</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"0s"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"30s"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"1m"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"5m"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  default_user_preferences</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    timezone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">UTC</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    theme</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">dark</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    rows_per_page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">50</span></span></code></pre>
<h2 id="provisioning-improvements">Provisioning improvements</h2>
<ul>
<li>Perses can now watch the provisioning folders and apply the changes right away, instead of waiting for the next
interval (<a href="https://github.com/perses/perses/pull/4136">#4136</a>). Resources are also only updated when they actually
changed, which avoids unnecessary writes and ever-increasing versions.</li>
<li>A provisioning file can contain several resources separated by <code>---</code> (<a href="https://github.com/perses/perses/pull/4332">#4332</a>).</li>
</ul>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">provisioning</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  enable_watch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  folders</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">/etc/perses/provisioning</span></span></code></pre>
<h2 id="cli-improvements">CLI improvements</h2>
<ul>
<li>The new command <code>percli dac watch</code> rebuilds your Dashboard-as-Code files on every change, including the dashboards
depending on a modified library file (<a href="https://github.com/perses/perses/pull/3903">#3903</a>). Combined with the
provisioning watch mode, it gives you a live reload of your dashboards.</li>
<li><code>percli dac preview</code> supports the <code>--create-project</code> flag, like <code>percli apply</code>
(<a href="https://github.com/perses/perses/pull/4413">#4413</a>).</li>
</ul>
<h2 id="dashboard-and-plugin-schemas-api">Dashboard and plugin schemas API</h2>
<p>Perses now exposes the CUE schemas of the dashboards and of the installed plugins
(<a href="https://github.com/perses/perses/pull/4505">#4505</a>). It is particularly useful for tools generating dashboards, like
the <a href="https://github.com/perses/mcp-server">Perses MCP server</a>:</p>
<ul>
<li><code>GET /api/v1/schemas/dashboards</code>: the complete dashboard schema, including the plugin schemas.</li>
<li><code>GET /api/v1/schemas/plugins</code>: the schemas of all plugins.</li>
<li><code>GET /api/v1/schemas/plugins/&#x3C;plugin_name></code>: the schema of a single plugin, with the optional <code>version</code> and
<code>registry</code> query parameters.</li>
</ul>
<h2 id="datasource-improvements">Datasource improvements</h2>
<p>The datasource editor has a new <code>Test Connection</code> button to check the datasource is reachable before saving it
(<a href="https://github.com/perses/perses/pull/4396">#4396</a>, <a href="https://github.com/perses/shared/pull/99">perses/shared#99</a>).
It is available for Prometheus (<a href="https://github.com/perses/plugins/pull/620">perses/plugins#620</a>), OpenSearch
(<a href="https://github.com/perses/plugins/pull/797">perses/plugins#797</a>) and AlertManager
(<a href="https://github.com/perses/plugins/pull/798">perses/plugins#798</a>).</p>
<video controls>
  <source src="https://perses.dev/assets/images/blog/v055/test-connection.mp4" type="video/mp4">
  Your browser does not support the video tag.
</video>
<p>The Kubernetes datasource discovery can also mark a discovered datasource as the default one, based on its labels or
annotations (<a href="https://github.com/perses/perses/pull/4368">#4368</a>):</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">datasource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    discovery</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">prometheus</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        kubernetes_sd</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">          # ...</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">          default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">            enable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">            labels</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">              app.kubernetes.io/name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">prometheus</span></span></code></pre>
<h2 id="new-plugins">New plugins</h2>
<h3 id="canvas">Canvas</h3>
<p>The Canvas panel (<a href="https://github.com/perses/plugins/pull/729">perses/plugins#729</a>) is a free-form diagram editor to
build weathermap-like visualizations. Place nodes, connect them with edges and add background shapes or images. Nodes
and edges can be bound to a query: their color then follows thresholds and the edge thickness can scale with the value.</p>
<p><img src="https://perses.dev/assets/images/blog/v055/canvas.png" alt="Canvas weathermap"></p>
<h3 id="json">Json</h3>
<p>The new JSON datasource and query (<a href="https://github.com/perses/plugins/pull/770">perses/plugins#770</a>) can query any HTTP
endpoint returning JSON, with <code>GET</code> or <code>POST</code>, query parameters and variables. The response can be transformed with a
<a href="https://jsonata.org/">JSONata</a> expression, and the result displayed in a <code>Table</code> panel.</p>
<p><img src="https://perses.dev/assets/images/blog/v055/json-query.png" alt="JSON query"></p>
<h2 id="plugin-improvements">Plugin improvements</h2>
<ul>
<li><strong>TimeSeriesChart</strong>:
<ul>
<li>the color palette can be selected again (<a href="https://github.com/perses/plugins/pull/845">perses/plugins#845</a>). <code>Auto</code>
keeps the current color by series name, the categorical palettes give more distinct colors.</li>
<li>rendering is faster, especially with many series (<a href="https://github.com/perses/plugins/pull/832">perses/plugins#832</a>).</li>
</ul>
</li>
<li><strong>StatChart</strong>: multiple series are laid out in a grid adapting to the panel size, instead of a single row
(<a href="https://github.com/perses/plugins/pull/812">perses/plugins#812</a>, <a href="https://github.com/perses/plugins/pull/814">perses/plugins#814</a>).
Their values and legends also share the same font size, which can be customized (<a href="https://github.com/perses/plugins/pull/778">perses/plugins#778</a>).</li>
<li><strong>Table</strong>: sorting can be enabled for all columns at once (<a href="https://github.com/perses/plugins/pull/759">perses/plugins#759</a>),
and the new <code>PivotByLabel</code> transform turns series into a time × label matrix (<a href="https://github.com/perses/shared/pull/288">perses/shared#288</a>).</li>
<li><strong>BarChart</strong>: colors can be overridden with regexes on the series or bar names (<a href="https://github.com/perses/plugins/pull/774">perses/plugins#774</a>).</li>
<li><strong>PieChart</strong>: the inner and outer radius can be configured, e.g. to display a donut (<a href="https://github.com/perses/plugins/pull/823">perses/plugins#823</a>).</li>
<li><strong>Markdown</strong>: external links open in a new tab (<a href="https://github.com/perses/plugins/pull/815">perses/plugins#815</a>).</li>
<li><strong>Prometheus</strong>: a query can be executed as an instant query, regardless of the panel (<a href="https://github.com/perses/plugins/pull/752">perses/plugins#752</a>).</li>
<li><strong>Pyroscope</strong>: profiles are queried through the Connect API instead of the legacy <code>/render</code> endpoint
(<a href="https://github.com/perses/plugins/pull/763">perses/plugins#763</a>). The minimum step can be configured on the
datasource (<a href="https://github.com/perses/plugins/pull/810">perses/plugins#810</a>), and the profile types and labels
proposed are restricted to the selected service (<a href="https://github.com/perses/plugins/pull/820">perses/plugins#820</a>,
<a href="https://github.com/perses/plugins/pull/835">perses/plugins#835</a>).</li>
</ul>













<table><thead><tr><th>TimeSeriesChart color palette</th><th>StatChart grid layout</th></tr></thead><tbody><tr><td><img src="https://perses.dev/assets/images/blog/v055/palette.png" alt="TimeSeriesChart color palette"></td><td><img src="https://perses.dev/assets/images/blog/v055/statchart-layout.png" alt="StatChart grid layout"></td></tr></tbody></table>
<h2 id="other-improvements">Other improvements</h2>
<ul>
<li>
<p><strong>Duplicate a dashboard into another project</strong> (<a href="https://github.com/perses/perses/pull/4536">#4536</a>), including from
a project where you only have read access.</p>
<p><img src="https://perses.dev/assets/images/blog/v055/duplicate-dashboard.png" alt="Duplicate a dashboard into another project"></p>
</li>
<li>
<p><strong>Open in a new tab</strong>: the project and admin tabs, as well as the ephemeral dashboards, are now real links
(<a href="https://github.com/perses/perses/pull/4252">#4252</a>).</p>
</li>
<li>
<p><strong>Page title</strong>: the browser tab title now reflects the current page (<a href="https://github.com/perses/perses/pull/4489">#4489</a>).</p>
</li>
<li>
<p><strong>Collapsed panel groups</strong> show the number of panels they contain (<a href="https://github.com/perses/shared/pull/309">perses/shared#309</a>).</p>
</li>
<li>
<p><strong>Custom unit label</strong>: a panel can display its own unit label (e.g. <code>trx/s</code>) while keeping the formatting of a
standard unit (<a href="https://github.com/perses/shared/pull/297">perses/shared#297</a>).</p>
</li>
<li>
<p><strong>Grafana migration</strong>: the default time range, the refresh interval and the timezone of the Grafana dashboard are kept
(<a href="https://github.com/perses/perses/pull/4555">#4555</a>). Table thresholds are migrated to cell settings
(<a href="https://github.com/perses/plugins/pull/808">perses/plugins#808</a>), and datasource variables for Jaeger and
OpenSearch are supported (<a href="https://github.com/perses/plugins/pull/769">perses/plugins#769</a>).</p>
</li>
<li>
<p><strong>Compressed requests</strong>: the API accepts request bodies compressed with gzip (<code>Content-Encoding: gzip</code>)
(<a href="https://github.com/perses/perses/pull/4381">#4381</a>).</p>
</li>
<li>
<p><strong>Custom fetch</strong>: apps embedding Perses can override the <code>fetch</code> used by the client and the datasources through a
fetch provider, e.g. to add custom headers (<a href="https://github.com/perses/shared/pull/214">perses/shared#214</a>,
<a href="https://github.com/perses/shared/pull/316">perses/shared#316</a>, <a href="https://github.com/perses/plugins/pull/854">perses/plugins#854</a>).</p>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Release v0.54.0</title>
      <link>https://perses.dev/blog/2026/07/29/release-v0540/</link>
      <guid isPermaLink="true">https://perses.dev/blog/2026/07/29/release-v0540/</guid>
      <pubDate>Wed, 29 Jul 2026 00:00:00 GMT</pubDate>
      <category>Release notes</category>
      <description>Welcome in the v0.54.0 release !</description>
      <content:encoded><![CDATA[
<p>Welcome in the v0.54.0 release !</p>
<p>First of all this release includes several security fixes that patches some breach in the permission system included in
Perses, so we strongly recommend to upgrade to this version as soon as possible.</p>
<p>Then, you will be happy to know that this release includes new plugins: Jaeger, GreptimeDB, Splunk, LogExplorer,
AlertManager and OpenSearch.</p>
<p>As adding more plugins is increasing the size of the container image, likely we will remove some of them in future
release. It does not mean we will remove the support for these plugins, it is just we won't include them into the
default image. You will have to add them manually. The drop will occur once we are able to provide a good way to add
plugins to an existing installation without having to rebuild the image. In the meantime, if you don't want to use these
plugins, you can choose to enable or disable them by configuration.</p>
<p>We are also happy to announce it includes the long awaited sub-folder system to better organize your dashboards and
improve the accessibility by adding keyboard shortcuts.</p>
<p>This release is also the last release for the package <code>@perses-dev/core</code> that is now deprecated. For that we are
introducing two new packages <code>@perses-dev/spec</code> and <code>@perses-dev/client</code>.</p>
<ul>
<li><code>@perses-dev/spec</code> contains the dashboard and datasource specifications.</li>
<li><code>@perses-dev/client</code> contains the client to interact with the Perses API.</li>
</ul>
<p>The code from <code>@perses-dev/core</code> has been dispatched in these these two packages and in others (like
<code>@perses-dev/plugin-system</code> and <code>@perses-dev/components</code>) to better separate the concerns and make it easier to
maintain.</p>
<p>Finally, thank you to all the contributors who made this release possible, you are more and more, and we are really
happy to see the community growing and contributing to make Perses better and better!</p>
<p>As usual, this blog post does not cover all the changes and improvements included in this release. We are only talking
about the changes that should interest you the most. If you want to have a complete list of all the changes, please
refer to the <a href="https://github.com/perses/perses/releases/tag/v0.54.0">changelog</a></p>
<!-- more -->
<h2 id="security-issues">Security issues</h2>
<p>On top of the various features and improvements, we have fixed several security issues in this release that compromised
the permission system of the Perses application. We strongly recommend to upgrade to this version as soon as possible.</p>
<h3 id="use-query-parameter-project-to-list-resources-without-having-access-to-cve-2026-63458">Use query parameter project to list resources without having access to (<a href="https://github.com/perses/perses/security/advisories/GHSA-cjgj-2fwf-4c2w">CVE-2026-63458</a>)</h3>
<p>In previous versions, it was possible to list resources (dashboards, datasources, etc.) that you don't have access to by
using the query parameter <code>project</code> in the API.</p>
<p>For example, if you have access to the project <code>project-a</code> but not to <code>project-b</code>, you could list all dashboards in
<code>project-b</code> by calling the API endpoint <code>/api/v1/dashboards?project=project-b</code>. This would return a list of dashboards
in <code>project-b</code> even if you don't have access to that project.</p>
<p>Now, if you try to list resources that you don't have access to, you will get a 403 Forbidden error.</p>
<h3 id="unvalidated-project-parameter-enables-filesystem-path-traversal-cve-2026-63445">Unvalidated project parameter enables filesystem path traversal (<a href="https://github.com/perses/perses/security/advisories/GHSA-vr5f-w35q-98jp">CVE-2026-63445</a>)</h3>
<p>In previous versions, it was possible to use the <code>project</code> query parameter to access files outside the Perses
installation directory. This could be exploited by an attacker to read sensitive files on the server.</p>
<p>It was also possible to use this query parameter to get access to other resources contained in the database by using a
project name that contains a path traversal sequence (e.g. <code>../secrets</code>).</p>
<p>For example <code>/api/v1/dashboards?project=../projects</code> returns the list of the project while it must not return anything.</p>
<p>Now, if you try to use a project name that contains a path traversal sequence, you will get a 400 Bad Request error.</p>
<p>Note that this attack is not possible if you are using an SQL database instead of the default fileSystem database.</p>
<h3 id="missing-authorization-in-datasource-proxy-allows-cross-scope-secret-disclosure-cve-2026-63199">Missing authorization in datasource proxy allows cross-scope secret disclosure (<a href="https://github.com/perses/perses/security/advisories/GHSA-4227-9989-jrhx">CVE-2026-63199</a>)</h3>
<p>In previous versions, it was possible to contact datasources protected by secrets that you don't necessary have access
to by using the datasource proxy.</p>
<p>This was because the datasource proxy did not check if you have access to the secret used to connect to the datasource
while testing the connection to the same datasource.</p>
<p>Now, if you are creating a datasource or testing a connection to a datasource, the datasource proxy will check if you
have access to the secret used to connect to the datasource. If you don't have access to the secret, you will get a 403
Forbidden error.</p>
<h2 id="introduction-of-the-perses-specification">Introduction of the Perses specification</h2>
<p>We have created a new repository called <a href="https://github.com/perses/spec">perses/spec</a> that contains the Dashboard and
Datasource specifications in different languages (Go, TypeScript, Cuelang).</p>
<p>The goal of this repository is to provide a single source of truth for the specifications and make it easier for
developers to work with them in different programming languages, independently of the Perses project.</p>
<p>The specifications are now used in the Perses app, the Go and CUE SDKs, and the CLI. This means that if you use the SDKs
and/or the CLI, you will need to update your code to use the new specifications and upgrade the CLI to v0.54.0.</p>
<h2 id="package-perses-devcore-deprecation">Package <code>@perses-dev/core</code> deprecation</h2>
<p>As part of the introduction of the Perses specification, we are deprecating the package <code>@perses-dev/core</code>. We have
created a final version of this package that is compatible with the new specifications and will be available in the npm
registry. However, we recommend migrating your code to use the new specifications instead of using this package.</p>
<p>Also, if you are using the <code>@perses-dev/core</code> package in your code, you may be using more than just the specifications.
In this case, you will also need to update your imports to use the new <code>@perses-dev/client</code> package.</p>
<p>Please read the <a href="https://perses.dev/docs/perses/latest/upgrade/v0.54.0/">migration guide</a> for more details about how to migrate
your code to use the new specifications and the new package.</p>
<h2 id="enable-or-disable-plugins-through-configuration">Enable or disable plugins through configuration</h2>
<p>As we are adding more and more plugins to Perses, we have introduced a new configuration option to enable or disable
plugins. This gives users more fine-grained control over which plugins are available in their Perses instance and
reduces noise and issues caused by unused plugins.</p>
<p>For example, with the following configuration:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">plugin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  disabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"pyroscope"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"victoriaLogs"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"clickHouse"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"tempo"</span></span></code></pre>
<p>Prometheus will be the only datasource enabled in the default Perses installation.</p>
<p>Another way to achieve the same result is to explicitly enable only the plugins you want to use:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">plugin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  enabled</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"prometheus"</span></span></code></pre>
<p>In this example, only the Prometheus plugin will be enabled and all other plugins will be disabled.</p>
<p>Note that, a consequence of this configuration is that every panels, variables and queries are also disabled.</p>
<p>This also means that if you add a new plugin in the future, it will be disabled by default, and you will need to
explicitly enable it in the configuration.</p>
<h2 id="annotations">Annotations</h2>
<p>Perses now supports annotations, which add information such as events to panels.</p>
<p>Panels must support annotations; for now, only the TimeSeries Chart panel does. In addition, only annotations based on
Prometheus PromQL are supported. However, thanks to the Perses plugin architecture, support for annotations can easily
be added to any datasource (as source of data) or panel (for the display).</p>
<p><img src="https://perses.dev/assets/images/blog/v054/annotation-editor.png" alt="TimeSeries Chart Editor">
<img src="https://perses.dev/assets/images/blog/v054/annotations.png" alt="TimeSeries Chart Annotation"></p>
<h2 id="keyboard-shortcuts">Keyboard shortcuts</h2>
<p>Perses v0.54.0 introduces built-in keyboard shortcuts to help you navigate and operate dashboards faster without having
to using a mouse. Press <code>?</code> anywhere in the UI to open the shortcuts help modal, which lists all available shortcuts
grouped by category.</p>
<p>Some highlights:</p>
<ul>
<li><strong><code>?</code></strong> — Open the keyboard shortcuts help modal</li>
<li><strong><code>Ctrl</code>/<code>⌘</code> + <code>K</code></strong> — Open the search dialog</li>
<li><strong><code>G</code> + <code>H</code></strong> — Go to the Home page</li>
<li><strong><code>Ctrl</code>/<code>⌘</code> + <code>S</code></strong> — Save the current dashboard</li>
<li><strong><code>D</code> + <code>M</code></strong> — Toggle between edit and view mode</li>
<li><strong><code>E</code></strong> — Edit the focused panel (in edit mode)</li>
<li><strong><code>V</code></strong> — Toggle fullscreen on the focused panel</li>
</ul>
<p><img src="https://perses.dev/assets/images/blog/v054/keyboard-shortcuts.gif" alt="Keyboard shortcuts in action"></p>
<p>Keyboard shortcuts are enabled by default. To disable them, set the following in your Perses configuration:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">frontend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  enable_keyboard_shortcuts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span></span></code></pre>
<h2 id="sub-folder-support">Sub-folder support</h2>
<p>Perses now supports folders — a way to organise dashboards within a project using a tree structure. A folder's
<code>spec.items</code> can contain both dashboard references and nested subfolders, allowing you to mirror how your teams
structure their observability content.</p>
<p><img src="https://perses.dev/assets/images/blog/v054/subfolder-tree-view.png" alt="Sub-folder tree view"></p>
<p>The project's dashboard list displays dashboards in a tree view, where you can browse, create, edit, and delete folders
and subfolders. The same operations are available through the API and CLI (<code>percli apply</code>, <code>percli get folder</code>, etc.).</p>
<p>For example, the <code>demos</code> folder visible in the screenshot above is defined as:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-json"><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "kind"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Folder"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "metadata"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"demos"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "project"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"perses"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  },</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  "spec"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    "items"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "kind"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Dashboard"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"demo"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "kind"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Dashboard"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"benchmark"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "kind"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Folder"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"infrastructure"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        "items"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          {</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            "kind"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Dashboard"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">            "name"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"nodeexporter"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        ]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ]</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<h2 id="new-plugins">New plugins</h2>
<h3 id="opensearch">OpenSearch</h3>
<p>This version of Perses now ships a bundled OpenSearch datasource along with a LogQuery plugin. Users can now query and
view their logs directly in a Perses dashboard, right next to the other panels with metrics and traces.</p>
<p>Connecting to an existing OpenSearch cluster is easy, using either a proxy or a direct connection. The recommended setup
routes requests through the Perses backend proxy: the browser talks to Perses and Perses talks to OpenSearch, so any
credentials stay server-side and you don't need to enable CORS on your cluster. A direct connection is also available
for local experimentation.</p>
<p><img src="https://perses.dev/assets/images/blog/v054/opensearch-datasource.png" alt="OpenSearch datasource configuration"></p>
<p>Logs are queried
with <a href="https://opensearch.org/docs/latest/search-plugins/sql/ppl/index/">PPL (Piped Processing Language)</a>. You add a
<strong>Logs Table</strong> panel, pick the <strong>OpenSearch Log Query</strong> query type, point it at an index pattern, and write a PPL
query — for example, showing the most recent <code>ERROR</code> lines from a service.</p>
<p><img src="https://perses.dev/assets/images/blog/v054/recent-logs.png" alt="OpenSearch Log Query panel editor"></p>
<p>Results are rendered as log entries, with every other column in the row kept as a label so you can filter and display
fields like <code>service.name</code>, <code>severityText</code>, or <code>traceId</code>. You can drop several log panels on a single dashboard. For
instance, a broad "Recent Logs" view alongside a filtered "Error Logs" one.</p>
<p><img src="https://perses.dev/assets/images/blog/v054/log-dashboard.png" alt="OpenSearch log panels on a dashboard"></p>
<p>A couple of things happen automatically to make this feel native. Queries are bound to the dashboard's current time
range. The plugin injects a timestamp filter for you, so the logs follow the time picker (you can turn this off per
query). And because OpenSearch indices are schema-flexible, the plugin auto-detects the timestamp and message fields
from common names, with per-query overrides when your index uses different ones. Since <code>traceId</code> is just another field,
you can even setup an OpenSearch logs panel next to a Tempo or Jaeger trace panel on the same dashboard and pivot from a
trace straight to the logs it produced.</p>
<h3 id="jaeger">Jaeger</h3>
<p>This release adds support for Jaeger. With this integration, you can run trace queries against Jaeger from Perses dashboards or explorer.</p>
<p><img src="https://perses.dev/assets/images/blog/v054/jaeger.png" alt="Jaeger Dashboard"></p>
<h3 id="greptimedb">GreptimeDB</h3>
<p>This release adds support for GreptimeDB as a datasource in Perses.</p>
<blockquote>
<p>GreptimeDB is an open-source observability database built for Observability 2.0 — treating metrics, logs, and traces
as one unified data model (wide events) instead of three separate pillars.</p>
</blockquote>
<p>With this integration, you can run log, trace, and time series queries against GreptimeDB directly from Perses
dashboards.</p>
<p>The images below show a dashboard example and the corresponding query editors.</p>
<p><img src="https://perses.dev/assets/images/blog/v054/greptimedb_dashboard.png" alt="GreptimeDB Dashboard"></p>













<table><thead><tr><th>GreptimeDB Log Query</th><th>GreptimeDB Time Series Query</th></tr></thead><tbody><tr><td><img src="https://perses.dev/assets/images/blog/v054/greptimedb_logquery.png" alt="GreptimeDB Log Query"></td><td><img src="https://perses.dev/assets/images/blog/v054/greptimedb_tsquery.png" alt="GreptimeDB Time Series Query"></td></tr></tbody></table>
<h3 id="splunk">Splunk</h3>
<p>Perses now supports Splunk as a datasource, bringing Splunk's search capabilities directly into your Perses dashboards.</p>
<p>The Splunk plugin lets you connect to Splunk Enterprise or Splunk Cloud and query data using SPL (Splunk Processing
Language) — the same query language you already use in Splunk. Once connected, you can visualize results as time series
charts or explore raw log data, all within the Perses UI.</p>
<ul>
<li>Time Series Queries - Run SPL queries (e.g., timechart) and render results in Perses panel that accepts time series data.</li>
<li>Log Queries - Retrieve and display log results from Splunk indexes directly in a logs panel.</li>
</ul>













<table><thead><tr><th>TimeSeries</th><th>Logs</th></tr></thead><tbody><tr><td><img src="https://perses.dev/assets/images/blog/v054/Splunk-Time-Series.jpg" alt="Splunk Time Series"></td><td><img src="https://perses.dev/assets/images/blog/v054/Splunk-Log-Query.jpg" alt="Splunk Log Query"></td></tr></tbody></table>
<h3 id="alertmanager">Alertmanager</h3>
<p>Perses now supports <a href="https://prometheus.io/docs/alerting/latest/alertmanager/">Alertmanager</a> as a datasource. This
allows you to visualize and manage alerts and silences directly from a Perses dashboard.</p>
<ul>
<li>The new Alert Table allows you to view, search, group, filter and silence alerts. It also allows to confgure custom
columns and label coloring, as many alert queries can be included for a single table it also supports deduplication.</li>
<li>The new Silence Table allows you to view, search and expire silences. It also allows to configure its columns.</li>
</ul>













<table><thead><tr><th>Alerts</th><th>Silences</th></tr></thead><tbody><tr><td><img src="https://perses.dev/assets/images/blog/v054/alerts-table.png" alt="Alerts Table"></td><td><img src="https://perses.dev/assets/images/blog/v054/silences-table.png" alt="Silences Table"></td></tr></tbody></table>
<h3 id="log-explorer">Log Explorer</h3>
<p>Perses has been extended with a generic Log Explorer. This allows you to visualize and explore logs from any datasource
that supports logs, such as Loki, VictoriaMetrics, ClickHouse, GreptimeDB, etc.</p>
<p><img src="https://perses.dev/assets/images/blog/v054/logexplorer.png" alt="Log Explorer"></p>
<p>This is a really great addition to Perses, as it will avoid the need to implement an explorer for each datasources
supporting logs.</p>
<p>We are thinking about doing the same for traces in the future, but we are still evaluating the best approach to do so.</p>]]></content:encoded>
    </item>
    <item>
      <title>Release v0.53.0</title>
      <link>https://perses.dev/blog/2026/01/31/release-v0530/</link>
      <guid isPermaLink="true">https://perses.dev/blog/2026/01/31/release-v0530/</guid>
      <pubDate>Sat, 31 Jan 2026 00:00:00 GMT</pubDate>
      <category>Release notes</category>
      <description>Welcome to Perses v0.53.0! In this release, on top of many improvements and bug fixes, we have introduced several changes that break the compatibility with previous versions.</description>
      <content:encoded><![CDATA[
<p>Welcome to Perses v0.53.0! In this release, on top of many improvements and bug fixes, we have introduced several
changes that break the compatibility with previous versions.</p>
<p>These changes have been thinking carefully to improve the overall user experience and maintainability of Perses. We hope
even if it will make the upgrade process a bit more complex, you will stay with us and enjoy the benefits of these
improvements.</p>
<p>While you can read this blog post to have details about the changes and how to upgrade, we are also providing a
<a href="https://perses.dev/docs/perses/latest/upgrade/v0.53.0/">migration guide</a> that is more condensed and focused on the steps
required to upgrade from previous versions to v0.53.0.</p>
<p>On a different topic, we are happy to being able to list <a href="https://logz.io/">Logz.io</a> as a new officially company using
Perses in production. Welcome to the Perses community!</p>
<p>If you are a company using Perses or contributing to it and want to be listed as an adopter, please follow
the <a href="https://perses.dev/adopters/">guideline</a>. It is always great to see more and more companies trusting Perses for their
monitoring needs. And it will help us to grow the community and make Perses even better.</p>
<p>As usual, this blog post does not cover all the changes and improvements included in this release. We are only talking
about the changes that should interest you the most. If you want to have a complete list of all the changes, please
refer to the <a href="https://github.com/perses/perses/releases/tag/v0.53.0">changelog</a></p>
<!-- more -->
<h2 id="introduction-of-plugin-version-and-registry">Introduction of plugin version and registry</h2>
<p>To enhance the management of plugins specially when dealing with upgrading a plugin version that may introduce breaking
changes, we introduced a new field in the plugin specification called <code>metadata</code>. It includes a <code>version</code> field that
allows to specify the version of the plugin and the <code>registry</code> field that indicates the source registry of the plugin.</p>
<p>Now a plugin specification looks like this:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">kind</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">TimeSeriesChart</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">metadata</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  version</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">v0.1.0</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  registry</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">perses.dev</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">spec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># ... rest of the plugin spec</span></span></code></pre>
<p>Note that the version is following the semantic versioning format (semver) and this is enforced during the loading of
the plugin.</p>
<p>This change is important as it will allow in the future to manage multiple versions of the same plugin and facilitate
the migration from one version to another. We are planning to introduce automatic migration tools in future releases to
help users upgrade their plugins seamlessly. Excepting if a plugin is introducing breaking changes that cannot be
automatically handled, the upgrade process will be handled by the Perses backend using cuelang script contained in the
plugin package.</p>
<h3 id="what-does-it-change">What does it change?</h3>
<p>For <strong>end users</strong> using the Perses application, this change is transparent and does not require any action.</p>
<p>However, for <strong>plugin developers</strong>, you will need to update the CLI to the last version. This is required as the API
handling the load of the plugins in development has changed. Therefore, previous versions of the CLI won't be able to
send the data to the server to load plugin in development. The error returned by the server will be 405 (Method Not
Allowed). (see <a href="https://github.com/perses/perses/issues/3789">https://github.com/perses/perses/issues/3789</a>)</p>
<p>If you want to see the changes and more details regarding how it is implemented, they are available in this
PR: <a href="https://github.com/perses/perses/pull/3711">https://github.com/perses/perses/pull/3711</a></p>
<h2 id="tls-config-changes">TLS config changes</h2>
<p>We are introducing a breaking change in the TLS configuration to have a consistent syntax to define TLS settings across
all data-sources specifications and across all backend sub configurations.</p>
<p>The previous version was mixing two syntaxes to set TLS across the various possible configuration that could lead to
confusion (camelCase and snake_case).
This breaking change is impacting only the SQL database configuration.</p>
<p>In the SQL configuration, if the tls_config is used, then you should change your config like that:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-txt"><span class="line"><span>ca_file -> caFile</span></span>
<span class="line"><span>cert_file -> certFile</span></span>
<span class="line"><span>key_file -> keyFile</span></span>
<span class="line"><span>server_name -> serverName</span></span>
<span class="line"><span>insecure_skip_verify -> insecureSkipVerify</span></span>
<span class="line"><span>min_version -> minVersion</span></span>
<span class="line"><span>max_version -> maxVersion</span></span></code></pre>
<h2 id="user-used-in-the-container">User used in the container</h2>
<p>In order to simplify the build of the docker image, we have changed the default user used in the container from <code>nobody</code>
to <code>nonroot</code>. As a based image we are using now <code>gcr.io/distroless/static-debian12:non-root</code> instead of
<code>ggcr.io/distroless/static-debian12:latest</code>, which gives us a non-root user by default.</p>
<h3 id="what-does-it-change_1">What does it change?</h3>
<p>This change can impact users that is using as a database the file system inside the container, specially when running
the container with docker (not within Kubernetes). In that case, you should ensure that the <code>nonroot</code> user has the right
permissions to read and write into the database folder. If this is not the case, when upgrading the image, you will face
permission errors when Perses is trying to load the data coming from the file system.</p>
<h2 id="authentication-changes">Authentication changes</h2>
<p>A new <strong>OIDC logout endpoint</strong> has been added to the API, allowing users to log out both from Perses and from their OIDC
provider, respecting
the <a href="https://openid.net/specs/openid-connect-rpinitiated-1_0.html">OpenID Connect RP-Initiated Logout 1.0</a>
specification.
This is mainly used by the frontend to ensure a proper provider-side logout when a user signs out.<br>
The feature is currently in <strong>beta</strong> and <strong>disabled by default</strong>. It has been successfully tested with <strong>Azure AD</strong>
and <strong>Keycloak</strong>, so feel free to try it out.</p>
<p>We also introduced several improvements to the generic <strong>OIDC/OAuth2</strong> provider system:</p>
<ul>
<li>The <code>apiPrefix</code> configuration is now correctly applied during login redirections.</li>
<li>The OAuth2/OIDC <code>state</code> parameter is now more secure, enabling compatibility with providers such as <strong>Authelia</strong>.</li>
</ul>
<h2 id="improving-run-query-button-behavior-in-multiqueryeditor">Improving "Run Query" button behavior in MultiQueryEditor</h2>
<h3 id="what-does-it-change_2">What does it change?</h3>
<p>If you are developing plugin specially query plugin or embedding MultiQueryEditor in your app, these changes will impact
you,
and you need to follow these guidelines.</p>
<p><code>MultiQueryEditor</code> component has a new mandatory method: <code>onQueryRun</code>. It will be called when the user click on the
button "Run Query". It's useful if you want to execute a query only when this button is clicked and not on every
<code>onChange</code> (previous Perses behavior). Now the <code>onChange</code> method is always called when something change in the editor.
On the Perses app, queries are only executed when the user click on the "Run Query" button, however changes are still
saved
if user save the dashboard without clicking on "Run Query". But embedded use-cases might want to execute queries on
every change,
so this new behavior allows both use-cases.</p>
<p>In parallel, the caching of queries has been greatly improved to avoid memory leaks on dashboard refresh. More info can
be found in related PR: <a href="https://github.com/perses/perses/pull/3518">#3518</a>
And queries errors are now displayed at the query level (before it was only displayed at the panel level, could be hard
to know which queries are causing issues).</p>
<p>About the breaking change, your code should change from this:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-tsx"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> FooExplorer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ReactElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">        data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">queries</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []},</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        setData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> useExplorerManagerContext</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FooExplorerQueryParams</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Stack</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> gap</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">} </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sx</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{{width: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'100%'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}}></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            &#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">MultiQueryEditor</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                queryTypes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'ProfileQuery'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                queries</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{queries}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                onChange</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">newQueries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({queries: queryDefinitions})}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            /></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            &#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">FooPanel</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> queries</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{queries}/></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Stack</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>to this:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-tsx"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> FooExplorer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ReactElement</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">        data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">queries</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []},</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">        setData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> useExplorerManagerContext</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FooExplorerQueryParams</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">queryDefinitions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">setQueryDefinitions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> useState</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">QueryDefinition</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]>(queries);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Stack</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> gap</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">} </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sx</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{{width: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'100%'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}}></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            &#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">MultiQueryEditor</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                queryTypes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">'ProfileQuery'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                queries</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{queryDefinitions}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                onChange</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">newQueries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setQueryDefinitions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(newQueries)}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">                onQueryRun</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">({queries: queryDefinitions})}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            /></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            &#x3C;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">FooPanel</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> queries</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{queries}/></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        &#x3C;/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Stack</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<h2 id="variable-migration-changes">Variable migration changes</h2>
<p>We realized variable migration script could be simplified &#x26; better follow CUE's good practices by replacing condition
blocks by constraints defined on the variable object. However to enable this we had to introduce a breaking change*:
where previously such schema was describing the remapping of a Grafana variable object named <code>#var</code>, it is now called
<code>#grafanaVar</code>. Thus, if you had defined a schema looking like this:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-cue"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">package</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> migrate</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "strings"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#var: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> #var.type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "custom"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> #var.type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "interval"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    kind: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"MyVariable"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    spec: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        values: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">strings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Split</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(#var.query, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">","</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>..the minimum change you need to do is this renaming:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-cue"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">package</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> migrate</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "strings"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#grafanaVar: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> #grafanaVar.type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "custom"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> #grafanaVar.type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "interval"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    kind: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"MyVariable"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    spec: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        values: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">strings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Split</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(#grafanaVar.query, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">","</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>Then it is recommended to refactor to something like this:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-cue"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">package</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> migrate</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "strings"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">#grafanaVar: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"custom"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "interval"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    query: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">string</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ...</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">kind: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"MyVariable"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">spec: {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    values: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">strings</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">Split</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(#grafanaVar.query, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">","</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>*We believe the trade‑off was worth introducing this breaking change, as we expect very few (if any) people to have
written such variable migration schemas outside of the Perses organization. However, if you are impacted, please reach
out to us! Learning more about our community helps us make better future decisions by having a clearer understanding of
potential impacts.</p>
<h2 id="introducing-i18n-support">Introducing i18n support</h2>
<p>This new version is introducing internationalization (i18n) support in the frontend, allowing to easily add new
languages and provide a better experience for non-English speaking users. The i18n implementation is based on the widely
used <code>react-i18next</code> library, which provides a powerful and flexible solution for managing translations in React
applications.</p>
<p>For the moment, the il8n is really limited as it only contains a few translations for few languages. The main goal of
this change is mainly to get the i18n support in place and have a framework to easily add new translations in the
future.</p>
<h2 id="kubernetes-auth">Kubernetes Auth</h2>
<p>This release introduces Kubernetes authentication and authorization providers, enables authorization decisions for users
based on Kubernetes RBAC checks against Perses CRDs. This change marks a forward step in Perses Kubernetes integration
story, allowing Perses CRDs to not just create resources but be used in conjunction with Kubernetes <code>Roles</code> and
<code>RoleBindings</code> to provide access checks for users within Perses itself. Due to the variety of authentication providers
for Kubernetes, the implementation is designed to be provider agnostic. When enabled, Perses expects requests to contain
an <code>Authorization</code> header in the form of <code>Authorization: Bearer XXXX</code>. The token is used to authenticate against the
Kubernetes API Server and check if the user has permission to requested namespaces and resources.</p>
<p>The concept of authorization providers has been added with this change, marking the
<code>.security.authorization.guest_permissions</code> and <code>.security.authorization.check_latest_update_interval</code> fields as
deprecated, moving them to the "native" authorization provider. These fields will be removed in a future release.</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">security</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  authorization</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    provider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      native</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        enable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        check_latest_update_interval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">5m</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        guest_permissions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        # ...</span></span></code></pre>
<p>The frontend and percli have been updated to support these new providers. An <code>/api/v1/user/whoami</code> endpoint has been
created to return user information for a logged in user. The percli has had <code>--kube</code> and <code>--kubeconfig-file</code> flags added
which use the bearer token present in a kubeconfig file to authenticate with the Perses backend.</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-sh"><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">percli</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> login</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --kube</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --kubeconfig-file=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"./kubeconfig"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> http://localhost:8080</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">successfully</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> logged</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> in</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> http://localhost:8080</span></span></code></pre>
<p>The Kubernetes authentication and authorization providers must be enabled together. When enabled, the Perses backend
will use its pod's service account to authenticate and authorize users. The service account should be given
<code>TokenReview</code> and <code>SubjectAccessReview</code> create and <code>Namespace</code> list permissions. The authenticator and authorizer
provider configurations are exposed as configuration options:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">security</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  enable_auth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  authorization</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    provider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      kubernetes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        enable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        qps</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">500</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        burst</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1000</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        authorizer_allow_ttl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">5m</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        authorizer_deny_ttl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">30s</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        authenticator_ttl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">2m</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  authentication</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    providers</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      kubernetes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">        enable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span></code></pre>
<h2 id="cli-improvements">CLI improvements</h2>
<ul>
<li><code>plugin test-schemas</code> has been improved to test that the actual migrated schemas are valid against the expected
schemas.</li>
<li><code>plugin start</code> is now able to discover the port used by rspack to serve the plugin in development mode, so you don't
need to provide it anymore.
<ul>
<li>There was also an issue when loading a plugin in development with no schema defined, it is now fixed.</li>
<li>When stoping the command, there was some orphan process left, it is now fixed.</li>
<li>As mentioned before, the CLI has been updated to be compatible with the new dev plugin API introduced in this
release.</li>
</ul>
</li>
<li><code>lint</code>: when you were using local plugin to validate the dashboards, it was mandatory to have the plugins extracted in
a folder. Now you can also provide the plugins as an archive like it is the case for the Perses server. The command
will extract the plugins before starting validating any data.</li>
</ul>
<h2 id="plugin-improvements">Plugin improvements</h2>
<p>// TODO list of improvements, ideally give major changes and improvements for each plugin.</p>
<h3 id="go-sdk-change-in-the-way-to-define-a-query-plugin">GO-SDK Change in the way to define a query plugin</h3>
<p>In the previous version of the GO-SDK, a query plugin was defined by using the Query builder. The issue with this
approach is that it was not possible to provide the high level query type as it was hardcoded in the query builder.</p>
<p>This was not a problem for the Perses app as we only have one query type until recently. It changed with the
introduction of the new query types:  "ProfileQuery", "LogQuery" and "TraceQuery". To support this new use-case, we had
to introduce a breaking change in the way to define a query plugin.</p>
<p>Now, instead of using the Query builder, you need to fill a struct <code>query.Option</code> that contains the query plugin and the
high level query type.</p>
<p>If we take the Prometheus plugin as an example, the implementation will change from this:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-go"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">package</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> query</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">	"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">github.com/perses/perses/go-sdk/query</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">func</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> PromQL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">expr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">options</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> func</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">builder</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Builder</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		plugin, err </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(expr, options</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">		if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> err </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> nil</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">			return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> err</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		builder.Spec.Plugin.Kind </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PluginKind</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		builder.Spec.Plugin.Spec </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> plugin</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">		return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> nil</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span></code></pre>
<p>to this:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-go"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">package</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> query</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">	"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">github.com/perses/perses/go-sdk/query</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">	"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">github.com/perses/perses/pkg/model/api/v1/common</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span>
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">	"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">github.com/perses/perses/pkg/model/api/v1/plugin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">func</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> PromQL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">expr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">options</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ...</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	plg, err </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(expr, options</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> query</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		Kind: plugin.KindTimeSeriesQuery,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		Plugin: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">common</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Plugin</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			Kind: PluginKind,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			Spec: plg,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		Error: err,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span></code></pre>
<h3 id="support-of-temperature-units">Support of temperature units</h3>
<p>Celsius (°C) and Fahrenheit (°F) temperature units are now available for panel plugins that support unit configuration.</p>
<h3 id="introducing-victorialogs-and-clickhouse-as-new-data-sources">Introducing VictoriaLogs and ClickHouse as new data-sources</h3>
<p>On top of that, this release is also introducing two new data-sources: VictoriaLogs and ClickHouse provided directly by
the community.</p>
<p>// TODO: write more about these two data-sources, highlight their features, and who did it.</p>
<p>Note that since these two data-sources are provided by the community, they are not officially supported by the Perses
team.
And as such, soon we will come with a governance model to manage community plugins. In later release, these plugins
might be removed in the main images, depending on the governance adopted. You will still be able to use them by
installing the datasources in your Perses instance.</p>]]></content:encoded>
    </item>
    <item>
      <title>Release v0.52.0</title>
      <link>https://perses.dev/blog/2025/09/15/release-v0520/</link>
      <guid isPermaLink="true">https://perses.dev/blog/2025/09/15/release-v0520/</guid>
      <pubDate>Mon, 15 Sep 2025 00:00:00 GMT</pubDate>
      <category>Release notes</category>
      <description>The release of Perses v0.52.0 introduces significant new features and improvements.</description>
      <content:encoded><![CDATA[
<p>The release of Perses v0.52.0 introduces significant new features and improvements.</p>
<p>This update expands Perses' observability capabilities by introducing support for logging and continuous profiling,
along with new plugins for Pyroscope, Flame Chart, Loki, and log visualization.</p>
<p>Additional enhancements include a heatmap panel for Prometheus histograms, a quick query viewer, panel group variable repeat,
usability improvements, and upgraded CLI commands to streamline plugin development and schema testing.</p>
<!-- more -->
<h2 id="new-profiling-plugins">New profiling plugins</h2>
<p>This release provides the support of Continuous Profiling through two plugins:</p>
<ul>
<li><strong>Pyroscope</strong>: a datasource plugin for retrieving and handling data from a Pyroscope server.</li>
<li><strong>Flame Chart</strong>: a visualization plugin which contains 3 panels: Flame Graph, Table View and Series Chart.</li>
</ul>
<h3 id="what-is-continuous-profiling">What is Continuous Profiling?</h3>
<p>Continuous Profiling is a new observability signal, complementing the traditional logs, metrics, and traces. This
innovative approach provides a way of continuously measuring applications' resource consumption with code-level
granularity and low overhead. This signal generates excitement in the community for its ability to provide in-depth
visibility into production performance of applications.</p>
<h3 id="panels">Panels</h3>
<h4 id="flame-graph">Flame Graph</h4>
<p>The flame graph panel offers a simple and intuitive way to represent performance data, providing a hierarchical view
that let you zoom in on any stack for a detailed analysis. It helps to understand resource allocations (CPU,
Memory, ...) and bottlenecks within an application.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/flame-graph-panel.png" alt="Flame Graph Panel"></p>
<h4 id="table-view">Table View</h4>
<p>This panel displays the profile in a table format. It allows you to sort stacks, for example in descending order, to see
which function consume the most resources. A search bar is also present for filtering the table and highlighting stacks
in the flame graph.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/table-view-panel.png" alt="Table View Panel"></p>
<h4 id="series-chart">Series Chart</h4>
<p>When retrieving profiles from the Pyroscope server, they include timeline data showing how the total amount of resources
consumed evolves over time, depending on the selected profile type. This panel allows you to visualize this data in
order to identify spikes in resource consumption (CPU, memory, etc.) and focus on them by zooming into the corresponding
time range.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/series-chart-panel.png" alt="Series Chart Panel"></p>
<h2 id="new-logs-plugins">New Logs plugins</h2>
<p>This release introduces two new plugins enabling log visualization and exploration in Perses:</p>
<ul>
<li><strong>Loki</strong>: a datasource plugin for retrieving and handling data from a Loki server.</li>
<li><strong>Logs Panel</strong>: a visualization plugin for displaying and exploring logs.</li>
</ul>
<p><img src="https://perses.dev/assets/images/blog/v052/logtable-panel.jpg" alt="LogTable Panel"></p>
<p>These new plugins have been developed by the Perses community.
A big thank you to <a href="https://github.com/abelyakin">@abelyakin</a> !!</p>
<h2 id="heatmap">Heatmap</h2>
<p>As spoiled on the previous release note, the heatmap panel has been added on Perses!
It is now possible to visualize Prometheus native histograms in a heatmap format. This panel is particularly useful for
visualizing latency distributions over time.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/heatmap-dark.png" alt="Heatmap Panel">
<img src="https://perses.dev/assets/images/blog/v052/heatmap-light.png" alt="Heatmap Panel"></p>
<p>This panel still need to be improved, so stay tuned for future updates! Or even better, contribute to it! List of
improvements to be done can be found in the <a href="https://github.com/perses/perses/issues/2978">GitHub issue #2978</a></p>
<h2 id="quick-query-viewer">Quick Query Viewer</h2>
<p>Panels introduces a new feature called <code>Quick Query Viewer</code> using which users can quickly check the executed queries
without being in edit mode.
The feature has added a new, default icon button into the panel header. When clicked a modal is opened in which you can
see relevant query specs.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/quick_query_viewer.png" alt="Quick Query Review"></p>
<h2 id="panel-group-repeat">Panel group repeat</h2>
<p>Panel group now support variable repeat. This allows you to create a panel group and have it repeated for each value of
a variable.</p>
<p>You can define the repeat variable in the panel group settings dialog.
It will be also applied to preview in panel group.
When editing a panel inside a panel group with repeat, changes will be applied to all panels group repeated.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/panel-group-job.png" alt="Panel Group Repeat">
<img src="https://perses.dev/assets/images/blog/v052/markdown-panel-job.png" alt="Panel Group Repeat"></p>
<h2 id="user-profile">User profile</h2>
<p>We are introducing user profiles in Perses!</p>
<p>For the moment, the user profile page only contains the list of the permissions associated to the account used.
But it is the first step towards a more complete user profile page, which will include more functionalities in the
future.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/user-profile.png" alt="User Profile"></p>
<h2 id="discard-changes-prompt">Discard changes prompt</h2>
<p>When editing a dashboard, if you try to leave the page with unsaved changes, a prompt will appear to warn you about
potential lost changes.
There are 2 different prompts depending on how you try to leave the page:</p>
<ul>
<li>If you try to navigate to another page in Perses, a modal will appear to confirm you want to leave the page.</li>
<li>If you try to close the tab or navigate to another website, a browser native prompt will appear.</li>
</ul>
<p><img src="https://perses.dev/assets/images/blog/v052/discard-changes-prompt.png" alt="Discard Changes Prompt">
<img src="https://perses.dev/assets/images/blog/v052/discard-browser-prompt.png" alt="Discard Browser Prompt"></p>
<h2 id="explorer-improvements">Explorer improvements</h2>
<p>Explorer can now show more information about your resources, thanks to collapsable tab menu!</p>
<p><img src="https://perses.dev/assets/images/blog/v052/explorer-not-collapsed.png" alt="Explorer Not Collapsed">
<img src="https://perses.dev/assets/images/blog/v052/explorer-collapsed.png" alt="Explorer Not Collapsed"></p>
<p>Few other improvements have been made to the explorer, such as:</p>
<ul>
<li>Tabs are now sorted alphabetically</li>
<li>The metric finder datasource selector is rendered correctly</li>
<li>Metric finder filter inputs are now displayed in 3 parts: key, operator, value. Instead of a single input.</li>
</ul>
<h2 id="plugins-improvements">Plugins Improvements</h2>
<h3 id="traces">Traces</h3>
<h4 id="attribute-search">Attribute Search</h4>
<p>The Tempo plugin now allows you to search for traces by attributes directly in the query editor, without writing a
TraceQL query manually.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/tempo-filter-bar.png" alt="Attribute Search"></p>
<h4 id="span-links">Span Links</h4>
<p>You can now view span links in a new <strong>Links</strong> tab when clicking on a span which has links configured. This makes it
easier to explore related spans and understand trace relationships.</p>
<p><img src="https://perses.dev/assets/images/blog/v052/tracingganttchart-span-links.png" alt="Span Links"></p>
<h4 id="download-traces">Download Traces</h4>
<p>The TracingGanttChart panel now includes a download action in the panel header. With one click, you can export the
entire trace in OTLP/JSON format for offline analysis or sharing.</p>
<h4 id="linking-improvements">Linking Improvements</h4>
<p>The TracingGanttChart, TraceTable, and ScatterChart panels now support configuring links in the panel spec. You can
configure the link to a specific trace (e.g. relevant for the trace table) or create dynamic links from resource and
span attributes (in the TracingGanttChart panel).</p>
<h2 id="cli-improvements">CLI Improvements</h2>
<h3 id="new-command-percli-plugin-test-schema">New command <code>percli plugin test-schema</code></h3>
<p>This new command provides a way to test the Cuelang schema and the migration schema. Here how it works:</p>
<p>First, all tests files needs to be placed directly alongside the schema file to test, within a <code>tests</code> folder.
Then you will have different way to test the schemas:</p>
<p><strong>Tests validating the model</strong>:</p>
<ul>
<li>Validate that a JSON file is accepted by the plugin's CUE schema.</li>
<li>Place valid tests under "tests/valid/". "tests" is located next to the entrypoint of the "model" CUE package.</li>
<li>Each test is a JSON file containing a valid configuration expected to pass validation.</li>
</ul>
<p><strong>Tests verifying invalid possibility</strong>:</p>
<ul>
<li>Validate that a JSON file is rejected by the plugin's CUE schema.</li>
<li>Place invalid tests in "tests/invalid/". "tests" is located next to the entrypoint of the "model" CUE package.</li>
<li>Each test is a JSON file containing an invalid configuration expected to fail validation.</li>
</ul>
<p><strong>Migration Tests</strong>:</p>
<ul>
<li>Validate migration logic defined in the plugin's "migrate.cue" file.</li>
<li>Place migration tests under "migrate/tests/". "tests" is located next to "migrate.cue".</li>
<li>Each test is a directory containing:
<ul>
<li>"input.json": The source file (e.g., Grafana format).</li>
<li>"expected.json": The expected result after migration (Perses format).</li>
</ul>
</li>
<li>The migration test unifies the input with the migration schema and compares the result to the expected output.</li>
</ul>
<p>Example of file structure for a single plugin:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-tree"><span class="line"><span>schemas/</span></span>
<span class="line"><span>├── model.cue</span></span>
<span class="line"><span>├── tests/</span></span>
<span class="line"><span>│   ├── valid/</span></span>
<span class="line"><span>│   │   ├── basic-config.json</span></span>
<span class="line"><span>│   │   └── advanced-config.json</span></span>
<span class="line"><span>│   └── invalid/</span></span>
<span class="line"><span>│       ├── missing-required.json</span></span>
<span class="line"><span>│       └── invalid-type.json</span></span>
<span class="line"><span>└── migrate/</span></span>
<span class="line"><span>├── migrate.cue</span></span>
<span class="line"><span>└── tests/</span></span>
<span class="line"><span>├── basic-migration/</span></span>
<span class="line"><span>│   ├── input.json</span></span>
<span class="line"><span>│   └── expected.json</span></span>
<span class="line"><span>└── complex-migration/</span></span>
<span class="line"><span>├── input.json</span></span>
<span class="line"><span>└── expected.json</span></span></code></pre>
<p>More complex example for a package embedding several plugins:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-tree"><span class="line"><span>schemas/</span></span>
<span class="line"><span>├── my-datasource/</span></span>
<span class="line"><span>│   ├── model.cue</span></span>
<span class="line"><span>│   ├── tests/</span></span>
<span class="line"><span>│   │   ├── valid/</span></span>
<span class="line"><span>│   │   │   ├── basic-config.json</span></span>
<span class="line"><span>│   │   │   └── advanced-config.json</span></span>
<span class="line"><span>│   │   └── invalid/</span></span>
<span class="line"><span>│   │       ├── missing-required.json</span></span>
<span class="line"><span>│   │       └── invalid-type.json</span></span>
<span class="line"><span>│   └── migrate/</span></span>
<span class="line"><span>│       ├── migrate.cue</span></span>
<span class="line"><span>│       └── tests/</span></span>
<span class="line"><span>│           ├── basic-migration/</span></span>
<span class="line"><span>│           │   ├── input.json</span></span>
<span class="line"><span>│           │   └── expected.json</span></span>
<span class="line"><span>│           └── complex-migration/</span></span>
<span class="line"><span>│               ├── input.json</span></span>
<span class="line"><span>│               └── expected.json</span></span>
<span class="line"><span>└── my-query/</span></span>
<span class="line"><span>├── model.cue</span></span>
<span class="line"><span>├── tests/</span></span>
<span class="line"><span>│   ├── valid/</span></span>
<span class="line"><span>│   └── invalid/</span></span>
<span class="line"><span>└── migrate/</span></span>
<span class="line"><span>├── migrate.cue</span></span>
<span class="line"><span>└── tests/`,</span></span></code></pre>
<h3 id="improvement-of-the-command-percli-plugin-start">Improvement of the command <code>percli plugin start</code></h3>
<p>This command has been improved to provide a better experience when starting a plugin locally.</p>
<p>Note: all improvement described below will only work with a remote server of version >= 0.52.0 as it also included new
endpoints to make the features work.</p>
<ol>
<li>
<p>With this new version, the command is now able to detect any changes on the Cuelang schema.
When a change is detected, the command will trigger the remote server to reload the schema internally.
This improvement is particularly useful during the development of a plugin, as it allows to see the changes of the
schema immediately without having to manually restart the server and the plugin watching process.</p>
</li>
<li>
<p>When stopping the command, it will now unregister any plugin it was watching. This is useful to avoid having to
restart the remote server to get back the list of registered plugins clean. It also solve an issue about being able
to override a plugin with the development version of the same plugin.</p>
</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Introducing the Perses MCP Server</title>
      <link>https://perses.dev/blog/2025/06/18/introducing-the-perses-mcp-server/</link>
      <guid isPermaLink="true">https://perses.dev/blog/2025/06/18/introducing-the-perses-mcp-server/</guid>
      <pubDate>Wed, 18 Jun 2025 00:00:00 GMT</pubDate>
      <category>Community</category>
      <description>We&apos;re thrilled to introduce the Perses MCP Server, now available in public beta. This new tool empowers you to interact with your Perses instances using natural language, opening up a world of…</description>
      <content:encoded><![CDATA[
<p>We're thrilled to introduce the <strong>Perses MCP Server</strong>, now available in public beta. This new tool empowers you to interact with your Perses instances using natural language, opening up a world of possibilities for monitoring and visualization.</p>
<p>With the Perses MCP Server, users can use AI Agents to understand, query and interact with Perses APIs in a standardized and secure manner.</p>
<p>Imagine being able to prompt your favorite AI Agent with questions like:</p>
<ul>
<li>"How many dashboards are created in the last 5 days in project 'Test Project'?"</li>
<li>"What is the default datasource for project 'Test Project'?"
<ul>
<li>"Is this datasource in proxy mode? and what is the URL?"</li>
</ul>
</li>
<li>"Analyze this dashboard 'Dashboard A' in project 'Test Project'"
<ul>
<li>Suggest me some improvements to panels and PromQL queries in this dashboard</li>
</ul>
</li>
</ul>
<p>As you can see, the possibilities are endless. The Perses MCP Server allows you to interact with Perses in ways that were previously not possible.</p>
<!-- more -->
<picture>
  <img alt="Fallback image description" src="https://github.com/user-attachments/assets/416409df-9045-41f3-b10b-91df3020af1f">
</picture>
<p>This diagram visually represents how the Perses MCP Server acts as an intermediary between your AI Agent and the Perses Application.</p>
<h3 id="what-is-mcp-the-model-context-protocol-explained">What is MCP - The Model Context Protocol Explained</h3>
<p>You might be wondering what makes this all possible. The magic behind the scenes is the Model Context Protocol (MCP), an open standard pioneered by Anthropic that is quickly gaining industry-wide adoption.</p>
<p>MCP’s purpose is to create a universal language for AI agents to interact with the "outside world" that is, any data or system beyond their initial training data. This protocol enables AI to securely access real-time information and perform tasks by connecting to external APIs. In short, MCP provides a paved road for Large Language Models (LLMs) to interact with external systems like databases, APIs, and filesystems.</p>
<p>Major players like Google, Microsoft, and OpenAI have already committed to supporting MCP.</p>
<h3 id="how-to-use-the-perses-mcp-server">How to Use the Perses MCP Server</h3>
<p>Using the Perses MCP Server is simple and straightforward.</p>
<ol>
<li>Follow this <a href="https://github.com/perses/mcp-server/blob/main/README.md#usage">User Guide</a> to install and configure the MCP Server;</li>
<li><strong>Ask a Question</strong>: Pose a natural language question to your favorite AI agent, such as, "When was 'Dashboard A' in 'Project B' last updated?";</li>
<li><strong>Get an Answer</strong>: The MCP Server instantly gets to work, querying the Perses API and delivering the answer back to your AI agent in seconds.</li>
</ol>
<p>Check out this short demo to see it in action:</p>
<video controls>
  <source src="https://perses.dev/assets/images/blog/mcp-server/perses-mcp-server-demo.mp4" type="video/mp4">
  Your browser does not support the video tag.
</video>
<h3 id="getting-started-with-perses-mcp-server">Getting Started with Perses MCP Server</h3>
<p>Ready to dive in? Here are the resources you'll need:</p>
<ul>
<li><strong>Perses MCP Server GitHub Repository:</strong> Explore the code, read the documentation, and find the installation instructions <a href="https://github.com/perses/mcp-server">here</a>;</li>
<li><strong>Perses Official Website:</strong> Discover more about the Perses, its features, blog posts and documentation <a href="https://perses.dev/">here</a>.</li>
</ul>
<h3 id="whats-next">What's next?</h3>
<p>This public beta is just the beginning. Currently, the server supports read-only operations, allowing you to query the Perses API. Our roadmap includes adding write capabilities, which will enable you to use AI agents to create and update Perses resources like dashboards, projects, and datasources.</p>
<p>We are committed to an open development process and we welcome your feedback and contributions as we build these new features.</p>]]></content:encoded>
    </item>
    <item>
      <title>Composable Dashboards -  Lessons from building Perses Community Dashboards</title>
      <link>https://perses.dev/blog/2025/06/10/composable-dashboards----lessons-from-building-perses-community-dashboards/</link>
      <guid isPermaLink="true">https://perses.dev/blog/2025/06/10/composable-dashboards----lessons-from-building-perses-community-dashboards/</guid>
      <pubDate>Tue, 10 Jun 2025 00:00:00 GMT</pubDate>
      <category>Community</category>
      <description>Every CNCF User/Developer/Contributor has, at some point, to endure the frustration of trying to salvage an outdated dashboard, or adapting upstream YAML, only to get to the point of wondering why it…</description>
      <content:encoded><![CDATA[
<h2 id="why-we-keep-rewriting-the-same-dashboards">Why we keep rewriting the same dashboards</h2>
<p>Every CNCF User/Developer/Contributor has, at some point, to endure the frustration of trying to salvage an outdated dashboard, or adapting upstream YAML, only to get to the point of wondering why it doesn't work on their setup. This leads to a recurring pattern: everyone ends up rebuilding the same dashboards, over and over again, each slightly different.</p>
<p>The Mixins Dashboards helped bring about a sense of relief, as users now could use dashboards and alerts packaged together with the code they are deployed with. In theory, this promised consistency and easier integration. In practical terms, as the concept of mixins relies on Jsonnet, and even though it’s a suitable language for configuration management, it leads to a few issues:</p>
<ul>
<li>
<p>Jsonnet has a steep learning curve. It’s not a conventional Turing-complete programming language, and often makes it hard for downstream users of mixins to be able to do any sort of customization on their dashboards;</p>
</li>
<li>
<p>Mixin Jsonnet is completely detached from the actual application code. It was introduced as a way to maintain dashboarding config for code that you are deploying side by side, to ensure it never goes out of sync. However, many mixins are rarely updated, even when the code is - sometimes these are maintained out of the tree. And Jsonnet cannot use Go structs, so there is no automatic validation during code changes. Thus keeping mixins accurate and reliable demands a lot of effort.;</p>
</li>
<li>
<p>Adoption has also been uneven. A good example of this is kube-prometheus stack, built with Jsonnet, where many users bypass it entirely and only fetch the rendered YAML from that repository, then doing any sort of changes with tools like Kustomize instead. This undermines the original goal of reuse and standardization.</p>
</li>
</ul>
<p>The end result is, that despite the promise of reusable dashboards, the reality is there’s still not a widely used solution for automatic dashboards creation.</p>
<!-- more -->
<h2 id="perses-kubecon-eu-recap-maybe-theres-a-better-way-to-build-dashboards">Perses KubeCon EU Recap - Maybe there’s a better way to build Dashboards</h2>
<p>During <strong>KubeCon EU 2025</strong> in London, two of Perses’ core maintainers, Nicolas Takashi and Antoine Thébaud, shared how Perses is changing the way engineers develop and manage dashboards as code. Their talk covered the power of the Open Dashboard Model, how to use strongly typed code with the Perses Go SDK, and why this approach fits naturally into CI/CD pipelines using modern GitOps practices. If you didn’t get a chance to watch it live, you can watch the full session <a href="http://youtube.com/watch?v=7h70Olo5Uzk">here</a>.</p>
<p>They also mentioned the <strong>Community Dashboards</strong> Project, but didn’t have time to dive into it during the session. With that in mind is our belief that such an important topic deserves more space, and as so we bring this into live here.</p>
<h2 id="moving-away-from-rebuilding-the-same-dashboards-to-composable-dashboards">Moving away from rebuilding the same dashboards to composable dashboards</h2>
<p>With the limitations of mixins in mind, the Perses community decided to take a different path. Since Perses is written in Go, with both its configuration and plugins defined using Go structs, it presents an opportunity to design dashboards in a more efficient and structured way. This approach takes full advantage of the Go structs imported from Perses, with its robust SDK that has the methods and constructs to build dashboards. This then ensures consistency with the core project, safe versioning, both for the dashboard data model and each individual panel plugins, and type-safe dashboard construction and customization.</p>
<p>Introducing the <a href="https://github.com/perses/community-dashboards">community-dashboards</a> repository. Maintained by community contributors, it offers the following dashboards in type-safe modular Go SDK based Dashboards as Code:</p>
<p><img src="https://perses.dev/assets/images/blog/community-dashboards/perses-dashboards-overview.png" alt="Dashboard overview"></p>
<p>The goal of the community-dashboards library isn't just to provide ready-to-use YAML dashboards (though you can use them as-is), but to empower users to import the project as a Go module in their downstream configuration, generate tailored subsets of dashboards, and customize or extend them to meet specific needs (similar to what mixins originally intended).</p>
<p>A core strength of the Perses Community Dashboards is its modular, reusable panel library. These panels—such as Go CPU Usage and Memory Consumption—serve as building blocks that can be composed into new dashboards. Instead of starting from scratch, users can leverage these community-maintained components to quickly build dashboards suited to their applications and workloads.</p>
<p>This approach also lowers the barrier to achieving consistency across dashboards. By reusing the same patterns to build and display common metrics, dashboards remain aligned across teams and services. This makes it easier to compare environments, onboard new engineers, and scale observability practices—without reinventing the wheel.</p>
<p><img src="https://perses.dev/assets/images/blog/community-dashboards/perses-dashboards-am.png" alt="AM overview"></p>
<h2 id="how-to-build-composable-dashboards-a-practical-example">How to build composable dashboards - a practical example</h2>
<p>Here we have an example of how to define a panel of Time Series type below. More detailed info about the available option for Time Series Panels can be found <a href="https://pkg.go.dev/github.com/perses/plugins/timeserieschart">here</a> and <a href="https://pkg.go.dev/github.com/perses/promql-builder">PromQLBuilder</a>.</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-go"><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Define your panel</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">func</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CPUUsage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">datasourceName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">labelMatchers</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ...*</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">labels</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Matcher</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">panelgroup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> panelgroup.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddPanel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"CPU Usage"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		panel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Description</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Shows the CPU usage of the component."</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		timeSeriesPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Chart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			timeSeriesPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WithYAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">timeSeriesPanel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">YAxis</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				Format: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">commonSdk</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Format</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					Unit: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(commonSdk.DecimalUnit),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			}),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			timeSeriesPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WithLegend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">timeSeriesPanel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Legend</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				Position: timeSeriesPanel.BottomPosition,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				Mode:     timeSeriesPanel.TableMode,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				Values:   []</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">commonSdk</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calculation</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{commonSdk.LastCalculation},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			}),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			timeSeriesPanel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WithVisual</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">timeSeriesPanel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Visual</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				Display:      timeSeriesPanel.LineDisplay,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				ConnectNulls: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				LineWidth:    </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.25</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				AreaOpacity:  </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0.5</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				Palette:      </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">timeSeriesPanel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Palette</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{Mode: timeSeriesPanel.AutoMode},</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			}),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		panel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddQuery</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			query.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PromQL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				promql.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SetLabelMatchersV2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					promqlbuilder.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Rate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						matrix.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">New</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">							vector.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">New</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">								vector.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WithMetricName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"process_cpu_seconds_total"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">							),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">							matrix.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">WithRangeAsVariable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"$__rate_interval"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					labelMatchers,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Pretty</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				dashboards.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddQueryDataSource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(datasourceName),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				query.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SeriesNameFormat</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"{{pod}}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>Next after you have your first panel, it’s time to add it to a dashboard - here’s how to add to a dashboard named <code>Workload / Overview</code>:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-go"><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Use the panel in a dashboard</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">func</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> withResources</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">datasource</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">clusterLabelMatcher</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">labels</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Matcher</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">dashboard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	labelMatchersToUse </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> []</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">labels</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Matcher</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		promql.JobVarV2,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	labelMatchersToUse </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> append</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(labelMatchersToUse, clusterLabelMatcher)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dashboard.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddPanelGroup</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"CPU Usage"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		panelgroup.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PanelsPerLine</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		panelgroup.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PanelHeight</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		panelsGostats.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CPUUsage</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(datasource, labelMatchersToUse</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// Build the dashboard and add the time series panel withResources</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">func</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BuildWorkloadOverview</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">project</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">datasource</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">clusterLabelName</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">dashboards</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DashboardResult</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	clusterLabelMatcher </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dashboards.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">GetClusterLabelMatcherV2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(clusterLabelName)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">	return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> dashboards.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">NewDashboardResult</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		dashboard.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">New</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"workload-overview"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			dashboard.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">ProjectName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(project),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			dashboard.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Workload / Overview"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			dashboard.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddVariable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"job"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				listvariable.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					labelvalues.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">PrometheusLabelValues</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"job"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						labelvalues.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Matchers</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"workload_build_info{}"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">						dashboards.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">AddVariableDatasource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(datasource),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">					listvariable.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DisplayName</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"job"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">				),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">			),</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">			withResources</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(datasource, clusterLabelMatcher),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">		),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">	).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"workload"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>For more on the SDK please check <a href="https://pkg.go.dev/github.com/perses/perses/go-sdk">perses/go-sdk</a>, and <a href="https://pkg.go.dev/github.com/perses/community-dashboards">community-dashboards</a>.</p>
<h2 id="beyond-copy-pasting-cleaner-and-smarter-way-to-building-dashboards">Beyond Copy-Pasting - Cleaner and Smarter way to building Dashboards</h2>
<p>Going back to the idea of copy-pasting raw YAML or JSON, although it might seem quicker, it leads to painful maintenance over time. The Go SDK offers a better path:</p>
<ul>
<li><strong>Type safety</strong> - You get compile-time feedback if something is wrong. No more mystery errors buried in JSON blobs.</li>
<li><strong>Reusability</strong> - Define a panel once and reuse it wherever you want. Avoid duplication and drift.</li>
<li><strong>Maintainability</strong> -  When a panel definition needs an update, you can do it in one place and apply it across all dashboards.</li>
<li><strong>CI/CD friendly</strong> - Code is easier to version, review, and test. It fits naturally into modern GitOps workflows.</li>
</ul>
<p>Combining the use of panel libraries and the SDK, you get a flexible and scalable way to manage dashboards, while saving time, reducing errors, and staying consistent across your observability stack. This allows a community of dashboards users to have their lives made easier with these features.</p>
<p>Also considering the most commonly used dashboard across platforms and teams, like <strong>Kubernetes</strong>, <strong>Prometheus</strong> and exporters like <strong>Node Exporter</strong>, <strong>Blackbox Exporter</strong>, also projects like <strong>Thanos</strong> dashboards as it tends to be a power duo within the Prometheus ecosystem, we have from the get go some core dashboards that will help you in the long term in your observability journey.</p>
<h2 id="next-steps-for-the-community-dashboards">Next Steps for the Community Dashboards</h2>
<p>We’re committed to expanding support for more CNCF and other OSS projects while continuing to enhance the existing panel libraries. By adding more features and improving the quality of reusable panels, we enable users to gain deeper insights from their dashboards because the faster you can pinpoint an issue in your telemetry data, the better.</p>
<p>Also, we aim to ensure proper documentation for all dashboards. Whether you're importing full dashboards or using panel libraries as building blocks, we want to make the process as seamless as possible. That means clear, well-commented code and guidance, so modularity is not only guaranteed but also easy to work with, without needing to dig through the entire codebase.</p>
<p>Ultimately, this is a community effort, and we invite everyone to help grow this project. So if you have a dashboard you’ve rewritten more than once, or any mixin dashboard you use, but want to ensure it becomes modular, easily used and want to increase adoption of it. Whether it’s opening an issue or submitting a contribution, all help is moving forward so we can all, very soon, stop rebuilding the same dashboards.</p>
<p>Let’s stop duplicating efforts and start building shared observability standards!</p>]]></content:encoded>
    </item>
    <item>
      <title>Release v0.51.0</title>
      <link>https://perses.dev/blog/2025/06/06/release-v0510/</link>
      <guid isPermaLink="true">https://perses.dev/blog/2025/06/06/release-v0510/</guid>
      <pubDate>Fri, 06 Jun 2025 00:00:00 GMT</pubDate>
      <category>Release notes</category>
      <description>We are excited to announce the release of Perses v0.51.0!</description>
      <content:encoded><![CDATA[
<p>We are excited to announce the release of Perses v0.51.0!</p>
<p>This release brings several new features, improvements, and bug fixes to enhance your experience with Perses.</p>
<p>It is a significant step forward in the evolution of Perses, and we are thrilled to share it with you. We have
been working hard to bring you a more powerful and flexible platform for your observability needs.</p>
<p>This release includes a new plugin architecture, new panel, new variable, a new
repository <a href="https://github.com/perses/plugins">perses/plugins</a>
containing all default plugins supported by Perses.</p>
<p>We have also made significant improvements to the documentation, highlighting features that were implemented some time
ago but not well advertised, such as datasource discovery and ephemeral dashboards.</p>
<!-- more -->
<h2 id="new-plugins-system">New Plugins system</h2>
<p>Big news from us at Perses! We've rolled out a brand-new plugin system, and it's all about making things more flexible
and expandable.
Our goal? To provide a more flexible and extensible way to scaffold, develop and distribute plugins in Perses so we can
expand the possibilities for sources of data, visualization and interactions within the platform.</p>
<h3 id="whats-under-the-hood">What's Under the Hood?</h3>
<p>Leveraging <a href="https://rspack.dev/guide/features/module-federation">module federation</a> plugins can now operate
independently of the main Perses code.
Opening up a world of possibilities for developers to create and share plugins without being tied down to the core
codebase.
Plugins can be grouped into <strong>Plugin Modules</strong>, which are essentially collections of related plugins that can be
developed and distributed together.
Underneath it all, the system has a backend that handles data validation and migrations using Cuelang schemas, and a
frontend that brings everything to life with React components.</p>
<h3 id="easier-plugin-development">Easier Plugin Development</h3>
<p>To make life easier for developers, we've built some handy <code>plugin</code> commands right into our command-line interface,
<a href="https://perses.dev/docs/perses/latest/cli/"><code>percli</code></a>.
The CLI will do all the heavy lifting from setting up your project, getting your development environment ready, to
building your plugins.
That way, you can kick back and focus on the exciting part: actually creating awesome plugin features!</p>
<h3 id="how-does-it-work">How Does It Work?</h3>
<p>The new plugin system is designed to be super user-friendly.
You can scaffold a plugin using the <code>percli plugin generate</code> command, which will set up the new plugin files for you.
This command can be used several times to create multiple plugins in the same plugin module.
Then you can start developing your plugin using <code>percli plugin start</code> to run it in development mode and test it out in
your local Perses instance. Finally, compile it with <code>percli plugin build</code> to prepare it for distribution.</p>
<p>You can follow the <a href="https://perses.dev/docs/perses/latest/plugins/creation/">documentation</a> for details and examples to get
started with creating your own plugins.</p>
<h3 id="where-to-find-plugins">Where to Find Plugins</h3>
<p>Thanks to this new setup, our main Perses plugins have moved to their own dedicated home
at <a href="https://github.com/perses/plugins">perses/plugins</a>. And speaking of plugins, the system supports a bunch of
different types:</p>
<ul>
<li>Datasource: Perfect for grabbing data from all sorts of places.</li>
<li>Query: This one links your datasources to your panels.</li>
<li>Panel: Your go-to for making data look good through various visualizations.</li>
<li>Variable: For when you need dynamic values in your queries.</li>
<li>Explore: A special kind of panel designed for diving deep into your data.</li>
</ul>
<p>You just use <code>percli</code> to get started, test your creations, and then build them up to distribute as archive files or npm
packages.
After that, they're ready to be installed on a Perses server or even embedded directly into other React apps.</p>
<p>So, what kind of plugin are you dreaming of building first?</p>
<h3 id="which-plugins-are-available-in-perses">Which plugins are available in Perses</h3>
<p>All plugins that are available in the repository <a href="https://github.com/perses/plugins">perses/plugins</a> are installed by
default in Perses.</p>
<p>You can find the list of available plugins at runtime in the UI, in the <strong>Configuration</strong> page, under the <strong>Plugins</strong>
tab.</p>
<p><img src="https://perses.dev/assets/images/blog/v051/plugins-list.png" alt="PluginsList"></p>
<p>You can also use the CLI command <code>percli plugin list</code> to get the list of available plugins.</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-bash"><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">percli</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> plugin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> list</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        NAME</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   VERSION</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">     TYPE</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">     │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> LOADED</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> FROM</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> DEV</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">────────────────────┼─────────────┼──────────────┼────────┼──────────</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> DatasourceVariable</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.1.2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Variable</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">     │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> GaugeChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">         │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.7.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Markdown</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">           │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.7.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Prometheus</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">         │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 0.51.0-rc.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> PluginModule</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ScatterChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.6.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> StaticListVariable</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.3.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Variable</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">     │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Table</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">              │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.6.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> HistogramChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">     │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.7.2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> PieChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">           │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.7.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TimeSeriesChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.8.0</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TimeSeriesTable</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">    │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.7.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TraceTable</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">         │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.6.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> BarChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">           │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.7.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> TracingGanttChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">  │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.6.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> StatChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">          │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.7.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> StatusHistoryChart</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0.7.2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">       │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> Panel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">        │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Tempo</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">              │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> 0.51.0-rc.1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> │</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> PluginModule</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">   │</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span></code></pre>
<h2 id="new-plugins">New Plugins</h2>
<h3 id="datasource-variable">Datasource variable</h3>
<p>Thanks to the community contributions, we are introducing a new plugin: the <strong>Datasource Variable</strong>.
This plugin allows the possibility to use a datasource as a variable in your dashboard, specially in the queries of your
panels.</p>
<p>This is particularly useful when you have multiple datasources of the same type, such as multiple Prometheus instances,
and you would like to switch between them without having to modify each panel query.
<img src="https://perses.dev/assets/images/blog/v051/datasourceVariable.gif" alt="DatasourceVariable"></p>
<p>Of course, this plugin is not limited to Prometheus; it can be used with any datasource.</p>
<p>Note: If you are familiar with Grafana this feature wont will feel particularly new to you.
It's a valuable addition to Perses, helping to bring feature parity and making it a strong alternative for those
considering or exploring a
transition.</p>
<h3 id="histogram-chart">Histogram Chart</h3>
<p>This release introduces a new plugin: the <strong>Histogram Chart</strong>. This plugin allows you to visualize Prometheus Native
Histograms, providing a clear and concise way to understand the distribution of your histogram buckets.</p>
<p><img src="https://perses.dev/assets/images/blog/v051/histogram-panel.png" alt="Histogram Panel"></p>
<p>This panel is supporting thresholds, which allow you to colorize the chart based on specific values, making it easier to
understand your data.</p>
<p><img src="https://perses.dev/assets/images/blog/v051/histogram-thresholds.png" alt="Histogram with thresholds"></p>
<p>This chart is also used in <strong>TimeSeriesTable</strong> panel to display histogram details, allowing the Explore page to display
histograms.</p>
<p><img src="https://perses.dev/assets/images/blog/v051/histogram-explore.png" alt="Explore page with histograms"></p>
<p>In next releases, we are planning to add exponential mode support, add support for Prometheus classic histograms and
summaries and thresholds on bucket counts.
Feel free to give us ideas on how to improve this plugin, with issues or discussions on
the <a href="https://github.com/perses/perses">Perses GitHub repository</a>.
Spoiler: the heatmap panel is coming next release 🤫</p>
<h2 id="breaking-change-in-dashboard-as-code">Breaking Change in Dashboard as Code</h2>
<p>As previously mentioned, we have relocated the default plugins to a new repository. This includes not only the frontend
code, which has been transferred there, but also the corresponding Go SDK and CUE SDK for each plugin.</p>
<p>This move is a breaking change for the Dashboard as Code feature as when upgraded to the last version, you will no
longer have the plugin code from perses/perses repository.</p>
<p>All imports will have to be updated to point to the new repository. We created a module for each plugin so you can
import only the ones you need.</p>
<p>For example, in Go SDK, in case you are using the plugin <code>label-values</code> from the <code>Prometheus</code> module, you will need to
<code>go get</code> the plugin first:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-bash"><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">go</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> get</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> github.com/perses/plugins/prometheus</span></span></code></pre>
<p>Then, in your Go code, you will have to change the import path from:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-go"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> labelValuesVar </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">github.com/perses/perses/go-sdk/prometheus/variable/label-values</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span></code></pre>
<p>to:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-go"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> labelValuesVar </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">github.com/perses/plugins/prometheus/sdk/go/variable/label-values</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span></span></code></pre>
<p>As a complete example, this PR: <a href="https://github.com/perses/community-dashboards/pull/69">https://github.com/perses/community-dashboards/pull/69</a> is demonstrating the required
changes you will have to do in your code when upgrading to the v0.51.0 of Perses.</p>
<p>In the case of CUE SDK, we are also leveraging on the new dependency management introduced by CUE v0.12.0.
Where we previously had a custom-made schema retrieval achieved by <code>percli dac setup</code>, Perses is now fully aligned with
the new <a href="https://cuelang.org/docs/reference/modules/">CUE modules</a>.</p>
<p>To continue using the CUE SDK, you will need to update your CUE files to import the new modules, but also to <strong>upgrade</strong>
the
<strong>cue</strong> version you are using to at least <strong>v0.12.0</strong>.</p>
<h2 id="custom-lint-rules">Custom Lint rules</h2>
<p>As you may know, to validate your dashboard, we have implemented a set of rules.
These rules are executed when you save your dashboard during the unmarshalling step from JSON or YAML or during the
validation of each plugin using Cuelang.</p>
<p>In this release, we have added the ability to create custom lint rules. This allows you to enforce specific standards or
practices within your organization.</p>
<p>These custom rules should be defined in the configuration file of your Perses instance, typically located at
<code>/etc/perses/config.yaml</code>. The rules are defined under the <code>dashboard.custom_lint_rules</code> section.</p>
<p>Here is an example of how to define custom lint rules for dashboards:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">dashboard</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  custom_lint_rules</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Dashboard Naming Convention"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      target</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"$.metadata.name"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      assertion</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"value.matches('^[a-z]+(-[a-z]+)*$')"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      message</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Dashboard name must be all lowercase letters with hyphens only."</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      disable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    - </span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">name</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"At Least One Panel Exists"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      target</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"$.spec.panels"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      assertion</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"value.size() > 0"</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      message</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"Dashboard must contain at least one panel."</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">      disable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span></span></code></pre>
<p>We are using the <a href="https://goessner.net/articles/JsonPath/">JSONPath</a> syntax to target specific parts of the dashboard
JSON structure, and the assertion is a <a href="https://github.com/google/cel-spec/blob/master/doc/langdef.md">CEL</a> expression.</p>
<p>To know more about the syntax of the rules, please refer to
the <a href="https://perses.dev/docs/perses/latest/configuration/custom-lint-rules/">documentation</a></p>
<h2 id="disable-datasource-and-variable">Disable datasource and variable</h2>
<p>In Perses, it is possible to create datasource and variables at three different levels: global, project, and dashboard.</p>
<p>Usually, for security and governance reasons, you may want to prevent people to create datasource and variables at
various levels. For global and project levels, this is already possible using the RBAC system.</p>
<p>But before this release, it was not possible to disable the creation of datasource and variables at the dashboard level.</p>
<p>In this release, we are introducing the ability to disable the manipulation of datasources and variables at any level.
For that, you need to modify the configuration file of your Perses instance, and add the following section:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">datasource</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    disable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  project</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    disable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  disable_local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span></code></pre>
<p>This configuration is preventing the usage of datasources at any level and disable the associated HTTP route in the
Perses proxy.</p>
<p>Of course, this config is silly because without datasources, you cannot use dashboards, but it is a good example of how
to disable datasources.</p>
<p>The same example applies for variables:</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0"><code class="language-yaml"><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">variable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  global</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    disable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  project</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    disable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  disable_local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span></span></code></pre>
<h2 id="improvement-of-the-datasource-discovery">Improvement of the datasource discovery</h2>
<p>One year ago, we introduced the datasource discovery feature, which allows you to automatically discover remote
datasources from the Kubernetes API or from a generic HTTP endpoint.
And so far we never got feedback about it until a couple of months ago when <a href="https://www.sap.com/">SAP</a> started using
it.</p>
<h3 id="overview">Overview</h3>
<p>We didn't have the opportunity to highlight this feature, so here is a quick overview of how it works.</p>
<p>Datasource discovery is useful when you have a large number of datasources, and you don't want to manually register
them in your application. Note that this feature can only be used when registering Global Datasources.</p>
<p>We are supporting two types of discovery:</p>
<ul>
<li><strong>Kubernetes API</strong>: This allows you to discover datasources that are registered in the Kubernetes API, such as
Prometheus, Loki, and others. You can configure the discovery by specifying the namespace where the datasources are
located, the label selector to filter the datasources and the type of the discovery you would like to use: service,
pod, endpoint.</li>
<li><strong>HTTP Endpoint</strong>: This allows you to discover datasources from a generic HTTP endpoint. You can configure the
discovery by specifying the URL of the endpoint. The endpoint should return a JSON array of Global Datasource.</li>
</ul>
<p>If you want to learn more about this feature, please refer to
the <a href="https://perses.dev/docs/perses/latest/configuration/datasource-discovery/">documentation</a>.</p>
<h3 id="improvements">Improvements</h3>
<ul>
<li>We made a mistake about how the label selector was converted from the configuration file to the Kubernetes
API. The label selector was not correctly formatted, which prevented the discovery from working properly.</li>
<li>When converting a service to a global datasource, there was a corner case where the global datasource was not
correctly created. And then Perses was not able to load the datasource.</li>
</ul>
<p>Thanks to these little improvements, the datasource discovery feature is now more reliable and easier to use.</p>
<h2 id="community-dashboards">Community Dashboards</h2>
<p>Fresh off our talk at KubeCon EU 2025 in
London - <a href="http://youtube.com/watch?v=7h70Olo5Uzk">Limitless Possibilities, Consistent Design: Crafting Dashboards With Perses DAC</a>,
given by two perses maintainers, Nicolas Takashi and Antoine Thébaud, we are happy to introduce
the <a href="https://github.com/perses/community-dashboards">community-dashboards</a> repository.</p>
<p>Here we provide support for commonly used Mixin Dashboards, like Prometheus, Kubernetes and Thanos, build on top of
<strong>Dashboard as Code</strong> capabilities provided by Perses. We’ll dive deeper into the community-dashboards in our upcoming
blog post, but starting today, you can begin using them right away — whether by:</p>
<ul>
<li>
<p>Importing them directly into your Perses instance;</p>
</li>
<li>
<p>Using them as a starting point to build your own dashboards;</p>
</li>
<li>
<p>Or reusing individual panels in your own dashboards-as-code workflows.</p>
</li>
</ul>
<p>We're also welcoming the community to help us support and extent the community-dashboards. So if there are additional
dashboards you’d like to see supported, feel free to reach out to the team - or even better, help us extend the
supported dashboards with feedback or improvements to the dashboards. Your input helps shape what comes next!</p>
<h2 id="support-oauth2-authentication-for-datasource">Support OAuth2 authentication for Datasource</h2>
<p>Another cool contribution from the community is the support for OAuth2 authentication for datasources.</p>
<p>Before this release, the only way to authenticate to a datasource was to use a token, basic authentication and/or TLS
configuration (like client certificate).</p>
<p>But in real world scenarios, you may want to use OAuth2 authentication to access your datasources and this is now
possible!</p>
<p><img src="https://perses.dev/assets/images/blog/v051/datasource-oauth2.png" alt="Datasource OAuth2"></p>
<h2 id="support-yaml-and-yaml-k8s-custom-resource-format-for-dashboard">Support YAML and YAML K8s Custom Resource format for Dashboard</h2>
<img alt="Dashboard YAML" src="https://perses.dev/assets/images/blog/v051/dashboard-yaml.png" width="350" align="left">
<p>Finally, but not least, we are introducing the support for YAML and YAML K8s Custom Resource format when exporting a
dashboard from the UI.</p>
<p>The YAML CR format is directly compatible with the <code>perses-operator</code> and can be used in your GitOps workflow.</p>
<p>In future releases, we will also support the YAML format for all other resources, so you can export a panel or variable
in a YAML format.</p>]]></content:encoded>
    </item>
    <item>
      <title>Release v0.50.0</title>
      <link>https://perses.dev/blog/2025/01/15/release-v0500/</link>
      <guid isPermaLink="true">https://perses.dev/blog/2025/01/15/release-v0500/</guid>
      <pubDate>Wed, 15 Jan 2025 00:00:00 GMT</pubDate>
      <category>Release notes</category>
      <description>We are excited to announce the release of Perses v0.50.0! This release brings significant improvements to the migration process from Grafana to Perses, including a major fix for a memory leak issue.…</description>
      <content:encoded><![CDATA[
<p>We are excited to announce the release of Perses v0.50.0! This release brings significant improvements to the migration
process from Grafana to Perses, including a major fix for a memory leak issue. Additionally, it introduces a new Status
History Panel and various enhancements to the Table Panel, UI, and CLI. Read on to learn more about the new features and
improvements in this release.</p>
<p>See the complete release note for more details: <a href="https://github.com/perses/perses/releases/tag/v0.50.0">v0.50.0</a></p>
<!-- more -->
<h2 id="migration">Migration</h2>
<p>One of the greatest contents of this release is the migration that has been drastically improved.</p>
<p>Since the beginning of the project, we have been willing to provide an easy way to migrate dashboards from Grafana to
Perses. As a reminder, you can migrate a Grafana dashboard using the HTTP endpoint <code>/api/migrate</code> or the UI or the CLI
that consumes this endpoint.</p>
<p>The big issue with this feature was the memory leak that was hidden and not that easy to trigger.
(See <a href="https://github.com/perses/perses/issues/2039">issue #2039</a>)</p>
<p>This was a big blocker for the migration and one of the main reasons why Amadeus was not able to migrate to Perses.
Amadeus has a huge number of dashboards, and the memory leak was too important to be ignored.
To give you an idea, the memory leak was about <strong>40GB</strong> after migrating <strong>3000 dashboards</strong>. (~ 3MB per dashboard)</p>
<p><img src="https://perses.dev/assets/images/blog/v050/migration-memory-leak.png" alt="Memory leak"></p>
<p>As you may know, we are using Cuelang for the Perses plugin validation, and at first, we implemented a complete way to
migrate using Cuelang only.
The idea behind was to append every migration script (one for each panel, variable, queries) to the main one.
Then the Grafana JSON was converted to a Cuelang value, and we were applying the migration script to this value.</p>
<p>With the v0.50.0, we are changing deeply and only internally the way it's working. It doesn't change anything for the
user, but it's a huge improvement for the maintainability and the performance of the migration.</p>
<p>We have entirely rewritten the migration process. It is now using a hybrid system partially written in Golang and the
rest in Cuelang when the plugins are involved. Thanks to this new system, the Cuelang files written to migrate the
panels, the variables, and the queries can be validated and tested before the migration is applied.</p>
<p>Thanks to this change, we are happy to announce the memory leak has been fixed and the migration is now working
perfectly. We performed the same mass migration, and it succeeded without causing OOMKill, as it requires much less
memory than before. The graph below shows we didn't exceed <strong>3GB of memory</strong> during the migration.</p>
<p><img src="https://perses.dev/assets/images/blog/v050/migration-without-memory-leak.png" alt="no more Memory leak"></p>
<p>Finally, we’ve also addressed numerous updates to the migration process itself, incorporating fixes and enhancements to
better cover use cases raised by the community - thank you for your contributions!</p>
<h2 id="status-history-panel">Status History panel</h2>
<p>Thanks to <a href="https://github.com/abelyakin">Alexander Belyakin</a> from the community, Perses is supporting a new Panel: the
Status History Panel.</p>
<p>The Status History panel provides a visual representation of the status of various metrics over time.
It allows users to track changes in the status of different metrics, making it easier to identify patterns, trends, and
anomalies.
This panel is particularly useful for monitoring the health and performance of systems, as it can display status changes
in a clear and concise manner.
The panel can be customized to show different statuses, such as up, down, warning, or any other user-defined states, and
it supports various visualization options to enhance the readability of the data.</p>
<p>And of course, this panel is fully compatible with the migration process.</p>
<p><img src="https://perses.dev/assets/images/blog/v050/status-history-panel.png" alt="Status History panel"></p>
<h2 id="general-improvements">General Improvements</h2>
<h3 id="ui">UI</h3>
<p>We have finally added the redirection to the initial URL after you are authenticated. This was definitely a missing
feature annoying for the users.</p>
<p>This release also introduces various improvements to the <strong>Table Panel</strong>, such as debounced text fields in the editor,
default column sorting, custom column ordering, default column width setting, and cell focus on hover.</p>
<p><img src="https://perses.dev/assets/images/blog/v050/reorder-columns.gif" alt="Table Panel reordering columns"></p>
<h3 id="cli">CLI</h3>
<p>First, we have fixed the login command not working if you were using the CLI to log in to different Perses servers.</p>
<p>Then, based on the community feedback, we also have improved the DAC (Dashboard as Code) sub-command.
We hope the experience with our DAC framework will be better.</p>
<p>We are also introducing new commands for plugin development.
That's something that comes along with the new plugin architecture we are working on since last year.
These commands cannot be used currently as we are still working on the plugin architecture.</p>
<p>But stay tuned as we are really close to finishing this intense work! <strong>V0.51.0</strong> is going to be incredible with a lot
of changes!</p>]]></content:encoded>
    </item>
  </channel>
</rss>
