Skip to content

[CELEBORN-2359] Deduplicate # HELP/# TYPE lines in PrometheusServlet output#3734

Open
afterincomparableyum wants to merge 1 commit into
apache:mainfrom
afterincomparableyum:CELEBORN-2359
Open

[CELEBORN-2359] Deduplicate # HELP/# TYPE lines in PrometheusServlet output#3734
afterincomparableyum wants to merge 1 commit into
apache:mainfrom
afterincomparableyum:CELEBORN-2359

Conversation

@afterincomparableyum

@afterincomparableyum afterincomparableyum commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

AbstractSource emits a # HELP and # TYPE line for every metric sample. When a metric family has multiple label sets — like ActiveConnectionCount (per application), RequestSlotsFailedCount (per status code), per-user/app resource consumption, or FlushWorkingQueueSize (per mountpoint) — the same family is exported with repeated # HELP and # TYPE lines. This violates the Prometheus exposition format.

The fix is to override PrometheusServlet.getMetricsSnapshot to keep only the first # HELP and # TYPE line per metric family while preserving all sample lines, producing valid Prometheus output.

I also added a PrometheusServletSuite covering a multi-label-set counter and a distinct gauge.

Why are the changes needed?

To dedup the help and type lines to no longer violate prometheus exposition format.

Does this PR resolve a correctness bug?

  • Yes

Does this PR introduce any user-facing change?

  • Yes

How was this patch tested?

CI/CD

…output

AbstractSource emits a `# HELP` and `# TYPE` line for every metric sample. When a metric family has multiple label sets — like ActiveConnectionCount (per application), RequestSlotsFailedCount (per status code), per-user/app resource consumption, or FlushWorkingQueueSize (per mountpoint) — the same family is exported with repeated `# HELP` and `# TYPE` lines. This violates the Prometheus exposition format.

The fix is to override PrometheusServlet.getMetricsSnapshot to keep only the first `# HELP` and `# TYPE` line per metric family while preserving all sample lines, producing valid Prometheus output.

I also added a PrometheusServletSuite covering a multi-label-set counter and a distinct gauge.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Prometheus exposition format violations by deduplicating repeated # HELP / # TYPE lines emitted per metric sample, ensuring each metric name has only a single HELP/TYPE header while keeping all sample lines.

Changes:

  • Override PrometheusServlet.getMetricsSnapshot to filter duplicate # HELP / # TYPE lines per metric name.
  • Add a PrometheusServletSuite test covering a multi-label-set counter plus a separate gauge.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
service/src/main/scala/org/apache/celeborn/common/metrics/sink/PrometheusServlet.scala Adds post-processing of the raw snapshot to deduplicate HELP/TYPE header lines.
service/src/test/scala/org/apache/celeborn/common/metrics/sink/PrometheusServletSuite.scala Adds coverage ensuring HELP/TYPE lines appear only once for multi-label-set metrics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +47 to +56
raw.linesIterator.foreach {
case line @ header(kind, metric) =>
val key = s"$kind\t$metric"
if (!seen.contains(key)) {
out.append(line).append('\n')
seen += key
}
case line =>
out.append(line).append('\n')
}
source.addGauge("Gauge1") { () => 1000 }

val snapshot = newServlet(source).getMetricsSnapshot
val lines = snapshot.linesIterator.toList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants