Skip to content

Fix incorrect Content-Type on /metrics endpoint#2418

Open
fishi0x01 wants to merge 1 commit into
RedHatInsights:masterfrom
fishi0x01:fix-metrics-content-type-coo
Open

Fix incorrect Content-Type on /metrics endpoint#2418
fishi0x01 wants to merge 1 commit into
RedHatInsights:masterfrom
fishi0x01:fix-metrics-content-type-coo

Conversation

@fishi0x01

@fishi0x01 fishi0x01 commented Jul 15, 2026

Copy link
Copy Markdown

What

common/status_app.py's /metrics handler returned generate_latest() bytes via web.Response(body=...) without an explicit content_type, so aiohttp defaulted the response's Content-Type header to application/octet-stream.

Why

Legacy Prometheus (2.x) parses the response body as the classic exposition text format regardless of Content-Type, so this went unnoticed. Prometheus 3.x is stricter and rejects ambiguous Content-Type outright unless a fallback_scrape_protocol is configured on the scrape side. App-SRE's newer Cluster Observability Operator stack runs Prometheus 3.x, so scrapes against listener, taskomatic, grouper, notificator, evaluator-upload, and evaluator-recalc (all of which use this shared status_app module) were failing with:

received unsupported Content-Type "application/octet-stream" and no fallback_scrape_protocol specified for target

while working fine under the legacy stack.

Fix

Explicitly set the Content-Type header to CONTENT_TYPE_LATEST, matching prometheus_client's own documented usage pattern (see exposition.py).

Ref: APPSRE-13041

Summary by Sourcery

Bug Fixes:

  • Set the /metrics HTTP response Content-Type to Prometheus's CONTENT_TYPE_LATEST instead of relying on the aiohttp default.

common/status_app.py's metrics handler returned generate_latest() bytes
via web.Response(body=...) without an explicit content_type, so aiohttp
defaulted the response to "application/octet-stream". Legacy Prometheus
(2.x) parses the body as classic exposition text regardless, but
Prometheus 3.x rejects ambiguous Content-Type outright unless a
fallback_scrape_protocol is configured - which caused these targets
(listener, taskomatic, grouper, notificator, evaluator-upload,
evaluator-recalc) to show as down when scraped by App-SRE's newer
Cluster Observability Operator Prometheus stack, while working fine
under the legacy stack.

Fix: explicitly set the Content-Type header to CONTENT_TYPE_LATEST,
matching prometheus_client's own documented usage pattern.

Ref: https://redhat.atlassian.net/browse/APPSRE-13041
@sourcery-ai

sourcery-ai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Sets the Prometheus /metrics endpoint to return the correct text-based metrics Content-Type instead of the default application/octet-stream, by importing prometheus_client.CONTENT_TYPE_LATEST and applying it explicitly on the aiohttp response.

Sequence diagram for updated /metrics Prometheus scrape response

sequenceDiagram
  actor Prometheus
  participant StatusApp
  participant prometheus_client
  participant aiohttp_web as web

  Prometheus->>StatusApp: GET /metrics
  StatusApp->>StatusApp: metrics(request)
  StatusApp->>prometheus_client: generate_latest()
  prometheus_client-->>StatusApp: metrics_bytes
  StatusApp->>aiohttp_web: Response(body=metrics_bytes, headers={Content-Type: CONTENT_TYPE_LATEST})
  aiohttp_web-->>Prometheus: 200 OK Content-Type=CONTENT_TYPE_LATEST
Loading

File-Level Changes

Change Details Files
Ensure the /metrics endpoint responds with Prometheus' latest text exposition content type rather than aiohttp's default binary content type.
  • Import CONTENT_TYPE_LATEST from prometheus_client alongside existing metric utilities.
  • Update the metrics() handler to pass headers={"Content-Type": CONTENT_TYPE_LATEST} to web.Response while still using generate_latest() for the body.
common/status_app.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot 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.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant