Skip to content

Commit e0e7d9d

Browse files
committed
Merge remote-tracking branch 'origin/main' into krajo/om2.0-native-histograms
2 parents 535e004 + 532758b commit e0e7d9d

File tree

9 files changed

+131
-4
lines changed

9 files changed

+131
-4
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
title: Visualizing Target Relabeling Rules in Prometheus 3.8.0
3+
created_at: 2025-12-02
4+
kind: article
5+
author_name: Julius Volz (@juliusv)
6+
---
7+
8+
Prometheus' [target relabeling](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) feature allows you to adjust the labels of a discovered target or even drop the target entirely. Relabeling rules, while powerful, can be hard to understand and debug. Your rules have to match the expected labels that your service discovery mechanism returns, and getting any step wrong could label your target incorrectly or accidentally drop it.
9+
10+
To help you figure out where things go wrong (or right), Prometheus 3.8.0 [just added a relabeling visualizer](https://github.com/prometheus/prometheus/pull/17337) to the Prometheus server's web UI that allows you to inspect how each relabeling rule is applied to a discovered target's labels. Let's take a look at how it works!
11+
12+
<!-- more -->
13+
14+
## Using the relabeling visualizer
15+
16+
If you head to any Prometheus server's "Service discovery" page (for example: https://demo.promlabs.com/service-discovery), you will now see a new "show relabeling" button for each discovered target:
17+
18+
![Service discovery page screenshot](/assets/blog/2025-12-02/prometheus-sd-page-show-relabeling.png)
19+
20+
Clicking this button shows you how each relabeling rule is applied to that particular target in sequence:
21+
22+
<video playsinline muted autoplay loop controls>
23+
<source src="/assets/blog/2025-12-02/prometheus-sd-page-relabeling-visualizer.mp4" type="video/mp4" />
24+
<p>Sorry, your browser does not support videos.</p>
25+
</video>
26+
27+
The visualizer shows you:
28+
29+
* The **initial labels** of the target as discovered by the service discovery mechanism.
30+
* The details of **each relabeling rule**, including its action type and other parameters.
31+
* **How the labels change** after each relabeling rule is applied, with changes, additions, and deletions highlighted in color.
32+
* Whether the target is ultimately **kept or dropped** after all relabeling rules have been applied.
33+
* The **final output labels** of the target if it is kept.
34+
35+
To debug your relabeling rules, you can now read this diagram from top to bottom and find the exact step where the labels change in an unexpected way or where the target gets dropped. This should help you identify misconfigurations in your relabeling rules more easily.
36+
37+
## Conclusion
38+
39+
The new relabeling visualizer in the Prometheus server's web UI is a powerful tool to help you understand and debug your target relabeling configurations. By providing a step-by-step view of how each relabeling rule affects a target's labels, it makes it easier to identify and fix issues in your setup. Update your Prometheus servers to 3.8.0 now to give it a try!

docs/instrumenting/exposition_formats.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,18 @@ When such features are enabled either by feature flag
167167
appropriate configuration option (`scrape_native_histograms: true`) then
168168
Protobuf will be favored over other exposition formats.
169169

170+
## HTTP Content-Type requirements
171+
172+
Starting with Prometheus 3.0, scrape targets **must** return a valid `Content-Type` header for the metrics endpoint. If the `Content-Type` is missing, unparsable, or not a supported media type, **the scrape will fail**. See changes in [scrape protocols](https://prometheus.io/docs/prometheus/latest/migration/#scrape-protocols) in the migration guide for details.
173+
174+
See each of the exposition format sections for the accurate HTTP content types.
175+
176+
### ScrapeProtocols vs Content-Type
177+
178+
Prometheus scrape config offers scrape protocol negotiation based on the content-type using the [`scrape_protocols`](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config) config. For the Prometheus user convenience the scrape protocols are referenced by a unique name that maps to the concrete content-type. See [Protocol Headers](./content_negotiation.md#protocol-headers) for details.
179+
180+
However, the targets should expose metrics in the exposition format with the absolute, response content-type (e.g. `application/openmetrics-text;version=1.0.0`) and only one.
181+
170182
## Historical versions
171183

172184
For details on historical format versions, see the legacy

docs/specs/om/open_metrics_spec_2_0.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,39 @@ acme_http_request_seconds_sum{path="/api/v1",method="GET"} 1.2e2 [email protected]
571571
acme_http_request_seconds_buckets{path="/api/v1",method="GET",le="0.5"} 1 [email protected]
572572
acme_http_request_seconds_buckets{path="/api/v1",method="GET",le="1"} 2 [email protected]
573573
acme_http_request_seconds_buckets{path="/api/v1",method="GET",le="+Inf"} 2 [email protected]
574+
# TYPE "foodb.read.errors" counter
575+
# HELP "foodb.read.errors" The number of errors in the read path for fooDb.
576+
{"foodb.read.errors","service.name"="my_service"} 3482
577+
# EOF
578+
```
579+
580+
##### UTF-8 Quoting
581+
582+
Metric names not conforming to the ABNF definition of `metricname` MUST be
583+
enclosed in double quotes and the alternative UTF-8 syntax MUST be used. In
584+
these MetricPoints, the quoted metric name MUST be moved inside the brackets
585+
without a label name and equal sign, in accordance with the ABNF. The metric
586+
names MUST be enclosed in double quotes in TYPE, UNIT, and HELP lines. Quoting
587+
and the alternative metric syntax MAY be used for any metric name, regardless of
588+
whether the name requires quoting or not.
589+
590+
Label names not conforming to the `label-name` ABNF definition MUST be enclosed
591+
in double quotes. Any label name MAY be enclosed in double quotes.
592+
593+
Expressed as regular expressions, metric names that don't need to be enclosed
594+
in quotes must match: `^[a-zA-Z_:][a-zA-Z0-9_:]*$`. For label names, the string
595+
must match: `^[a-zA-Z_][a-zA-Z0-9_]*$`.
596+
597+
Complete example:
598+
599+
```openmetrics
600+
# TYPE "process.cpu.seconds" counter
601+
# UNIT "process.cpu.seconds" seconds
602+
# HELP "process.cpu.seconds" Total user and system CPU time spent in seconds.
603+
{"process.cpu.seconds","node.name"="my_node"} 4.20072246e+06
604+
# TYPE "quoting_example" gauge
605+
# HELP "quoting_example" Number of goroutines that currently exist.
606+
{"quoting_example","foo"="bar"} 4.5
574607
# EOF
575608
```
576609

@@ -674,6 +707,8 @@ The value of a UNIT or HELP line MAY be empty. This MUST be treated as if no met
674707
# HELP foo_seconds Some text and \n some \" escaping
675708
```
676709

710+
See the UTF-8 Quoting section for circumstances where the metric name MUST be enclosed in double quotes.
711+
677712
There MUST NOT be more than one of each type of metadata line for a MetricFamily. The ordering SHOULD be TYPE, UNIT, HELP.
678713

679714
Aside from this metadata and the EOF line at the end of the message, you MUST NOT expose lines beginning with a #.
@@ -702,6 +737,13 @@ Label values MAY be any valid UTF-8 value, so escaping MUST be applied as per th
702737
bar_seconds_count{a="x",b="escaping\" example \n "} 0
703738
```
704739

740+
Metric names and label names MAY also be any valid UTF-8 value, and under certain circumstances they MUST be quoted and escaped per the ABNF.
741+
See the UTF-8 Quoting section for specifics.
742+
743+
```openmetrics-add-eof
744+
{"\"bar\".seconds.count","b\\"="escaping\" example \n "} 0
745+
```
746+
705747
The rendering of values for a MetricPoint can include additional labels (e.g. the "le" label for a Histogram type), which MUST be rendered in the same way as a Metric's own LabelSet.
706748

707749
#### MetricPoint
Binary file not shown.
196 KB
Loading

src/app/docs/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import TOC from "@/components/TOC";
1212
import LeftNav from "./LeftNav";
1313
import { IconMenu2 } from "@tabler/icons-react";
14+
import { AnchorScroller } from "@/components/AnchorScroller";
1415

1516
export default function DocsLayout({
1617
children,
@@ -85,6 +86,7 @@ export default function DocsLayout({
8586
}}
8687
/>
8788
</Group>
89+
<AnchorScroller />
8890
</>
8991
);
9092
}

src/app/globals.css

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ pre > code > span {
5353
}
5454

5555
.markdown-content {
56-
img:not(.no-markdown-image-styles) {
56+
img:not(.no-markdown-image-styles),
57+
video {
5758
max-width: 90%;
58-
max-height: 50vh;
59+
max-height: 65vh;
5960
height: auto;
6061
margin: 1.5em auto;
6162
display: block;

src/components/AnchorScroller.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"use client";
2+
3+
import { useEffect } from "react";
4+
5+
// A component that, when included on a page, scrolls to the element
6+
// indicated by the URL hash (if any) after the page loads. While the
7+
// browser normally does this automatically, it does so too early in
8+
// our case, before the layout settles, resulting in incorrect scroll
9+
// positions.
10+
export function AnchorScroller() {
11+
useEffect(() => {
12+
const hash = window.location.hash;
13+
if (!hash) {
14+
return;
15+
}
16+
17+
const el = document.querySelector(hash);
18+
if (!el) {
19+
return;
20+
}
21+
22+
// Wait for layout to settle using two wrapped requestAnimationFrame calls.
23+
requestAnimationFrame(() => {
24+
requestAnimationFrame(() => {
25+
el.scrollIntoView({ block: "start" });
26+
});
27+
});
28+
}, []);
29+
30+
return null;
31+
}

src/components/PromMarkdown.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ export default async function PromMarkdown({
147147
// <Group> with display: "inline-flex" somehow breaks link underlining,
148148
// so going for this manual solution instead.
149149
<span>
150-
{children}
150+
{children}&nbsp;
151151
<IconExternalLink
152152
size="0.9em"
153-
style={{ marginLeft: 4, marginBottom: -1.5 }}
153+
style={{ marginBottom: -1.5 }}
154154
/>
155155
</span>
156156
) : (

0 commit comments

Comments
 (0)