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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ project adheres to [Semantic Versioning](http://semver.org/).

### Added

- 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

This release marks our first release as a Prometheus subproject.
Expand Down
47 changes: 43 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,39 @@ 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
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.

#### Summary

Summaries calculate percentiles of observed values.
Expand Down Expand Up @@ -397,11 +430,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 +453,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
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