Skip to content

DAT-1735: Upgrading prometheus_exporter#28

Merged
cajun merged 1 commit intomainfrom
DAT-1964
Apr 6, 2026
Merged

DAT-1735: Upgrading prometheus_exporter#28
cajun merged 1 commit intomainfrom
DAT-1964

Conversation

@cajun
Copy link
Copy Markdown
Contributor

@cajun cajun commented Mar 23, 2026

What? Why?

This PR adds a Content-Type header to work with newer versions of Prometheus.

This link describes the details of the Content-Type header settings
https://prometheus.io/docs/instrumenting/content_negotiation/

How was it tested?

First I started with running two versions of Prometheus with the same scrape configuration:

docker-compose.yml

services:
  prometheus-old:
    image: prom/prometheus:v2.50.0
    volumes:
      - "./prometheus.yml:/etc/prometheus/prometheus.yml"
    ports:
      - 9090:9090
  prometheus-new:
    image: prom/prometheus
    volumes:
      - "./prometheus.yml:/etc/prometheus/prometheus.yml"
    ports:
      - 9091:9090

prometheus.yml

scrape_configs:
  - job_name: 'bc-prometheus-ruby'
    metrics_path: '/metrics'
    scrape_interval: 5s
    static_configs:
      - targets: ['host.docker.internal:9394']

Then i used the default code from the readme of this repository.

#!/usr/bin/env ruby

ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile', __dir__)
require 'bundler/setup' # Set up gems listed in the Gemfile.

require 'bigcommerce/prometheus'

class AppTypeCollector < ::Bigcommerce::Prometheus::TypeCollectors::Base
  def build_metrics
    {
      honks: PrometheusExporter::Metric::Counter.new('honks', 'Running counter of honks'),
      points: PrometheusExporter::Metric::Gauge.new('points', 'Current amount of points')
    }
  end

  def collect_metrics(data:, labels: {})
    metric(:points).observe(data.fetch('points', 0))
    metric(:honks).observe(1, labels) if data.fetch('honks', 0).to_i.positive?
  end
end

class AppCollector < ::Bigcommerce::Prometheus::Collectors::Base
  def honk!
    push(
      honks: 1,
      custom_labels: {
        volume: 'loud'
      }
    )
  end

  def collect(metrics)
    metrics[:points] = rand(1..100)
    metrics
  end
end

::Bigcommerce::Prometheus.configure do |c|
  c.web_collectors = [AppCollector]
  c.web_type_collectors = [AppTypeCollector.new]
  c.resque_collectors = [AppCollector]
  c.resque_type_collectors = [AppTypeCollector.new]
  c.hutch_collectors = [AppCollector]
  c.hutch_type_collectors = [AppTypeCollector.new]
end

server = ::Bigcommerce::Prometheus::Server.new
Bigcommerce::Prometheus.web_type_collectors.each do |tc|
  server.add_type_collector(tc)
end

server.start_until_stopped do
  app_collector = AppCollector.new
  app_collector.honk!
  puts 'waiting'
end

Here are the metrics that are produced from the code above with the content-type being set

❯ curl -v localhost:9394/metrics
* Host localhost:9394 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:9394...
* connect to ::1 port 9394 from ::1 port 51494 failed: Connection refused
*   Trying 127.0.0.1:9394...
* Connected to localhost (127.0.0.1) port 9394
> GET /metrics HTTP/1.1
> Host: localhost:9394
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< content-type: text/plain; charset=utf-8
< content-length: 898
<
# HELP ruby_collector_metrics_total Total metrics processed by exporter.
# TYPE ruby_collector_metrics_total counter
ruby_collector_metrics_total 1


# HELP ruby_collector_sessions_total Total send_metric sessions processed by exporter.
# TYPE ruby_collector_sessions_total counter
ruby_collector_sessions_total 1


# HELP ruby_collector_bad_metrics_total Total mis-handled metrics by collector.
# TYPE ruby_collector_bad_metrics_total counter



# HELP ruby_collector_working Is the main process collector able to collect metrics
# TYPE ruby_collector_working gauge
ruby_collector_working 1


# HELP ruby_collector_rss total memory used by collector process
# TYPE ruby_collector_rss gauge
ruby_collector_rss 60512

# HELP ruby_honks Running counter of honks
# TYPE ruby_honks counter
ruby_honks{volume="loud"} 1

# HELP ruby_points Current amount of points
# TYPE ruby_points gauge
ruby_points 0
* Connection #0 to host localhost left intact

Testing Prometheus v2.50.0:
image

Testing Prometheus v3.10.0:

image

Note

Low Risk
Low risk: only adds an explicit Content-Type header on the /metrics endpoint and a small spec to lock in the behavior; no changes to metric generation or request routing.

Overview
Ensures the Puma /metrics endpoint always returns Content-Type: text/plain; charset=utf-8, improving compatibility with newer Prometheus content negotiation expectations.

Adds a focused Rack app spec asserting the header is present for GET /metrics responses.

Written by Cursor Bugbot for commit 573fed5. This will update automatically on new commits. Configure here.

@cajun cajun marked this pull request as ready for review March 24, 2026 14:50
@cajun cajun requested a review from a team as a code owner March 24, 2026 14:50
Comment thread lib/bigcommerce/prometheus/servers/puma/rack_app.rb Outdated
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Comment thread lib/bigcommerce/prometheus/servers/puma/rack_app.rb Outdated
@cajun cajun merged commit 5f8a82e into main Apr 6, 2026
10 checks passed
@cajun cajun deleted the DAT-1964 branch April 6, 2026 14:38
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.

2 participants