Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ project adheres to [Semantic Versioning](http://semver.org/).

- Record cluster and worker thread scrape failures in internal histograms,
including timeouts, worker-reported errors, and failures with no known worker errors.
- Opt-in native histograms with configurable exponential buckets, a zero bucket,
bucket-count limits, exemplars, and worker/cluster aggregation.
- Prometheus protobuf registries for native and classic metrics, with public
content-type constants and TypeScript support for binary output.

## [0.16.0] - 2026-08-24

Expand Down
55 changes: 50 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,44 @@ xhrRequest(function (err, res) {
});
```

##### Native histograms

Enable native buckets with `nativeHistogramBucketFactor` and expose the registry
using Prometheus protobuf:

```js
const registry = new client.Registry(
client.Registry.PROMETHEUS_PROTOBUF_CONTENT_TYPE,
);
const histogram = new client.Histogram({
name: 'request_duration_seconds',
help: 'Time spent handling requests',
nativeHistogramBucketFactor: 1.1,
buckets: [],
registers: [registry],
});
histogram.observe(0.125);

res.setHeader('Content-Type', registry.contentType);
res.end(await registry.metrics()); // A Buffer for protobuf registries
```

Native buckets cover positive and negative values using exponential buckets and
a zero bucket. The default zero threshold is `2 ** -128`, configurable with
`nativeHistogramZeroThreshold`. The default budget of 160 populated buckets per
label set can be configured with `nativeHistogramMaxBucketNumber` (0 disables
the budget). When needed, resolution is reduced down to schema -4; at that

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit:

Suggested change
the budget). When needed, resolution is reduced down to schema -4; at that
the budget). When needed, resolution is progressively reduced down to schema -4; at that

minimum resolution the budget is a soft limit.

Classic buckets are retained by default. Set `buckets: []` for native-only
protobuf output. Prometheus text and OpenMetrics 1.0 text expose only the classic
representation. Prometheus must also be configured to scrape native histograms.

Native histograms default to `aggregator: 'sumNative'`. Use `firstNative` to keep
first values or `omit` to exclude them from aggregation. Both native aggregators
also handle the accompanying classic buckets; `sumNative` metrics are retained
on worker shutdown, like `sum` metrics.

#### Summary

Summaries calculate percentiles of observed values.
Expand Down Expand Up @@ -397,11 +435,12 @@ enabled. They get a single object with the format
`{labels, value, exemplarLabels}`.

When using exemplars, the registry used for metrics should be set to OpenMetrics
type (including the global or default registry if no registries are specified).
or Prometheus protobuf (including the global or default registry if no registries
are specified).

### Registry type

The library supports both the old Prometheus format and the OpenMetrics format.
The library supports Prometheus text, OpenMetrics text, and Prometheus protobuf.
The format can be set per registry. For default metrics:

```js
Expand All @@ -419,9 +458,14 @@ this is currently the default registry type.
**OPENMETRICS_CONTENT_TYPE** - defaults to version 1.0.0 of the
[OpenMetrics standard](https://github.com/OpenObservability/OpenMetrics/blob/d99b705f611b75fec8f450b05e344e02eea6921d/specification/OpenMetrics.md).

**PROMETHEUS_PROTOBUF_CONTENT_TYPE** - length-delimited Prometheus protobuf,
including native histograms. Registry serialization methods return a `Buffer`
for this format.

The HTTP Content-Type string for each registry type is exposed both at module
level (`prometheusContentType` and `openMetricsContentType`) and as static
properties on the `Registry` object.
level (`prometheusContentType`, `openMetricsContentType`, and
`prometheusProtobufContentType`) and as static properties on the `Registry`
object.

The `contentType` constant exposed by the module returns the default content
type when creating a new registry, currently defaults to Prometheus type.
Expand Down Expand Up @@ -630,7 +674,8 @@ Default metrics use sensible aggregation methods. (Note, however, that the event
loop lag mean and percentiles are averaged, which is not perfectly accurate.)
Custom metrics are summed across workers by default. To use a different
aggregation method, set the `aggregator` property in the metric config to one of
'sum', 'first', 'min', 'max', 'average' or 'omit'. (See `lib/metrics/version.js`
'sum', 'first', 'min', 'max', 'average' or 'omit'. Native histograms use
'sumNative' (the default), 'firstNative' or 'omit'. (See `lib/metrics/version.js`
for an example.)

Failed cluster collections are recorded in the
Expand Down
54 changes: 54 additions & 0 deletions example/native-histogram.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright The Prometheus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

const http = require('node:http');
const client = require('../index');

const registry = new client.Registry(
client.Registry.PROMETHEUS_PROTOBUF_CONTENT_TYPE,
);
client.collectDefaultMetrics({ register: registry });

const duration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Time spent handling requests',
labelNames: ['method'],
nativeHistogramBucketFactor: 1.1,
nativeHistogramMaxBucketNumber: 160,
buckets: [],
registers: [registry],
});

http
.createServer(async (req, res) => {
if (req.url === '/metrics') {
try {
const metrics = await registry.metrics();
res.writeHead(200, { 'Content-Type': registry.contentType });
res.end(metrics);
} catch (error) {
res.writeHead(500);
res.end(error.message);
}
return;
}

const end = duration.startTimer({ method: req.method });
res.writeHead(204);
res.end();
end();
})
.listen(Number(process.env.PORT ?? 3000));
Loading