Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

prom-client

Package Overview
Dependencies
Maintainers
2
Versions
84
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prom-client - npm Package Compare versions

Comparing version 11.5.3 to 12.0.0

lib/metrics/gc.js

23

CHANGELOG.md

@@ -12,6 +12,28 @@ # Changelog

- Dropped support for end-of-life Node.js versions 6.x and 8.x
- Dropped the previously deprecated support for positional parameters in
constructors, only the config object forms remain.
- Default metrics are collected on scrape of metrics endpoint, not on an
interval. The `timeout` option to `collectDefaultMetrics(conf)` is no longer
supported or needed, and the function no longer returns a `Timeout` object.
### Changed
- chore: remove ignored package-lock.json
- fix: `process_max_fds` is process limit, not OS (#314)
- Changed `Metric` labelNames & labelValues in TypeScript declaration to a generic type `T extends string`, instead of `string`
- Lazy-load Node.js Cluster module to fix Passenger support (#293)
- fix: avoid mutation bug in `registry.getMetricsAsJSON()`
- fix: improve performance of `registry.getMetrics*`
- End function of histogram `startTimer`, when invoked returns the number of seconds
- chore: reindent package.json
- chore: correct var name in processStartTime
- chore: add test for `process_start_time_seconds`
- chore: spelling corrections in README
### Added
- feat: implement GC metrics collection without native(C++) modules.
- faet: implement advanced event loop monitoring
## [11.5.3] - 2019-06-27

@@ -58,2 +80,3 @@

### Added
- Added a `remove()` method on each metric type, based on [Prometheus "Writing Client Libraries" section on labels](https://prometheus.io/docs/instrumenting/writing_clientlibs/#labels)

@@ -60,0 +83,0 @@

195

index.d.ts

@@ -5,12 +5,2 @@ // Type definitions for prom-client

/**
* Options pass to Registry.metrics()
*/
export interface MetricsOpts {
/**
* Whether to include timestamps in the output, defaults to true
*/
timestamps?: boolean;
}
/**
* Container for all registered metrics

@@ -22,3 +12,3 @@ */

*/
metrics(opts?: MetricsOpts): string;
metrics(): string;

@@ -39,3 +29,3 @@ /**

*/
registerMetric(metric: Metric): void;
registerMetric<T extends string>(metric: Metric<T>): void;

@@ -62,3 +52,3 @@ /**

*/
getSingleMetric(name: string): Metric;
getSingleMetric<T extends string>(name: string): Metric<T>;

@@ -131,3 +121,7 @@ /**

*/
export type Metric = Counter | Gauge | Summary | Histogram;
export type Metric<T extends string> =
| Counter<T>
| Gauge<T>
| Summary<T>
| Histogram<T>;

@@ -153,10 +147,8 @@ /**

interface labelValues {
[key: string]: string | number;
}
type LabelValues<T extends string> = Partial<Record<T, string | number>>;
export interface CounterConfiguration {
export interface CounterConfiguration<T extends string> {
name: string;
help: string;
labelNames?: string[];
labelNames?: T[];
registers?: Registry[];

@@ -169,23 +161,14 @@ aggregator?: Aggregator;

*/
export class Counter {
export class Counter<T extends string> {
/**
* @param configuration Configuration when creating a Counter metric. Name and Help is required.
*/
constructor(configuration: CounterConfiguration);
constructor(configuration: CounterConfiguration<T>);
/**
* @param name The name of the metric
* @param help Help description
* @param labels Label keys
* @deprecated
*/
constructor(name: string, help: string, labels?: string[]);
/**
* Increment for given labels
* @param labels Object with label keys and values
* @param value The number to increment with
* @param timestamp Timestamp to associate the time series with
*/
inc(labels: labelValues, value?: number, timestamp?: number | Date): void;
inc(labels: LabelValues<T>, value?: number): void;

@@ -195,5 +178,4 @@ /**

* @param value The value to increment with
* @param timestamp Timestamp to associate the time series with
*/
inc(value?: number, timestamp?: number | Date): void;
inc(value?: number): void;

@@ -224,12 +206,11 @@ /**

* @param value The value to increment with
* @param timestamp Timestamp to associate the time series with
*/
inc(value?: number, timestamp?: number | Date): void;
inc(value?: number): void;
}
}
export interface GaugeConfiguration {
export interface GaugeConfiguration<T extends string> {
name: string;
help: string;
labelNames?: string[];
labelNames?: T[];
registers?: Registry[];

@@ -242,23 +223,14 @@ aggregator?: Aggregator;

*/
export class Gauge {
export class Gauge<T extends string> {
/**
* @param configuration Configuration when creating a Gauge metric. Name and Help is mandatory
*/
constructor(configuration: GaugeConfiguration);
constructor(configuration: GaugeConfiguration<T>);
/**
* @param name The name of the metric
* @param help Help description
* @param labels Label keys
* @deprecated
*/
constructor(name: string, help: string, labels?: string[]);
/**
* Increment gauge for given labels
* @param labels Object with label keys and values
* @param value The value to increment with
* @param timestamp Timestamp to associate the time series with
*/
inc(labels: labelValues, value?: number, timestamp?: number | Date): void;
inc(labels: LabelValues<T>, value?: number): void;

@@ -268,5 +240,4 @@ /**

* @param value The value to increment with
* @param timestamp Timestamp to associate the time series with
*/
inc(value?: number, timestamp?: number | Date): void;
inc(value?: number): void;

@@ -277,5 +248,4 @@ /**

* @param value Value to decrement with
* @param timestamp Timestamp to associate the time series with
*/
dec(labels: labelValues, value?: number, timestamp?: number | Date): void;
dec(labels: LabelValues<T>, value?: number): void;

@@ -285,5 +255,4 @@ /**

* @param value The value to decrement with
* @param timestamp Timestamp to associate the time series with
*/
dec(value?: number, timestamp?: number | Date): void;
dec(value?: number): void;

@@ -294,5 +263,4 @@ /**

* @param value The value to set
* @param timestamp Timestamp to associate the time series with
*/
set(labels: labelValues, value: number, timestamp?: number | Date): void;
set(labels: LabelValues<T>, value: number): void;

@@ -302,5 +270,4 @@ /**

* @param value The value to set
* @param timestamp Timestamp to associate the time series with
*/
set(value: number, timestamp?: number | Date): void;
set(value: number): void;

@@ -311,3 +278,3 @@ /**

*/
setToCurrentTime(labels?: labelValues): void;
setToCurrentTime(labels?: LabelValues<T>): void;

@@ -319,3 +286,3 @@ /**

*/
startTimer(labels?: labelValues): (labels?: labelValues) => void;
startTimer(labels?: LabelValues<T>): (labels?: LabelValues<T>) => void;

@@ -327,3 +294,3 @@ /**

*/
labels(...values: string[]): Gauge.Internal;
labels(...values: string[]): Gauge.Internal<T>;

@@ -343,9 +310,8 @@ /**

export namespace Gauge {
interface Internal {
interface Internal<T extends string> {
/**
* Increment gauge with value
* @param value The value to increment with
* @param timestamp Timestamp to associate the time series with
*/
inc(value?: number, timestamp?: number | Date): void;
inc(value?: number): void;

@@ -355,5 +321,4 @@ /**

* @param value The value to decrement with
* @param timestamp Timestamp to associate the time series with
*/
dec(value?: number, timestamp?: number | Date): void;
dec(value?: number): void;

@@ -363,5 +328,4 @@ /**

* @param value The value to set
* @param timestamp Timestamp to associate the time series with
*/
set(value: number, timestamp?: number | Date): void;
set(value: number): void;

@@ -377,10 +341,10 @@ /**

*/
startTimer(): (labels?: labelValues) => void;
startTimer(): (labels?: LabelValues<T>) => void;
}
}
export interface HistogramConfiguration {
export interface HistogramConfiguration<T extends string> {
name: string;
help: string;
labelNames?: string[];
labelNames?: T[];
buckets?: number[];

@@ -394,29 +358,9 @@ registers?: Registry[];

*/
export class Histogram {
export class Histogram<T extends string> {
/**
* @param configuration Configuration when creating the Histogram. Name and Help is mandatory
*/
constructor(configuration: HistogramConfiguration);
constructor(configuration: HistogramConfiguration<T>);
/**
* @param name The name of metric
* @param help Help description
* @param labels Label keys
* @param config Configuration object for Histograms
*/
constructor(
name: string,
help: string,
labels?: string[],
config?: Histogram.Config
);
/**
* @param name The name of metric
* @param help Help description
* @param config Configuration object for Histograms
* @deprecated
*/
constructor(name: string, help: string, config: Histogram.Config);
/**
* Observe value

@@ -431,3 +375,3 @@ * @param value The value to observe

*/
observe(labels: labelValues, value: number): void;
observe(labels: LabelValues<T>, value: number): void;

@@ -439,3 +383,3 @@ /**

*/
startTimer(labels?: labelValues): (labels?: labelValues) => void;
startTimer(labels?: LabelValues<T>): (labels?: LabelValues<T>) => void;

@@ -452,3 +396,3 @@ /**

*/
labels(...values: string[]): Histogram.Internal;
labels(...values: string[]): Histogram.Internal<T>;

@@ -463,3 +407,3 @@ /**

export namespace Histogram {
interface Internal {
interface Internal<T extends string> {
/**

@@ -476,3 +420,3 @@ * Observe value

*/
startTimer(): (labels?: labelValues) => void;
startTimer(): (labels?: LabelValues<T>) => void;
}

@@ -488,6 +432,6 @@

export interface SummaryConfiguration {
export interface SummaryConfiguration<T extends string> {
name: string;
help: string;
labelNames?: string[];
labelNames?: T[];
percentiles?: number[];

@@ -504,29 +448,9 @@ registers?: Registry[];

*/
export class Summary {
export class Summary<T extends string> {
/**
* @param configuration Configuration when creating Summary metric. Name and Help is mandatory
*/
constructor(configuration: SummaryConfiguration);
constructor(configuration: SummaryConfiguration<T>);
/**
* @param name The name of the metric
* @param help Help description
* @param labels Label keys
* @param config Configuration object
*/
constructor(
name: string,
help: string,
labels?: string[],
config?: Summary.Config
);
/**
* @param name The name of the metric
* @param help Help description
* @param config Configuration object
* @deprecated
*/
constructor(name: string, help: string, config: Summary.Config);
/**
* Observe value in summary

@@ -541,3 +465,3 @@ * @param value The value to observe

*/
observe(labels: labelValues, value: number): void;
observe(labels: LabelValues<T>, value: number): void;

@@ -549,3 +473,3 @@ /**

*/
startTimer(labels?: labelValues): (labels?: labelValues) => void;
startTimer(labels?: LabelValues<T>): (labels?: LabelValues<T>) => void;

@@ -562,3 +486,3 @@ /**

*/
labels(...values: string[]): Summary.Internal;
labels(...values: string[]): Summary.Internal<T>;

@@ -573,3 +497,3 @@ /**

export namespace Summary {
interface Internal {
interface Internal<T extends string> {
/**

@@ -586,3 +510,3 @@ * Observe value in summary

*/
startTimer(): (labels?: labelValues) => void;
startTimer(): (labels?: LabelValues<T>) => void;
}

@@ -682,6 +606,6 @@

export interface DefaultMetricsCollectorConfiguration {
timeout?: number;
timestamps?: boolean;
register?: Registry;
prefix?: string;
gcDurationBuckets?: number[];
eventLoopMonitoringPrecision?: number;
}

@@ -692,16 +616,7 @@

* @param config Configuration object for default metrics collector
* @return The setInterval number
*/
export function collectDefaultMetrics(
config?: DefaultMetricsCollectorConfiguration
): ReturnType<typeof setInterval>;
): void;
/**
* Configure default metrics
* @param timeout The interval how often the default metrics should be probed
* @deprecated A number to defaultMetrics is deprecated, please use \`collectDefaultMetrics({ timeout: ${timeout} })\`.
* @return The setInterval number
*/
export function collectDefaultMetrics(timeout: number): number;
export interface defaultMetrics {

@@ -708,0 +623,0 @@ /**

@@ -11,6 +11,12 @@ 'use strict';

const cluster = require('cluster');
const Registry = require('./registry');
const { Grouper } = require('./util');
const { aggregators } = require('./metricAggregators');
// We need to lazy-load the 'cluster' module as some application servers -
// namely Passenger - crash when it is imported.
let cluster = () => {
const data = require('cluster');
cluster = () => data;
return data;
};

@@ -70,7 +76,7 @@ const GET_METRICS_REQ = 'prom-client:getMetricsReq';

for (const id in cluster.workers) {
for (const id in cluster().workers) {
// If the worker exits abruptly, it may still be in the workers
// list but not able to communicate.
if (cluster.workers[id].isConnected()) {
cluster.workers[id].send(message);
if (cluster().workers[id].isConnected()) {
cluster().workers[id].send(message);
request.pending++;

@@ -158,5 +164,5 @@ }

if (cluster.isMaster) {
if (cluster().isMaster) {
// Listen for worker responses to requests for local metrics
cluster.on('message', (worker, message) => {
cluster().on('message', (worker, message) => {
if (message.type === GET_METRICS_RES) {

@@ -183,15 +189,13 @@ const request = requests.get(message.requestId);

if (cluster.isWorker) {
// Respond to master's requests for worker's local metrics.
process.on('message', message => {
if (message.type === GET_METRICS_REQ) {
process.send({
type: GET_METRICS_RES,
requestId: message.requestId,
metrics: registries.map(r => r.getMetricsAsJSON())
});
}
});
}
// Respond to master's requests for worker's local metrics.
process.on('message', message => {
if (cluster().isWorker && message.type === GET_METRICS_REQ) {
process.send({
type: GET_METRICS_RES,
requestId: message.requestId,
metrics: registries.map(r => r.getMetricsAsJSON())
});
}
});
module.exports = AggregatorRegistry;

@@ -10,7 +10,5 @@ /**

const {
isDate,
getPropertiesFromObj,
hashObject,
isObject,
printDeprecationObjectConstructor,
getLabels,

@@ -29,30 +27,20 @@ removeLabels

* Counter
* @param {string} name - Name of the metric
* @param {string} help - Help description for the metric
* @param {Array.<string>} labels - Labels
* @param {config} config - Configuration object.
* @param {string} config.name - Name of the metric
* @param {string} config.help - Help description for the metric
* @param {Array.<string>} config.labels - Array with strings, all label keywords supported
*/
constructor(name, help, labels) {
let config;
if (isObject(name)) {
config = Object.assign(
{
labelNames: []
},
name
);
if (!config.registers) {
config.registers = [globalRegistry];
}
} else {
printDeprecationObjectConstructor();
config = {
name,
help,
labelNames: labels,
registers: [globalRegistry]
};
constructor(config) {
if (!isObject(config)) {
throw new TypeError('constructor expected a config object');
}
config = Object.assign(
{
labelNames: []
},
config
);
if (!config.registers) {
config.registers = [globalRegistry];
}
if (!config.help) {

@@ -67,3 +55,2 @@ throw new Error('Missing mandatory help parameter');

}
if (!validateLabelName(config.labelNames)) {

@@ -74,7 +61,4 @@ throw new Error('Invalid label name');

this.name = config.name;
this.labelNames = config.labelNames || [];
this.reset();
this.help = config.help;

@@ -92,6 +76,5 @@ this.aggregator = config.aggregator || 'sum';

* @param {Number} value - Value to increment, if omitted increment with 1
* @param {(Number|Date)} timestamp - Timestamp to set the counter to
* @returns {void}
*/
inc(labels, value, timestamp) {
inc(labels, value) {
if (!isObject(labels)) {

@@ -102,3 +85,3 @@ return inc.call(this, null)(labels, value);

const hash = hashObject(labels);
return inc.call(this, labels, hash)(value, timestamp);
return inc.call(this, labels, hash)(value);
}

@@ -148,11 +131,6 @@

const inc = function(labels, hash) {
return (value, timestamp) => {
return value => {
if (value && !Number.isFinite(value)) {
throw new TypeError(`Value is not a valid number: ${util.format(value)}`);
}
if (timestamp && !isDate(timestamp) && !Number.isFinite(timestamp)) {
throw new TypeError(
`Timestamp is not a valid date or number: ${util.format(timestamp)}`
);
}
if (value < 0) {

@@ -167,18 +145,12 @@ throw new Error('It is not possible to decrease a counter');

this.hashMap = setValue(this.hashMap, incValue, timestamp, labels, hash);
this.hashMap = setValue(this.hashMap, incValue, labels, hash);
};
};
function setValue(hashMap, value, timestamp, labels, hash) {
function setValue(hashMap, value, labels, hash) {
hash = hash || '';
timestamp = isDate(timestamp)
? timestamp.valueOf()
: Number.isFinite(timestamp)
? timestamp
: undefined;
if (hashMap[hash]) {
hashMap[hash].value += value;
hashMap[hash].timestamp = timestamp;
} else {
hashMap[hash] = { value, labels: labels || {}, timestamp };
hashMap[hash] = { value, labels: labels || {} };
}

@@ -185,0 +157,0 @@ return hashMap;

'use strict';
const { isObject } = require('./util');
const { globalRegistry } = require('./registry');
// Default metrics.
const processCpuTotal = require('./metrics/processCpuTotal');

@@ -14,4 +18,3 @@ const processStartTime = require('./metrics/processStartTime');

const version = require('./metrics/version');
const { globalRegistry } = require('./registry');
const { printDeprecationCollectDefaultMetricsNumber } = require('./util');
const gc = require('./metrics/gc');

@@ -29,59 +32,49 @@ const metrics = {

heapSpacesSizeAndUsed,
version
version,
gc
};
const metricsList = Object.keys(metrics);
let existingInterval = null;
// This is used to ensure the program throws on duplicate metrics during first run
// We might want to consider not supporting running the default metrics function more than once
let init = true;
module.exports = function collectDefaultMetrics(config) {
if (config !== null && config !== undefined && !isObject(config)) {
throw new TypeError('config must be null, undefined, or an object');
}
module.exports = function startDefaultMetrics(config) {
let normalizedConfig = config;
if (typeof config === 'number') {
printDeprecationCollectDefaultMetricsNumber(config);
config = Object.assign({ eventLoopMonitoringPrecision: 10 }, config);
normalizedConfig = { timeout: config };
}
const registry = config.register || globalRegistry;
const last = registry
.collectors()
.find(collector => collector._source === metrics);
normalizedConfig = Object.assign(
{
timestamps: true,
timeout: 10000
},
normalizedConfig
);
if (existingInterval !== null) {
clearInterval(existingInterval);
if (last) {
throw new Error(
'Cannot add the default metrics twice to the same registry'
);
}
const initialisedMetrics = metricsList.map(metric => {
const defaultMetric = metrics[metric];
if (!init) {
defaultMetric.metricNames.map(
globalRegistry.removeSingleMetric,
globalRegistry
);
}
return defaultMetric(normalizedConfig.register, normalizedConfig);
const scrapers = metricsList.map(key => {
const metric = metrics[key];
return metric(config.register, config);
});
function updateAllMetrics() {
initialisedMetrics.forEach(metric => metric.call());
// Ideally the library would be based around a concept of collectors and
// async callbacks, but in the short-term, trigger scraping of the
// current metric value synchronously.
// - // https://prometheus.io/docs/instrumenting/writing_clientlibs/#overall-structure
function defaultMetricCollector() {
scrapers.forEach(scraper => scraper());
}
updateAllMetrics();
// defaultMetricCollector has to be dynamic, because the scrapers are in
// its closure, but we still want to identify a default collector, so
// tag it with a value known only to this module (the const metric array
// value) so we can find it later.
defaultMetricCollector._source = metrics;
registry.registerCollector(defaultMetricCollector);
existingInterval = setInterval(
updateAllMetrics,
normalizedConfig.timeout
).unref();
init = false;
return existingInterval;
// Because the tests expect an immediate collection.
defaultMetricCollector();
};
module.exports.metricsList = metricsList;

@@ -11,3 +11,2 @@ /**

const {
isDate,
setValue,

@@ -18,3 +17,2 @@ getPropertiesFromObj,

isObject,
printDeprecationObjectConstructor,
removeLabels

@@ -31,29 +29,20 @@ } = require('./util');

* Gauge
* @param {string} name - Name of the metric
* @param {string} help - Help for the metric
* @param {Array.<string>} labels - Array with strings, all label keywords supported
* @param {config} config - Configuration object
* @param {string} config.name - Name of the metric
* @param {string} config.help - Help description for the metric
* @param {Array.<string>} config.labels - Array with strings, all label keywords supported
*/
constructor(name, help, labels) {
let config;
if (isObject(name)) {
config = Object.assign(
{
labelNames: []
},
name
);
if (!config.registers) {
config.registers = [globalRegistry];
}
} else {
printDeprecationObjectConstructor();
config = {
name,
help,
labelNames: labels,
registers: [globalRegistry]
};
constructor(config) {
if (!isObject(config)) {
throw new TypeError('constructor expected a config object');
}
config = Object.assign(
{
labelNames: []
},
config
);
if (!config.registers) {
config.registers = [globalRegistry];
}
if (!config.help) {

@@ -87,10 +76,9 @@ throw new Error('Missing mandatory help parameter');

* @param {Number} value - Value to set the gauge to, must be positive
* @param {(Number|Date)} timestamp - Timestamp to set the gauge to
* @returns {void}
*/
set(labels, value, timestamp) {
set(labels, value) {
if (!isObject(labels)) {
return set.call(this, null)(labels, value);
}
return set.call(this, labels)(value, timestamp);
return set.call(this, labels)(value);
}

@@ -110,7 +98,6 @@

* @param {Number} value - Value to increment - if omitted, increment with 1
* @param {(Number|Date)} timestamp - Timestamp to set the gauge to
* @returns {void}
*/
inc(labels, value, timestamp) {
inc.call(this, labels)(value, timestamp);
inc(labels, value) {
inc.call(this, labels)(value);
}

@@ -122,7 +109,6 @@

* @param {Number} value - Value to decrement - if omitted, decrement with 1
* @param {(Number|Date)} timestamp - Timestamp to set the gauge to
* @returns {void}
*/
dec(labels, value, timestamp) {
dec.call(this, labels)(value, timestamp);
dec(labels, value) {
dec.call(this, labels)(value);
}

@@ -210,9 +196,5 @@

function dec(labels) {
return (value, timestamp) => {
return value => {
const data = convertLabelsAndValues(labels, value);
this.set(
data.labels,
this._getValue(data.labels) - (data.value || 1),
timestamp
);
this.set(data.labels, this._getValue(data.labels) - (data.value || 1));
};

@@ -222,9 +204,5 @@ }

function inc(labels) {
return (value, timestamp) => {
return value => {
const data = convertLabelsAndValues(labels, value);
this.set(
data.labels,
this._getValue(data.labels) + (data.value || 1),
timestamp
);
this.set(data.labels, this._getValue(data.labels) + (data.value || 1));
};

@@ -234,11 +212,6 @@ }

function set(labels) {
return (value, timestamp) => {
return value => {
if (typeof value !== 'number') {
throw new TypeError(`Value is not a valid number: ${util.format(value)}`);
}
if (timestamp && !isDate(timestamp) && !Number.isFinite(timestamp)) {
throw new TypeError(
`Timestamp is not a valid date or number: ${util.format(timestamp)}`
);
}

@@ -248,3 +221,3 @@ labels = labels || {};

validateLabel(this.labelNames, labels);
this.hashMap = setValue(this.hashMap, value, labels, timestamp);
this.hashMap = setValue(this.hashMap, value, labels);
};

@@ -251,0 +224,0 @@ }

@@ -14,3 +14,2 @@ /**

isObject,
printDeprecationObjectConstructor,
removeLabels

@@ -27,43 +26,21 @@ } = require('./util');

* Histogram
* @param {string} name - Name of the metric
* @param {string} help - Help for the metric
* @param {object|Array.<string>} labelsOrConf - Either array of label names or config object as a key-value object
* @param {object} conf - Configuration object
* @param {config} config - Configuration object.
* @param {string} config.name - Name of the metric
* @param {string} config.help - Help for the metric
* @param {Array.<string>} config.labels - Array with strings, all label keywords supported
*/
constructor(name, help, labelsOrConf, conf) {
let config;
if (isObject(name)) {
config = Object.assign(
{
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
labelNames: []
},
name
);
if (!config.registers) {
config.registers = [globalRegistry];
}
} else {
let obj;
let labels = [];
if (Array.isArray(labelsOrConf)) {
obj = conf || {};
labels = labelsOrConf;
} else {
obj = labelsOrConf || {};
}
printDeprecationObjectConstructor();
config = {
name,
labelNames: labels,
help,
buckets: configureUpperbounds(obj.buckets),
registers: [globalRegistry]
};
constructor(config) {
if (!isObject(config)) {
throw new TypeError('constructor expected a config object');
}
config = Object.assign(
{
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
labelNames: []
},
config
);
if (!config.registers) {
config.registers = [globalRegistry];
}
validateInput(config.name, config.help, config.labelNames);

@@ -141,3 +118,4 @@

* makeExpensiveXHRRequest(function(err, res) {
* end(); //Observe the duration of expensiveXHRRequest
* const duration = end(); //Observe the duration of expensiveXHRRequest and returns duration in seconds
* console.log('Duration', duration);
* });

@@ -168,9 +146,9 @@ */

const delta = process.hrtime(start);
this.observe(
Object.assign({}, startLabels, endLabels),
delta[0] + delta[1] / 1e9
);
const value = delta[0] + delta[1] / 1e9;
this.observe(Object.assign({}, startLabels, endLabels), value);
return value;
};
};
}
function validateInput(name, help, labels) {

@@ -199,23 +177,2 @@ if (!help) {

function configureUpperbounds(configuredBuckets) {
const defaultBuckets = [
0.005,
0.01,
0.025,
0.05,
0.1,
0.25,
0.5,
1,
2.5,
5,
10
];
return [].concat(configuredBuckets || defaultBuckets).sort(sortAscending);
}
function sortAscending(x, y) {
return x - y;
}
function setValuePair(labels, value, metricName) {

@@ -264,3 +221,3 @@ return {

if (valueFromMap.bucketValues.hasOwnProperty(b)) {
if (Object.prototype.hasOwnProperty.call(valueFromMap.bucketValues, b)) {
valueFromMap.bucketValues[b] += 1;

@@ -267,0 +224,0 @@ }

@@ -5,4 +5,24 @@ 'use strict';

// Check if perf_hooks module is available
let perf_hooks;
try {
/* eslint-disable node/no-unsupported-features/node-builtins */
perf_hooks = require('perf_hooks');
} catch (e) {
// node version is too old
}
// Reported always, but because legacy lag_seconds is collected async, the value
// will always be stale by one scrape interval.
const NODEJS_EVENTLOOP_LAG = 'nodejs_eventloop_lag_seconds';
// Reported only when perf_hooks is available.
const NODEJS_EVENTLOOP_LAG_MIN = 'nodejs_eventloop_lag_min_seconds';
const NODEJS_EVENTLOOP_LAG_MAX = 'nodejs_eventloop_lag_max_seconds';
const NODEJS_EVENTLOOP_LAG_MEAN = 'nodejs_eventloop_lag_mean_seconds';
const NODEJS_EVENTLOOP_LAG_STDDEV = 'nodejs_eventloop_lag_stddev_seconds';
const NODEJS_EVENTLOOP_LAG_P50 = 'nodejs_eventloop_lag_p50_seconds';
const NODEJS_EVENTLOOP_LAG_P90 = 'nodejs_eventloop_lag_p90_seconds';
const NODEJS_EVENTLOOP_LAG_P99 = 'nodejs_eventloop_lag_p99_seconds';
function reportEventloopLag(start, gauge) {

@@ -13,3 +33,3 @@ const delta = process.hrtime(start);

gauge.set(seconds, Date.now());
gauge.set(seconds);
}

@@ -20,3 +40,3 @@

const gauge = new Gauge({
const lag = new Gauge({
name: namePrefix + NODEJS_EVENTLOOP_LAG,

@@ -27,9 +47,73 @@ help: 'Lag of event loop in seconds.',

});
const lagMin = new Gauge({
name: namePrefix + NODEJS_EVENTLOOP_LAG_MIN,
help: 'The minimum recorded event loop delay.',
registers: registry ? [registry] : undefined
});
const lagMax = new Gauge({
name: namePrefix + NODEJS_EVENTLOOP_LAG_MAX,
help: 'The maximum recorded event loop delay.',
registers: registry ? [registry] : undefined
});
const lagMean = new Gauge({
name: namePrefix + NODEJS_EVENTLOOP_LAG_MEAN,
help: 'The mean of the recorded event loop delays.',
registers: registry ? [registry] : undefined
});
const lagStddev = new Gauge({
name: namePrefix + NODEJS_EVENTLOOP_LAG_STDDEV,
help: 'The standard deviation of the recorded event loop delays.',
registers: registry ? [registry] : undefined
});
const lagP50 = new Gauge({
name: namePrefix + NODEJS_EVENTLOOP_LAG_P50,
help: 'The 50th percentile of the recorded event loop delays.',
registers: registry ? [registry] : undefined
});
const lagP90 = new Gauge({
name: namePrefix + NODEJS_EVENTLOOP_LAG_P90,
help: 'The 90th percentile of the recorded event loop delays.',
registers: registry ? [registry] : undefined
});
const lagP99 = new Gauge({
name: namePrefix + NODEJS_EVENTLOOP_LAG_P99,
help: 'The 99th percentile of the recorded event loop delays.',
registers: registry ? [registry] : undefined
});
if (!perf_hooks || !perf_hooks.monitorEventLoopDelay) {
return () => {
const start = process.hrtime();
setImmediate(reportEventloopLag, start, lag);
};
}
const histogram = perf_hooks.monitorEventLoopDelay({
resolution: config.eventLoopMonitoringPrecision
});
histogram.enable();
return () => {
const start = process.hrtime();
setImmediate(reportEventloopLag, start, gauge);
setImmediate(reportEventloopLag, start, lag);
lagMin.set(histogram.min / 1e9);
lagMax.set(histogram.max / 1e9);
lagMean.set(histogram.mean / 1e9);
lagStddev.set(histogram.stddev / 1e9);
lagP50.set(histogram.percentile(50) / 1e9);
lagP90.set(histogram.percentile(90) / 1e9);
lagP99.set(histogram.percentile(99) / 1e9);
};
};
module.exports.metricNames = [NODEJS_EVENTLOOP_LAG];
module.exports.metricNames = [
NODEJS_EVENTLOOP_LAG,
NODEJS_EVENTLOOP_LAG_MIN,
NODEJS_EVENTLOOP_LAG_MAX,
NODEJS_EVENTLOOP_LAG_MEAN,
NODEJS_EVENTLOOP_LAG_STDDEV,
NODEJS_EVENTLOOP_LAG_P50,
NODEJS_EVENTLOOP_LAG_P90,
NODEJS_EVENTLOOP_LAG_P99
];

@@ -20,3 +20,3 @@ 'use strict';

name: namePrefix + NODEJS_HEAP_SIZE_TOTAL,
help: 'Process heap size from node.js in bytes.',
help: 'Process heap size from Node.js in bytes.',
registers

@@ -26,33 +26,19 @@ });

name: namePrefix + NODEJS_HEAP_SIZE_USED,
help: 'Process heap size used from node.js in bytes.',
help: 'Process heap size used from Node.js in bytes.',
registers
});
let externalMemUsed;
const externalMemUsed = new Gauge({
name: namePrefix + NODEJS_EXTERNAL_MEMORY,
help: 'Node.js external memory size in bytes.',
registers
});
const usage = safeMemoryUsage();
if (usage && usage.external) {
externalMemUsed = new Gauge({
name: namePrefix + NODEJS_EXTERNAL_MEMORY,
help: 'Nodejs external memory size in bytes.',
registers
});
}
return () => {
// process.memoryUsage() can throw EMFILE errors, see #67
// process.memoryUsage() can throw on some platforms, see #67
const memUsage = safeMemoryUsage();
if (memUsage) {
if (config.timestamps) {
const now = Date.now();
heapSizeTotal.set(memUsage.heapTotal, now);
heapSizeUsed.set(memUsage.heapUsed, now);
if (memUsage.external && externalMemUsed) {
externalMemUsed.set(memUsage.external, now);
}
} else {
heapSizeTotal.set(memUsage.heapTotal);
heapSizeUsed.set(memUsage.heapUsed);
if (memUsage.external && externalMemUsed) {
externalMemUsed.set(memUsage.external);
}
heapSizeTotal.set(memUsage.heapTotal);
heapSizeUsed.set(memUsage.heapUsed);
if (memUsage.external && externalMemUsed) {
externalMemUsed.set(memUsage.external);
}

@@ -59,0 +45,0 @@ }

'use strict';
const Gauge = require('../gauge');
let v8;
const v8 = require('v8');
try {
v8 = require('v8');
} catch (e) {
// node version is too old
// probably we can use v8-heap-space-statistics for >=node-4.0.0 and <node-6.0.0
}
const METRICS = ['total', 'used', 'available'];
const NODEJS_HEAP_SIZE = {};

@@ -22,9 +14,2 @@

module.exports = (registry, config = {}) => {
if (
typeof v8 === 'undefined' ||
typeof v8.getHeapSpaceStatistics !== 'function'
) {
return () => {};
}
const registers = registry ? [registry] : undefined;

@@ -38,3 +23,3 @@ const namePrefix = config.prefix ? config.prefix : '';

name: namePrefix + NODEJS_HEAP_SIZE[metricType],
help: `Process heap space size ${metricType} from node.js in bytes.`,
help: `Process heap space size ${metricType} from Node.js in bytes.`,
labelNames: ['space'],

@@ -41,0 +26,0 @@ registers

@@ -13,3 +13,3 @@ 'use strict';

if (data.hasOwnProperty(listElement.constructor.name)) {
if (Object.hasOwnProperty.call(data, listElement.constructor.name)) {
data[listElement.constructor.name] += 1;

@@ -23,10 +23,6 @@ } else {

function updateMetrics(gauge, data, includeTimestamp) {
function updateMetrics(gauge, data) {
gauge.reset();
for (const key in data) {
if (includeTimestamp) {
gauge.set({ type: key }, data[key], Date.now());
} else {
gauge.set({ type: key }, data[key]);
}
gauge.set({ type: key }, data[key]);
}

@@ -33,0 +29,0 @@ }

'use strict';
function safeMemoryUsage() {
let memoryUsage;
try {
memoryUsage = process.memoryUsage();
return process.memoryUsage();
} catch (ex) {
// empty
return;
}
return memoryUsage;
}
module.exports = safeMemoryUsage;

@@ -54,14 +54,19 @@ 'use strict';

// Sync I/O is often problematic, but /proc isn't really I/O, it a
// virtual filesystem that maps directly to in-kernel data structures
// and never blocks.
//
// Node.js/libuv do this already for process.memoryUsage(), see:
// - https://github.com/libuv/libuv/blob/a629688008694ed8022269e66826d4d6ec688b83/src/unix/linux-core.c#L506-L523
return () => {
fs.readFile('/proc/self/status', 'utf8', (err, status) => {
if (err) {
return;
}
const now = Date.now();
const structuredOutput = structureOutput(status);
try {
const stat = fs.readFileSync('/proc/self/status', 'utf8');
const structuredOutput = structureOutput(stat);
residentMemGauge.set(structuredOutput.VmRSS, now);
virtualMemGauge.set(structuredOutput.VmSize, now);
heapSizeMemGauge.set(structuredOutput.VmData, now);
});
residentMemGauge.set(structuredOutput.VmRSS);
virtualMemGauge.set(structuredOutput.VmSize);
heapSizeMemGauge.set(structuredOutput.VmData);
} catch (er) {
return;
}
};

@@ -68,0 +73,0 @@ };

@@ -9,7 +9,2 @@ 'use strict';

module.exports = (registry, config = {}) => {
// Don't do anything if the function doesn't exist (introduced in node@6.1.0)
if (typeof process.cpuUsage !== 'function') {
return () => {};
}
const registers = registry ? [registry] : undefined;

@@ -16,0 +11,0 @@ const namePrefix = config.prefix ? config.prefix : '';

@@ -31,15 +31,7 @@ 'use strict';

const updater = config.timestamps
? () => {
const handles = process._getActiveHandles();
updateMetrics(gauge, aggregateByObjectName(handles), true);
totalGauge.set(handles.length, Date.now());
}
: () => {
const handles = process._getActiveHandles();
updateMetrics(gauge, aggregateByObjectName(handles), false);
totalGauge.set(handles.length);
};
return updater;
return () => {
const handles = process._getActiveHandles();
updateMetrics(gauge, aggregateByObjectName(handles));
totalGauge.set(handles.length);
};
};

@@ -46,0 +38,0 @@

@@ -8,11 +8,25 @@ 'use strict';

let maxFds;
module.exports = (registry, config = {}) => {
let isSet = false;
if (process.platform !== 'linux') {
return () => {};
if (maxFds === undefined) {
// This will fail if a linux-like procfs is not available.
try {
const limits = fs.readFileSync('/proc/self/limits', 'utf8');
const lines = limits.split('\n');
lines.find(line => {
if (line.startsWith('Max open files')) {
const parts = line.split(/ +/);
maxFds = Number(parts[1]);
return true;
}
});
} catch (er) {
return () => {};
}
}
if (maxFds === undefined) return () => {};
const namePrefix = config.prefix ? config.prefix : '';
const fileDescriptorsGauge = new Gauge({

@@ -24,19 +38,7 @@ name: namePrefix + PROCESS_MAX_FDS,

return () => {
if (isSet) {
return;
}
fileDescriptorsGauge.set(Number(maxFds));
fs.readFile('/proc/sys/fs/file-max', 'utf8', (err, maxFds) => {
if (err) {
return;
}
isSet = true;
fileDescriptorsGauge.set(Number(maxFds));
});
};
return () => {};
};
module.exports.metricNames = [PROCESS_MAX_FDS];

@@ -23,10 +23,10 @@ 'use strict';

return () => {
fs.readdir('/proc/self/fd', (err, list) => {
if (err) {
return;
}
// Minus 1, as this invocation created one
fileDescriptorsGauge.set(list.length - 1, Date.now());
});
try {
const fds = fs.readdirSync('/proc/self/fd');
// Minus 1 to not count the fd that was used by readdirSync(), its now
// closed.
fileDescriptorsGauge.set(fds.length - 1);
} catch (er) {
return;
}
};

@@ -33,0 +33,0 @@ };

'use strict';
const Gauge = require('../gauge');
const nowInSeconds = Math.round(Date.now() / 1000 - process.uptime());
const startInSeconds = Math.round(Date.now() / 1000 - process.uptime());

@@ -17,13 +17,7 @@ const PROCESS_START_TIME = 'process_start_time_seconds';

});
let isSet = false;
cpuUserGauge.set(startInSeconds);
return () => {
if (isSet) {
return;
}
cpuUserGauge.set(nowInSeconds);
isSet = true;
};
return () => {};
};
module.exports.metricNames = [PROCESS_START_TIME];

@@ -22,20 +22,9 @@ 'use strict';

});
let isSet = false;
nodeVersionGauge
.labels(version, versionSegments[0], versionSegments[1], versionSegments[2])
.set(1);
return () => {
if (isSet) {
return;
}
nodeVersionGauge
.labels(
version,
versionSegments[0],
versionSegments[1],
versionSegments[2]
)
.set(1);
isSet = true;
};
return () => {};
};
module.exports.metricNames = [NODE_VERSION_INFO];

@@ -78,3 +78,3 @@ 'use strict';

if (method !== 'DELETE') {
req.write(this.registry.metrics({ timestamps: false }));
req.write(this.registry.metrics());
}

@@ -81,0 +81,0 @@ req.end();

@@ -14,9 +14,6 @@ 'use strict';

const defaultMetricsOpts = {
timestamps: true
};
class Registry {
constructor() {
this._metrics = {};
this._collectors = [];
this._defaultLabels = {};

@@ -29,4 +26,3 @@ }

getMetricAsPrometheusString(metric, conf) {
const opts = Object.assign({}, defaultMetricsOpts, conf);
getMetricAsPrometheusString(metric) {
const item = metric.get();

@@ -45,7 +41,7 @@ const name = escapeString(item.name);

val.labels = Object.assign({}, val.labels);
}
for (const labelName of defaultLabelNames) {
val.labels[labelName] =
val.labels[labelName] || this._defaultLabels[labelName];
for (const labelName of defaultLabelNames) {
val.labels[labelName] =
val.labels[labelName] || this._defaultLabels[labelName];
}
}

@@ -63,7 +59,3 @@

let line = `${metricName} ${getValueAsString(val.value)}`;
if (opts.timestamps && val.timestamp) {
line += ` ${val.timestamp}`;
}
values += `${line.trim()}\n`;
values += `${metricName} ${getValueAsString(val.value)}\n`;
}

@@ -74,7 +66,9 @@

metrics(opts) {
metrics() {
let metrics = '';
this.collect();
for (const metric of this.getMetricsAsArray()) {
metrics += `${this.getMetricAsPrometheusString(metric, opts)}\n\n`;
metrics += `${this.getMetricAsPrometheusString(metric)}\n\n`;
}

@@ -85,17 +79,30 @@

registerMetric(metricFn) {
if (
this._metrics[metricFn.name] &&
this._metrics[metricFn.name] !== metricFn
) {
registerMetric(metric) {
if (this._metrics[metric.name] && this._metrics[metric.name] !== metric) {
throw new Error(
`A metric with the name ${metricFn.name} has already been registered.`
`A metric with the name ${metric.name} has already been registered.`
);
}
this._metrics[metricFn.name] = metricFn;
this._metrics[metric.name] = metric;
}
registerCollector(collectorFn) {
if (this._collectors.includes(collectorFn)) {
return; // Silently ignore repeated registration.
}
this._collectors.push(collectorFn);
}
collectors() {
return this._collectors;
}
collect() {
this._collectors.forEach(collector => collector());
}
clear() {
this._metrics = {};
this._collectors = [];
this._defaultLabels = {};

@@ -108,7 +115,12 @@ }

this.collect();
for (const metric of this.getMetricsAsArray()) {
const item = metric.get();
if (item.values) {
if (item.values && defaultLabelNames.length > 0) {
for (const val of item.values) {
// Make a copy before mutating
val.labels = Object.assign({}, val.labels);
for (const labelName of defaultLabelNames) {

@@ -115,0 +127,0 @@ val.labels[labelName] =

@@ -14,3 +14,2 @@ /**

isObject,
printDeprecationObjectConstructor,
removeLabels

@@ -30,45 +29,21 @@ } = require('./util');

* Summary
* @param {string} name - Name of the metric
* @param {string} help - Help for the metric
* @param {object|Array.<string>} labelsOrConf - Either array of label names or config object as a key-value object
* @param {object} conf - Configuration object
* @param {config} config - Configuration object.
* @param {string} config.name - Name of the metric
* @param {string} config.help - Help for the metric
* @param {Array.<string>} config.labels - Array with strings, all label keywords supported
*/
constructor(name, help, labelsOrConf, conf) {
let config;
if (isObject(name)) {
config = Object.assign(
{
percentiles: [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999],
labelNames: []
},
name
);
if (!config.registers) {
config.registers = [globalRegistry];
}
} else {
let obj;
let labels = [];
if (Array.isArray(labelsOrConf)) {
obj = conf || {};
labels = labelsOrConf;
} else {
obj = labelsOrConf || {};
}
printDeprecationObjectConstructor();
config = {
name,
help,
labelNames: labels,
percentiles: configurePercentiles(obj.percentiles),
registers: [globalRegistry],
maxAgeSeconds: obj.maxAgeSeconds,
ageBuckets: obj.ageBuckets
};
constructor(config) {
if (!isObject(config)) {
throw new TypeError('constructor expected a config object');
}
config = Object.assign(
{
percentiles: [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999],
labelNames: []
},
config
);
if (!config.registers) {
config.registers = [globalRegistry];
}
validateInput(config.name, config.help, config.labelNames);

@@ -82,3 +57,2 @@

this.aggregator = config.aggregator || 'sum';
this.percentiles = config.percentiles;

@@ -237,13 +211,2 @@ this.hashMap = {};

function configurePercentiles(configuredPercentiles) {
const defaultPercentiles = [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999];
return []
.concat(configuredPercentiles || defaultPercentiles)
.sort(sortAscending);
}
function sortAscending(x, y) {
return x - y;
}
function observe(labels) {

@@ -250,0 +213,0 @@ return value => {

'use strict';
const deprecationsEmitted = {};
exports.isDate = isDate;
exports.getPropertiesFromObj = function(hashMap) {

@@ -31,12 +27,7 @@ const obj = Object.keys(hashMap).map(x => hashMap[x]);

exports.setValue = function setValue(hashMap, value, labels, timestamp) {
exports.setValue = function setValue(hashMap, value, labels) {
const hash = hashObject(labels);
hashMap[hash] = {
value: typeof value === 'number' ? value : 0,
labels: labels || {},
timestamp: isDate(timestamp)
? timestamp.valueOf()
: Number.isFinite(timestamp)
? timestamp
: undefined
labels: labels || {}
};

@@ -83,5 +74,2 @@ return hashMap;

function isDate(obj) {
return obj instanceof Date && !isNaN(obj.valueOf());
}
exports.isObject = function isObject(obj) {

@@ -91,30 +79,2 @@ return obj === Object(obj);

function printDeprecation(msg) {
if (deprecationsEmitted[msg]) {
return;
}
deprecationsEmitted[msg] = true;
if (process.emitWarning) {
process.emitWarning(msg, 'DeprecationWarning');
} else {
// Check can be removed when we only support node@>=6
// eslint-disable-next-line no-console
console.warn(new Error(msg));
}
}
exports.printDeprecationObjectConstructor = () => {
printDeprecation(
'prom-client - Passing a non-object to metrics constructor is deprecated'
);
};
exports.printDeprecationCollectDefaultMetricsNumber = timeout => {
printDeprecation(
`prom-client - A number to defaultMetrics is deprecated, please use \`collectDefaultMetrics({ timeout: ${timeout} })\`.`
);
};
class Grouper extends Map {

@@ -121,0 +81,0 @@ /**

{
"name": "prom-client",
"version": "11.5.3",
"description": "Client for prometheus",
"main": "index.js",
"files": [
"lib/",
"index.js",
"index.d.ts"
],
"engines": {
"node": ">=6.1"
},
"scripts": {
"benchmarks": "node ./benchmarks/index.js",
"test": "npm run lint && npm run compile-typescript && npm run test-unit",
"lint": "eslint .",
"test-unit": "jest",
"compile-typescript": "tsc --project ."
},
"repository": {
"type": "git",
"url": "git@github.com:siimon/prom-client.git"
},
"keywords": [
"Prometheus",
"Metrics",
"Client"
],
"author": "Simon Nyberg",
"license": "Apache-2.0",
"homepage": "https://github.com/siimon/prom-client",
"devDependencies": {
"@clevernature/benchmark-regression": "^1.0.0",
"eslint": "^5.6.0",
"eslint-config-prettier": "^4.3.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-prettier": "^3.0.1",
"express": "^4.13.3",
"husky": "^1.3.1",
"jest": "^24.8.0",
"lint-staged": "^7.0.0",
"lolex": "^4.0.1",
"prettier": "1.17.1",
"typescript": "^3.0.3"
},
"dependencies": {
"tdigest": "^0.1.1"
},
"types": "./index.d.ts",
"jest": {
"testEnvironment": "node",
"testRegex": ".*Test\\.js$"
},
"lint-staged": {
"*.js": [
"eslint --fix",
"git add"
],
"*.{ts,md,json,yml}": [
"prettier --write",
"git add"
],
".{eslintrc,travis.yml}": [
"prettier --write",
"git add"
]
},
"prettier": {
"singleQuote": true,
"useTabs": true,
"overrides": [
{
"files": "*.md",
"options": {
"useTabs": false
}
},
{
"files": ".eslintrc",
"options": {
"parser": "json"
}
}
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
"name": "prom-client",
"version": "12.0.0",
"description": "Client for prometheus",
"main": "index.js",
"files": [
"lib/",
"index.js",
"index.d.ts"
],
"engines": {
"node": ">=10"
},
"scripts": {
"benchmarks": "node ./benchmarks/index.js",
"test": "npm run lint && npm run compile-typescript && npm run test-unit",
"lint": "eslint .",
"test-unit": "jest",
"compile-typescript": "tsc --project ."
},
"repository": {
"type": "git",
"url": "git@github.com:siimon/prom-client.git"
},
"keywords": [
"Prometheus",
"Metrics",
"Client"
],
"author": "Simon Nyberg",
"license": "Apache-2.0",
"homepage": "https://github.com/siimon/prom-client",
"devDependencies": {
"@clevernature/benchmark-regression": "^1.0.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-prettier": "^3.0.1",
"express": "^4.13.3",
"husky": "^4.2.1",
"jest": "^25.1.0",
"lint-staged": "^10.0.4",
"lolex": "^5.1.2",
"prettier": "1.19.1",
"typescript": "^3.0.3"
},
"dependencies": {
"tdigest": "^0.1.1"
},
"types": "./index.d.ts",
"jest": {
"testEnvironment": "node",
"testRegex": ".*Test\\.js$"
},
"lint-staged": {
"*.js": "eslint --fix",
"*.{ts,md,json,yml}": "prettier --write",
".{eslintrc,travis.yml}": "prettier --write"
},
"prettier": {
"singleQuote": true,
"useTabs": true,
"overrides": [
{
"files": "*.md",
"options": {
"useTabs": false
}
},
{
"files": ".eslintrc",
"options": {
"parser": "json"
}
}
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
}

@@ -1,2 +0,2 @@

# Prometheus client for node.js [![Build Status](https://travis-ci.org/siimon/prom-client.svg?branch=master)](https://travis-ci.org/siimon/prom-client) [![Build status](https://ci.appveyor.com/api/projects/status/k2e0gwonkcee3lp9/branch/master?svg=true)](https://ci.appveyor.com/project/siimon/prom-client/branch/master)
# Prometheus client for node.js [![Build Status](https://travis-ci.org/siimon/prom-client.svg?branch=master)](https://travis-ci.org/siimon/prom-client) [![Build status](https://ci.appveyor.com/api/projects/status/k2e0gwonkcee3lp9/branch/master?svg=true)](https://ci.appveyor.com/project/siimon/prom-client/branch/master) [![Actions Status](https://github.com/siimon/prom-client/workflows/Node.js%20CI/badge.svg?branch=master)](https://github.com/siimon/prom-client/actions)

@@ -51,19 +51,12 @@ A prometheus client for node.js that supports histogram, summaries, gauges and

In addition, some Node-specific metrics are included, such as event loop lag,
active handles and Node.js version. See what metrics there are in
active handles, GC and Node.js version. See what metrics there are in
[lib/metrics](lib/metrics).
`collectDefaultMetrics` takes 1 options object with 3 entries, a timeout for how
often the probe should be fired, an optional prefix for metric names
and a registry to which metrics should be registered. By default probes are
launched every 10 seconds, but this can be modified like this:
`collectDefaultMetrics` optionally accepts a config object with following entries:
```js
const client = require('prom-client');
- `prefix` an optional prefix for metric names. Default: no prefix.
- `registry` to which metrics should be registered. Default: the global default registry.
- `gcDurationBuckets` with custom buckets for GC duration histogram. Default buckets of GC duration histogram are `[0.001, 0.01, 0.1, 1, 2, 5]` (in seconds).
- `eventLoopMonitoringPrecision` with sampling rate in milliseconds. Must be greater than zero. Default: 10.
const collectDefaultMetrics = client.collectDefaultMetrics;
// Probe every 5th second.
collectDefaultMetrics({ timeout: 5000 });
```
To register metrics to another registry, pass it in as `register`:

@@ -77,7 +70,6 @@

const register = new Registry();
collectDefaultMetrics({ register });
```
To prefix metric names with your own arbitrary string, pass in a `prefix`:
To use custom buckets for GC duration histogram, pass it in as `gcDurationBuckets`:

@@ -89,15 +81,12 @@ ```js

// Probe every 5th second.
collectDefaultMetrics({ prefix: 'my_application_' });
collectDefaultMetrics({ gcDurationBuckets: [0.1, 0.2, 0.3] });
```
To disable metric timestamps set `timestamps` to `false` (You can find the list of metrics that support this feature in `test/defaultMetricsTest.js`):
To prefix metric names with your own arbitrary string, pass in a `prefix`:
```js
const client = require('prom-client');
const collectDefaultMetrics = client.collectDefaultMetrics;
// Probe every 5th second.
collectDefaultMetrics({ timestamps: false });
const prefix = 'my_application_';
collectDefaultMetrics({ prefix });
```

@@ -191,3 +180,3 @@

The defaults buckets are intended to cover usual web/rpc requests, this can
however be overriden.
however be overridden.

@@ -231,3 +220,3 @@ ```js

xhrRequest(function(err, res) {
end(); // Observes the value to xhrRequests duration in seconds
const seconds = end(); // Observes and returns the value to xhrRequests duration in seconds
});

@@ -243,3 +232,3 @@ ```

The default percentiles are: 0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999. But they
can be overriden like this:
can be overridden like this:

@@ -346,18 +335,2 @@ ```js

### Timestamps
Counter and gauge metrics can take a timestamp argument after the value
argument. This argument must be a Date or a number (milliseconds since Unix
epoch, i.e. 1970-01-01 00:00:00 UTC, excluding leap seconds).
```js
gauge.set(100, 1485531442231); // Set gauge value and timestamp as milliseconds since Unix epoch
gauge.set(100, Date.now()); // Set gauge value and timestamp as milliseconds since Unix epoch
gauge.set(100, new Date()); // Set gauge value and timestamp as Date
gauge.set({ method: 'GET', statusCode: '200' }, 100, new Date()); // Set gauge value and timestamp with labels
gauge.labels('GET', '200').set(100, new Date()); // Same as above
counter.inc(1, new Date()); // Increment counter with timestamp
```
### Multiple registries

@@ -412,5 +385,2 @@

`register.metrics()` takes an optional object with a `timestamps` field. Setting
this to false will strip timestamps from the string.
#### Getting a single metric for Prometheus displaying

@@ -467,5 +437,2 @@

Note that timestamps will be stripped before the metrics are pushed, since
pushgateway >= 0.4 does not accept timestamps.
```js

@@ -490,3 +457,3 @@ const client = require('prom-client');

### Utilites
### Utilities

@@ -493,0 +460,0 @@ For convenience, there are 2 bucket generator functions - linear and

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc