prom-client
Advanced tools
Comparing version 9.1.1 to 10.0.0
# Changelog | ||
All noteable changes to this project will be documented in this file. | ||
All notable changes to this project will be documented in this file. | ||
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). | ||
## Unrelased | ||
## [Unreleased] | ||
### Breaking | ||
### Added | ||
### Changed | ||
## [10.0.0] - 2017-07-04 | ||
### Breaking | ||
- Print deprecation warning when metrics are constructed using non-objects | ||
- Print deprecation warning when `collectDefaultMetrics` is called with a number | ||
### Added | ||
- Ability to set default labels by registry | ||
- Allow passing in `registry` as second argument to `collectDefaultMetrics` to use that instead of the default registry | ||
### Changed | ||
- Convert code base to ES2015 code (node 4) | ||
- add engines field to package.json | ||
- Use object shorthand | ||
- Remove `util-extend` in favor of `Object.assign` | ||
- Arrow functions over binding or putting `this` in a variable | ||
- Use template strings | ||
- `prototype` -> `class` | ||
## [9.1.1] - 2017-06-17 | ||
### Changed | ||
- Don't set timestamps for metrics that are never updated | ||
## [9.1.0] - 2017-06-07 | ||
@@ -28,1 +49,8 @@ ### Added | ||
- Creating metrics with one argument per parameter - use object literals instead. | ||
[Unreleased]: https://github.com/siimon/prom-client/compare/v10.0.0...HEAD | ||
[10.0.0]: https://github.com/siimon/prom-client/compare/v9.1.1...v10.0.0 | ||
[9.1.1]: https://github.com/siimon/prom-client/compare/v9.1.0...v9.1.1 | ||
[9.1.0]: https://github.com/siimon/prom-client/compare/v9.0.0...v9.1.0 | ||
[9.0.0]: https://github.com/siimon/prom-client/commit/1ef835f908e1a5032f228bbc754479fe7ccf5201 |
268
index.d.ts
@@ -11,11 +11,14 @@ // Type definitions for prom-client | ||
*/ | ||
metrics(): string | ||
metrics(): string; | ||
/** | ||
* Remove all metrics from the registry | ||
*/ | ||
clear(): void | ||
clear(): void; | ||
/** | ||
* Get all metrics as objects | ||
*/ | ||
getMetricsAsJSON(): metric[] | ||
getMetricsAsJSON(): metric[]; | ||
/** | ||
@@ -25,3 +28,4 @@ * Remove a single metric | ||
*/ | ||
removeSingleMetric(name: string): void | ||
removeSingleMetric(name: string): void; | ||
/** | ||
@@ -31,13 +35,22 @@ * Get a single metric | ||
*/ | ||
getSingleMetric(name:string): Metric | ||
getSingleMetric(name: string): Metric; | ||
/** | ||
* Set static labels to every metric emitted by this registry | ||
* @param object of name/value pairs: | ||
* { defaultLabel: "value", anotherLabel: "value 2" } | ||
*/ | ||
setDefaultLabels(labels: Object): void; | ||
/** | ||
* Get a string representation of a single metric by name | ||
* @param name The name of the metric | ||
*/ | ||
getSingleMetricAsString(name:string): string | ||
getSingleMetricAsString(name: string): string; | ||
/** | ||
* Merge registers | ||
* @param registers The registers you want to merge together | ||
*/ | ||
merge(registers: Registry[]): Registry | ||
* Merge registers | ||
* @param registers The registers you want to merge together | ||
*/ | ||
static merge(registers: Registry[]): Registry; | ||
} | ||
@@ -48,8 +61,8 @@ | ||
*/ | ||
export const register: Registry | ||
export const register: Registry; | ||
/** | ||
* General metric type | ||
*/ | ||
export type Metric = Counter | Gauge | Summary | Histogram | ||
* General metric type | ||
*/ | ||
export type Metric = Counter | Gauge | Summary | Histogram; | ||
@@ -64,15 +77,16 @@ export enum MetricType { | ||
interface metric { | ||
name: string, | ||
help: string, | ||
type: MetricType | ||
name: string; | ||
help: string; | ||
type: MetricType; | ||
} | ||
interface labelValues { | ||
[key: string]: string|number | ||
[key: string]: string | number; | ||
} | ||
export interface CounterConfiguration { | ||
name: string, | ||
help: string, | ||
labelNames?: string [], | ||
registers?: Registry[] | ||
name: string; | ||
help: string; | ||
labelNames?: string[]; | ||
registers?: Registry[]; | ||
} | ||
@@ -84,7 +98,6 @@ | ||
export class Counter { | ||
/** | ||
* @param configuration Configuration when creating a Counter metric. Name and Help is required. | ||
*/ | ||
constructor(configuration: CounterConfiguration) | ||
constructor(configuration: CounterConfiguration); | ||
@@ -95,4 +108,5 @@ /** | ||
* @param labels Label keys | ||
* @deprecated | ||
*/ | ||
constructor(name: string, help: string, labels?: string[]) | ||
constructor(name: string, help: string, labels?: string[]); | ||
@@ -105,3 +119,3 @@ /** | ||
*/ | ||
inc(labels: labelValues, value?: number, timestamp?: number|Date): void | ||
inc(labels: labelValues, value?: number, timestamp?: number | Date): void; | ||
@@ -113,3 +127,3 @@ /** | ||
*/ | ||
inc(value?: number, timestamp?: number|Date): void | ||
inc(value?: number, timestamp?: number | Date): void; | ||
@@ -121,6 +135,5 @@ /** | ||
*/ | ||
labels(...values: string[]): Counter.Internal | ||
labels(...values: string[]): Counter.Internal; | ||
} | ||
export namespace Counter { | ||
@@ -133,23 +146,21 @@ interface Internal { | ||
*/ | ||
inc(value?: number, timestamp?: number|Date): void | ||
inc(value?: number, timestamp?: number | Date): void; | ||
} | ||
} | ||
export interface GaugeConfiguration{ | ||
name: string, | ||
help: string, | ||
labelNames?: string[], | ||
registers?: Registry[] | ||
export interface GaugeConfiguration { | ||
name: string; | ||
help: string; | ||
labelNames?: string[]; | ||
registers?: Registry[]; | ||
} | ||
/** | ||
A gauge is a metric that represents a single numerical value that can arbitrarily go up and down. | ||
*/ | ||
* A gauge is a metric that represents a single numerical value that can arbitrarily go up and down. | ||
*/ | ||
export class Gauge { | ||
/** | ||
* @param configuration Configuration when creating a Gauge metric. Name and Help is mandatory | ||
*/ | ||
constructor(configuration: GaugeConfiguration) | ||
constructor(configuration: GaugeConfiguration); | ||
@@ -160,4 +171,5 @@ /** | ||
* @param labels Label keys | ||
* @deprecated | ||
*/ | ||
constructor(name: string, help: string, labels?: string[]) | ||
constructor(name: string, help: string, labels?: string[]); | ||
@@ -170,3 +182,3 @@ /** | ||
*/ | ||
inc(labels: labelValues, value?: number, timestamp?: number|Date): void | ||
inc(labels: labelValues, value?: number, timestamp?: number | Date): void; | ||
@@ -178,3 +190,3 @@ /** | ||
*/ | ||
inc(value?: number, timestamp?: number|Date): void | ||
inc(value?: number, timestamp?: number | Date): void; | ||
@@ -187,3 +199,3 @@ /** | ||
*/ | ||
dec(labels: labelValues, value?: number, timestamp?: number|Date): void | ||
dec(labels: labelValues, value?: number, timestamp?: number | Date): void; | ||
@@ -195,5 +207,4 @@ /** | ||
*/ | ||
dec(value?: number, timestamp?: number|Date): void | ||
dec(value?: number, timestamp?: number | Date): void; | ||
/** | ||
@@ -205,3 +216,3 @@ * Set gauge value for labels | ||
*/ | ||
set(labels: labelValues, value: number, timestamp?: number|Date): void | ||
set(labels: labelValues, value: number, timestamp?: number | Date): void; | ||
@@ -213,3 +224,3 @@ /** | ||
*/ | ||
set(value: number, timestamp?: number|Date): void | ||
set(value: number, timestamp?: number | Date): void; | ||
@@ -220,3 +231,3 @@ /** | ||
*/ | ||
setToCurrentTime(labels?: labelValues): void | ||
setToCurrentTime(labels?: labelValues): void; | ||
@@ -228,3 +239,3 @@ /** | ||
*/ | ||
startTimer(labels?: labelValues): (labels?: labelValues) => void | ||
startTimer(labels?: labelValues): (labels?: labelValues) => void; | ||
@@ -236,3 +247,3 @@ /** | ||
*/ | ||
labels(...values: string[]): Gauge.Internal | ||
labels(...values: string[]): Gauge.Internal; | ||
} | ||
@@ -247,3 +258,3 @@ | ||
*/ | ||
inc(value?: number, timestamp?: number|Date): void | ||
inc(value?: number, timestamp?: number | Date): void; | ||
@@ -255,3 +266,3 @@ /** | ||
*/ | ||
dec(value?: number, timestamp?: number|Date): void | ||
dec(value?: number, timestamp?: number | Date): void; | ||
@@ -263,8 +274,8 @@ /** | ||
*/ | ||
set(value: number, timestamp?: number|Date): void | ||
set(value: number, timestamp?: number | Date): void; | ||
/** | ||
* Set gauge value to current epoch time in ms | ||
* Set gauge value to current epoch time in ms | ||
*/ | ||
setToCurrentTime(): void | ||
setToCurrentTime(): void; | ||
@@ -275,3 +286,3 @@ /** | ||
*/ | ||
startTimer(): (labels?: labelValues) => void | ||
startTimer(): (labels?: labelValues) => void; | ||
} | ||
@@ -281,7 +292,7 @@ } | ||
export interface HistogramConfiguration { | ||
name: string, | ||
help: string, | ||
labelNames?: string[], | ||
buckets?: number[], | ||
registers?: Registry[] | ||
name: string; | ||
help: string; | ||
labelNames?: string[]; | ||
buckets?: number[]; | ||
registers?: Registry[]; | ||
} | ||
@@ -293,7 +304,6 @@ | ||
export class Histogram { | ||
/** | ||
* @param configuration Configuration when creating the Histogram. Name and Help is mandatory | ||
*/ | ||
constructor(configuration: HistogramConfiguration) | ||
constructor(configuration: HistogramConfiguration); | ||
@@ -306,3 +316,8 @@ /** | ||
*/ | ||
constructor(name: string, help: string, labels?: string[], config?: Histogram.Config) | ||
constructor( | ||
name: string, | ||
help: string, | ||
labels?: string[], | ||
config?: Histogram.Config | ||
); | ||
/** | ||
@@ -312,4 +327,5 @@ * @param name The name of metric | ||
* @param config Configuration object for Histograms | ||
* @deprecated | ||
*/ | ||
constructor(name: string, help: string, config: Histogram.Config) | ||
constructor(name: string, help: string, config: Histogram.Config); | ||
@@ -320,3 +336,3 @@ /** | ||
*/ | ||
observe(value: number): void | ||
observe(value: number): void; | ||
/** | ||
@@ -327,3 +343,4 @@ * Observe value for given labels | ||
*/ | ||
observe(labels: labelValues, value: number): void | ||
observe(labels: labelValues, value: number): void; | ||
/** | ||
@@ -334,7 +351,9 @@ * Start a timer where the value in seconds will observed | ||
*/ | ||
startTimer(labels?: labelValues): (labels?: labelValues) => void | ||
startTimer(labels?: labelValues): (labels?: labelValues) => void; | ||
/** | ||
* Reset histogram values | ||
*/ | ||
reset(): void | ||
reset(): void; | ||
/** | ||
@@ -345,3 +364,3 @@ * Return the child for given labels | ||
*/ | ||
labels(...values: string[]): Histogram.Internal | ||
labels(...values: string[]): Histogram.Internal; | ||
} | ||
@@ -355,3 +374,4 @@ | ||
*/ | ||
observe(value: number): void | ||
observe(value: number): void; | ||
/** | ||
@@ -362,3 +382,3 @@ * Start a timer where the value in seconds will observed | ||
*/ | ||
startTimer(): (labels?: labelValues) => void | ||
startTimer(): (labels?: labelValues) => void; | ||
} | ||
@@ -370,12 +390,12 @@ | ||
*/ | ||
buckets?: number[] | ||
buckets?: number[]; | ||
} | ||
} | ||
export interface SummaryConfiguration{ | ||
name: string, | ||
help: string, | ||
labelNames?: string[] | ||
percentiles?: number[], | ||
registers?: Registry[] | ||
export interface SummaryConfiguration { | ||
name: string; | ||
help: string; | ||
labelNames?: string[]; | ||
percentiles?: number[]; | ||
registers?: Registry[]; | ||
} | ||
@@ -387,7 +407,6 @@ | ||
export class Summary { | ||
/** | ||
* @param configuration Configuration when creating Summary metric. Name and Help is mandatory | ||
*/ | ||
constructor(configuration: SummaryConfiguration) | ||
constructor(configuration: SummaryConfiguration); | ||
@@ -400,3 +419,8 @@ /** | ||
*/ | ||
constructor(name: string, help: string, labels?: string[], config?: Summary.Config) | ||
constructor( | ||
name: string, | ||
help: string, | ||
labels?: string[], | ||
config?: Summary.Config | ||
); | ||
/** | ||
@@ -406,4 +430,5 @@ * @param name The name of the metric | ||
* @param config Configuration object | ||
* @deprecated | ||
*/ | ||
constructor(name: string, help: string, config: Summary.Config) | ||
constructor(name: string, help: string, config: Summary.Config); | ||
@@ -414,3 +439,3 @@ /** | ||
*/ | ||
observe(value: number): void | ||
observe(value: number): void; | ||
/** | ||
@@ -421,3 +446,4 @@ * Observe value for given labels | ||
*/ | ||
observe(labels: labelValues, value: number): void | ||
observe(labels: labelValues, value: number): void; | ||
/** | ||
@@ -428,7 +454,8 @@ * Start a timer where the value in seconds will observed | ||
*/ | ||
startTimer(labels?: labelValues): (labels?: labelValues) => void | ||
startTimer(labels?: labelValues): (labels?: labelValues) => void; | ||
/** | ||
* Reset all values in the summary | ||
*/ | ||
reset(): void | ||
reset(): void; | ||
@@ -440,3 +467,3 @@ /** | ||
*/ | ||
labels(...values: string[]): Summary.Internal | ||
labels(...values: string[]): Summary.Internal; | ||
} | ||
@@ -450,3 +477,4 @@ | ||
*/ | ||
observe(value: number): void | ||
observe(value: number): void; | ||
/** | ||
@@ -457,3 +485,3 @@ * Start a timer where the value in seconds will observed | ||
*/ | ||
startTimer(): (labels?: labelValues) => void | ||
startTimer(): (labels?: labelValues) => void; | ||
} | ||
@@ -465,3 +493,3 @@ | ||
*/ | ||
percentiles?: number[] | ||
percentiles?: number[]; | ||
} | ||
@@ -479,3 +507,3 @@ } | ||
*/ | ||
constructor(url: string, options?: any, registry?: Registry) | ||
constructor(url: string, options?: any, registry?: Registry); | ||
@@ -487,3 +515,7 @@ /** | ||
*/ | ||
pushAdd(params: Pushgateway.Parameters, callback: (error?: Error, httpResponse?: any, body?: any) => void): void; | ||
pushAdd( | ||
params: Pushgateway.Parameters, | ||
callback: (error?: Error, httpResponse?: any, body?: any) => void | ||
): void; | ||
/** | ||
@@ -494,3 +526,7 @@ * Overwrite all metric (using PUT to Pushgateway) | ||
*/ | ||
push(params: Pushgateway.Parameters, callback: (error?: Error, httpResponse?: any, body?: any) => void): void; | ||
push( | ||
params: Pushgateway.Parameters, | ||
callback: (error?: Error, httpResponse?: any, body?: any) => void | ||
): void; | ||
/** | ||
@@ -501,3 +537,6 @@ * Delete all metrics for jobName | ||
*/ | ||
delete(params: Pushgateway.Parameters, callback: (error?: Error, httpResponse?: any, body?: any) => void): void; | ||
delete( | ||
params: Pushgateway.Parameters, | ||
callback: (error?: Error, httpResponse?: any, body?: any) => void | ||
): void; | ||
} | ||
@@ -510,3 +549,3 @@ | ||
*/ | ||
jobName: string, | ||
jobName: string; | ||
/** | ||
@@ -516,4 +555,4 @@ * Label sets used in the url when making a request to the Pushgateway, | ||
groupings?: { | ||
[key: string]: string | ||
} | ||
[key: string]: string; | ||
}; | ||
} | ||
@@ -529,3 +568,8 @@ } | ||
*/ | ||
export function linearBuckets(start: number, width: number, count: number): number[] | ||
export function linearBuckets( | ||
start: number, | ||
width: number, | ||
count: number | ||
): number[]; | ||
/** | ||
@@ -538,15 +582,29 @@ * Create an array that grows exponentially | ||
*/ | ||
export function exponentialBuckets(start: number, factor: number, count: number): number[] | ||
export function exponentialBuckets( | ||
start: number, | ||
factor: number, | ||
count: number | ||
): number[]; | ||
export interface DefaultMetricsCollectorConfiguration { | ||
interval?: number; | ||
registry?: Registry; | ||
} | ||
/** | ||
* Configure default metrics | ||
* @param interval The interval how often the default metrics should be probed | ||
* @param config Configuration object for default metrics collector | ||
* @return The setInterval number | ||
*/ | ||
export function collectDefaultMetrics(interval: number): number | ||
export function collectDefaultMetrics( | ||
config?: DefaultMetricsCollectorConfiguration | ||
): number; | ||
/** | ||
* Configure default metrics | ||
* @param interval The interval how often the default metrics should be probed | ||
* @deprecated | ||
* @return The setInterval number | ||
*/ | ||
export function collectDefaultMetrics(): number | ||
export function collectDefaultMetrics(interval: number): number; | ||
@@ -557,3 +615,3 @@ export interface defaultMetrics { | ||
*/ | ||
metricsList: string[] | ||
metricsList: string[]; | ||
} |
@@ -8,5 +8,5 @@ /** | ||
exports.register = require('./lib/register'); | ||
exports.register = require('./lib/registry').globalRegistry; | ||
exports.Registry = require('./lib/registry'); | ||
exports.contentType = require('./lib/register').contentType; | ||
exports.contentType = require('./lib/registry').globalRegistry.contentType; | ||
@@ -13,0 +13,0 @@ exports.Counter = require('./lib/counter'); |
'use strict'; | ||
exports.linearBuckets = function(start, width, count) { | ||
if(count < 1) { | ||
exports.linearBuckets = (start, width, count) => { | ||
if (count < 1) { | ||
throw new Error('Linear buckets needs a positive count'); | ||
} | ||
var buckets = new Array(count); | ||
for(var i = 0; i < count; i++) { | ||
const buckets = new Array(count); | ||
for (let i = 0; i < count; i++) { | ||
buckets[i] = start; | ||
@@ -16,14 +16,14 @@ start += width; | ||
exports.exponentialBuckets = function(start, factor, count) { | ||
if(start <= 0) { | ||
exports.exponentialBuckets = (start, factor, count) => { | ||
if (start <= 0) { | ||
throw new Error('Exponential buckets needs a positive start'); | ||
} | ||
if(count < 1) { | ||
if (count < 1) { | ||
throw new Error('Exponential buckets needs a positive count'); | ||
} | ||
if(factor <= 1) { | ||
if (factor <= 1) { | ||
throw new Error('Exponential buckets needs a factor greater than 1'); | ||
} | ||
var buckets = new Array(count); | ||
for(var i = 0; i < count; i++) { | ||
const buckets = new Array(count); | ||
for (let i = 0; i < count; i++) { | ||
buckets[i] = start; | ||
@@ -30,0 +30,0 @@ start *= factor; |
@@ -5,118 +5,124 @@ /** | ||
'use strict'; | ||
var globalRegistry = require('./register'); | ||
var type = 'counter'; | ||
var isNumber = require('./util').isNumber; | ||
var isDate = require('./util').isDate; | ||
var getProperties = require('./util').getPropertiesFromObj; | ||
var hashObject = require('./util').hashObject; | ||
var validateLabels = require('./validation').validateLabel; | ||
var validateMetricName = require('./validation').validateMetricName; | ||
var validateLabelNames = require('./validation').validateLabelName; | ||
var isObject = require('./util').isObject; | ||
var extend = require('util-extend'); | ||
const globalRegistry = require('./registry').globalRegistry; | ||
const type = 'counter'; | ||
const isNumber = require('./util').isNumber; | ||
const isDate = require('./util').isDate; | ||
const getProperties = require('./util').getPropertiesFromObj; | ||
const hashObject = require('./util').hashObject; | ||
const validateLabels = require('./validation').validateLabel; | ||
const validateMetricName = require('./validation').validateMetricName; | ||
const validateLabelNames = require('./validation').validateLabelName; | ||
const isObject = require('./util').isObject; | ||
const printDeprecationObjectConstructor = require('./util') | ||
.printDeprecationObjectConstructor; | ||
var getLabels = require('./util').getLabels; | ||
const getLabels = require('./util').getLabels; | ||
/** | ||
* Counter | ||
* @param {string} name - Name of the metric | ||
* @param {string} help - Help description for the metric | ||
* @param {Array.<string>} labels - Labels | ||
* @constructor | ||
*/ | ||
function Counter(name, help, labels) { | ||
var config; | ||
if(isObject(name)) { | ||
config = extend({ | ||
labelNames: [], | ||
registers: [ globalRegistry ] | ||
}, name); | ||
} else { | ||
//Backwards compability - will be depricated | ||
config = { | ||
name: name, | ||
help: help, | ||
labelNames: labels, | ||
registers: [ globalRegistry ] | ||
}; | ||
} | ||
class Counter { | ||
/** | ||
* Counter | ||
* @param {string} name - Name of the metric | ||
* @param {string} help - Help description for the metric | ||
* @param {Array.<string>} labels - Labels | ||
*/ | ||
constructor(name, help, labels) { | ||
let config; | ||
if (isObject(name)) { | ||
config = Object.assign( | ||
{ | ||
labelNames: [] | ||
}, | ||
name | ||
); | ||
if(!config.help) { | ||
throw new Error('Missing mandatory help parameter'); | ||
} | ||
if(!config.name) { | ||
throw new Error('Missing mandatory name parameter'); | ||
} | ||
if(!validateMetricName(config.name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
if (!config.registers) { | ||
config.registers = [globalRegistry]; | ||
} | ||
} else { | ||
printDeprecationObjectConstructor(); | ||
if(!validateLabelNames(config.labelNames)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
config = { | ||
name, | ||
help, | ||
labelNames: labels, | ||
registers: [globalRegistry] | ||
}; | ||
} | ||
this.name = name; | ||
this.name = config.name; | ||
this.hashMap = {}; | ||
if (!config.help) { | ||
throw new Error('Missing mandatory help parameter'); | ||
} | ||
if (!config.name) { | ||
throw new Error('Missing mandatory name parameter'); | ||
} | ||
if (!validateMetricName(config.name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
this.labelNames = (config.labelNames || []); | ||
if (!validateLabelNames(config.labelNames)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
this.help = config.help; | ||
this.name = config.name; | ||
this.hashMap = {}; | ||
var metric = this; | ||
config.registers.forEach(function(registryInstance) { | ||
registryInstance.registerMetric(metric); | ||
}); | ||
} | ||
this.labelNames = config.labelNames || []; | ||
/** | ||
* Increment counter | ||
* @param {object} labels - What label you want to be incremented | ||
* @param {Number} value - Value to increment, if omitted increment with 1 | ||
* @param {(Number|Date)} timestamp - Timestamp to set the counter to | ||
* @returns {void} | ||
*/ | ||
Counter.prototype.inc = function(labels, value, timestamp) { | ||
if(isNumber(labels) || !labels) { | ||
return inc.call(this, null)(labels, value); | ||
this.help = config.help; | ||
config.registers.forEach(registryInstance => | ||
registryInstance.registerMetric(this) | ||
); | ||
} | ||
var hash = hashObject(labels); | ||
return inc.call(this, labels, hash)(value, timestamp); | ||
}; | ||
/** | ||
* Increment counter | ||
* @param {object} labels - What label you want to be incremented | ||
* @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) { | ||
if (isNumber(labels) || !labels) { | ||
return inc.call(this, null)(labels, value); | ||
} | ||
Counter.prototype.get = function() { | ||
return { | ||
help: this.help, | ||
name: this.name, | ||
type: type, | ||
values: getProperties(this.hashMap) | ||
}; | ||
}; | ||
const hash = hashObject(labels); | ||
return inc.call(this, labels, hash)(value, timestamp); | ||
} | ||
Counter.prototype.labels = function() { | ||
var labels = getLabels(this.labelNames, arguments) || {}; | ||
var hash = hashObject(labels); | ||
validateLabels(this.labelNames, labels); | ||
return { | ||
inc: inc.call(this, labels, hash) | ||
}; | ||
}; | ||
get() { | ||
return { | ||
help: this.help, | ||
name: this.name, | ||
type, | ||
values: getProperties(this.hashMap) | ||
}; | ||
} | ||
var inc = function(labels, hash) { | ||
var that = this; | ||
return function(value, timestamp) { | ||
if(value && !isNumber(value)) { | ||
labels() { | ||
const labels = getLabels(this.labelNames, arguments) || {}; | ||
const hash = hashObject(labels); | ||
validateLabels(this.labelNames, labels); | ||
return { | ||
inc: inc.call(this, labels, hash) | ||
}; | ||
} | ||
} | ||
const inc = function(labels, hash) { | ||
return (value, timestamp) => { | ||
if (value && !isNumber(value)) { | ||
throw new Error('Value is not a valid number', value); | ||
} | ||
if(timestamp && !isDate(timestamp) && !isNumber(timestamp)) { | ||
if (timestamp && !isDate(timestamp) && !isNumber(timestamp)) { | ||
throw new Error('Timestamp is not a valid date or number', value); | ||
} | ||
if(value < 0) { | ||
if (value < 0) { | ||
throw new Error('It is not possible to decrease a counter'); | ||
} | ||
var incValue = value === null || value === undefined ? 1 : value; | ||
const incValue = value === null || value === undefined ? 1 : value; | ||
that.hashMap = createValue(that.hashMap, incValue, timestamp, labels, hash); | ||
this.hashMap = createValue(this.hashMap, incValue, timestamp, labels, hash); | ||
}; | ||
@@ -126,12 +132,14 @@ }; | ||
function createValue(hashMap, value, timestamp, labels, hash) { | ||
timestamp = isDate(timestamp) ? timestamp.valueOf() : isNumber(timestamp) ? timestamp : undefined; | ||
if(hashMap[hash]) { | ||
timestamp = isDate(timestamp) | ||
? timestamp.valueOf() | ||
: isNumber(timestamp) ? timestamp : undefined; | ||
if (hashMap[hash]) { | ||
hashMap[hash].value += value; | ||
hashMap[hash].timestamp = timestamp; | ||
} else { | ||
hashMap[hash] = { value: value, labels: labels || {}, timestamp: timestamp }; | ||
hashMap[hash] = { value, labels: labels || {}, timestamp }; | ||
} | ||
return hashMap; | ||
}; | ||
} | ||
module.exports = Counter; |
'use strict'; | ||
var processCpuTotal = require('./metrics/processCpuTotal'); | ||
var processStartTime = require('./metrics/processStartTime'); | ||
var osMemoryHeap = require('./metrics/osMemoryHeap'); | ||
var processOpenFileDescriptors = require('./metrics/processOpenFileDescriptors'); | ||
var processMaxFileDescriptors = require('./metrics/processMaxFileDescriptors'); | ||
var eventLoopLag = require('./metrics/eventLoopLag'); | ||
var processHandles = require('./metrics/processHandles'); | ||
var processRequests = require('./metrics/processRequests'); | ||
var heapSizeAndUsed = require('./metrics/heapSizeAndUsed'); | ||
var heapSpacesSizeAndUsed = require('./metrics/heapSpacesSizeAndUsed'); | ||
var version = require('./metrics/version'); | ||
var register = require('./register'); | ||
const processCpuTotal = require('./metrics/processCpuTotal'); | ||
const processStartTime = require('./metrics/processStartTime'); | ||
const osMemoryHeap = require('./metrics/osMemoryHeap'); | ||
const processOpenFileDescriptors = require('./metrics/processOpenFileDescriptors'); | ||
const processMaxFileDescriptors = require('./metrics/processMaxFileDescriptors'); | ||
const eventLoopLag = require('./metrics/eventLoopLag'); | ||
const processHandles = require('./metrics/processHandles'); | ||
const processRequests = require('./metrics/processRequests'); | ||
const heapSizeAndUsed = require('./metrics/heapSizeAndUsed'); | ||
const heapSpacesSizeAndUsed = require('./metrics/heapSpacesSizeAndUsed'); | ||
const version = require('./metrics/version'); | ||
const globalRegistry = require('./registry').globalRegistry; | ||
const printDeprecationCollectDefaultMetricsNumber = require('./util') | ||
.printDeprecationCollectDefaultMetricsNumber; | ||
var metrics = { | ||
processCpuTotal: processCpuTotal, | ||
processStartTime: processStartTime, | ||
osMemoryHeap: osMemoryHeap, | ||
processOpenFileDescriptors: processOpenFileDescriptors, | ||
processMaxFileDescriptors: processMaxFileDescriptors, | ||
eventLoopLag: eventLoopLag, | ||
processHandles: processHandles, | ||
processRequests: processRequests, | ||
heapSizeAndUsed: heapSizeAndUsed, | ||
heapSpacesSizeAndUsed: heapSpacesSizeAndUsed, | ||
version: version | ||
const metrics = { | ||
processCpuTotal, | ||
processStartTime, | ||
osMemoryHeap, | ||
processOpenFileDescriptors, | ||
processMaxFileDescriptors, | ||
eventLoopLag, | ||
processHandles, | ||
processRequests, | ||
heapSizeAndUsed, | ||
heapSpacesSizeAndUsed, | ||
version | ||
}; | ||
var metricsList = Object.keys(metrics); | ||
const metricsList = Object.keys(metrics); | ||
var existingInterval = null; | ||
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 | ||
var init = true; | ||
let init = true; | ||
module.exports = function startDefaultMetrics(interval) { | ||
if(existingInterval !== null) { | ||
module.exports = function startDefaultMetrics(config) { | ||
let normalizedConfig = config; | ||
if (typeof config === 'number') { | ||
printDeprecationCollectDefaultMetricsNumber(config); | ||
normalizedConfig = { timeout: config }; | ||
} | ||
normalizedConfig = Object.assign({ timeout: 10000 }, normalizedConfig); | ||
if (existingInterval !== null) { | ||
clearInterval(existingInterval); | ||
} | ||
interval = interval || 10000; | ||
const initialisedMetrics = metricsList.map(metric => { | ||
const defaultMetric = metrics[metric]; | ||
if (!init) { | ||
defaultMetric.metricNames.map( | ||
globalRegistry.removeSingleMetric, | ||
globalRegistry | ||
); | ||
} | ||
var initialisedMetrics = metricsList | ||
.map(function(metric) { | ||
var defaultMetric = metrics[metric]; | ||
if(!init) { | ||
defaultMetric.metricNames.map(register.removeSingleMetric, register); | ||
} | ||
return defaultMetric(normalizedConfig.register); | ||
}); | ||
return defaultMetric(); | ||
}); | ||
function updateAllMetrics() { | ||
initialisedMetrics.forEach(function(metric) { | ||
metric.call(); | ||
}); | ||
initialisedMetrics.forEach(metric => metric.call()); | ||
} | ||
@@ -61,3 +70,6 @@ | ||
existingInterval = setInterval(updateAllMetrics, interval).unref(); | ||
existingInterval = setInterval( | ||
updateAllMetrics, | ||
normalizedConfig.interval | ||
).unref(); | ||
@@ -64,0 +76,0 @@ init = false; |
306
lib/gauge.js
@@ -6,80 +6,86 @@ /** | ||
var globalRegistry = require('./register'); | ||
var type = 'gauge'; | ||
const globalRegistry = require('./registry').globalRegistry; | ||
const type = 'gauge'; | ||
var isNumber = require('./util').isNumber; | ||
var isDate = require('./util').isDate; | ||
var extend = require('util-extend'); | ||
var createValue = require('./util').setValue; | ||
var getProperties = require('./util').getPropertiesFromObj; | ||
var getLabels = require('./util').getLabels; | ||
var hashObject = require('./util').hashObject; | ||
var validateMetricName = require('./validation').validateMetricName; | ||
var validateLabels = require('./validation').validateLabel; | ||
var validateLabelNames = require('./validation').validateLabelName; | ||
var isObject = require('./util').isObject; | ||
var extend = require('util-extend'); | ||
const isNumber = require('./util').isNumber; | ||
const isDate = require('./util').isDate; | ||
const createValue = require('./util').setValue; | ||
const getProperties = require('./util').getPropertiesFromObj; | ||
const getLabels = require('./util').getLabels; | ||
const hashObject = require('./util').hashObject; | ||
const validateMetricName = require('./validation').validateMetricName; | ||
const validateLabels = require('./validation').validateLabel; | ||
const validateLabelNames = require('./validation').validateLabelName; | ||
const isObject = require('./util').isObject; | ||
const printDeprecationObjectConstructor = require('./util') | ||
.printDeprecationObjectConstructor; | ||
/** | ||
* Gauge constructor | ||
* @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 | ||
* @constructor | ||
*/ | ||
function Gauge(name, help, labels) { | ||
var config; | ||
if(isObject(name)) { | ||
config = extend({ | ||
labelNames: [], | ||
registers: [ globalRegistry ], | ||
}, name); | ||
} else { | ||
config = { | ||
name: name, | ||
help: help, | ||
labelNames: labels, | ||
registers: [ globalRegistry ] | ||
}; | ||
} | ||
class Gauge { | ||
/** | ||
* 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 | ||
*/ | ||
constructor(name, help, labels) { | ||
let config; | ||
if (isObject(name)) { | ||
config = Object.assign( | ||
{ | ||
labelNames: [] | ||
}, | ||
name | ||
); | ||
if(!config.help) { | ||
throw new Error('Missing mandatory help parameter'); | ||
} | ||
if(!config.name) { | ||
throw new Error('Missing mandatory name parameter'); | ||
} | ||
if(!validateMetricName(config.name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
if(!validateLabelNames(config.labelNames)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
if (!config.registers) { | ||
config.registers = [globalRegistry]; | ||
} | ||
} else { | ||
printDeprecationObjectConstructor(); | ||
config = { | ||
name, | ||
help, | ||
labelNames: labels, | ||
registers: [globalRegistry] | ||
}; | ||
} | ||
this.name = config.name; | ||
this.labelNames = config.labelNames || []; | ||
this.hashMap = {}; | ||
this.help = config.help; | ||
if (!config.help) { | ||
throw new Error('Missing mandatory help parameter'); | ||
} | ||
if (!config.name) { | ||
throw new Error('Missing mandatory name parameter'); | ||
} | ||
if (!validateMetricName(config.name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
if (!validateLabelNames(config.labelNames)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
var metric = this; | ||
config.registers.forEach(function(registryInstance) { | ||
registryInstance.registerMetric(metric); | ||
}); | ||
} | ||
this.name = config.name; | ||
this.labelNames = config.labelNames || []; | ||
this.hashMap = {}; | ||
this.help = config.help; | ||
/** | ||
* Set a gauge to a value | ||
* @param {object} labels - Object with labels and their values | ||
* @param {Number} value - Value to set the gauge to, must be positive | ||
* @param {(Number|Date)} timestamp - Timestamp to set the gauge to | ||
* @returns {void} | ||
*/ | ||
Gauge.prototype.set = function(labels, value, timestamp) { | ||
if(isNumber(labels)) { | ||
return set.call(this, null)(labels, value); | ||
config.registers.forEach(registryInstance => | ||
registryInstance.registerMetric(this) | ||
); | ||
} | ||
return set.call(this, labels)(value, timestamp); | ||
}; | ||
/** | ||
/** | ||
* Set a gauge to a value | ||
* @param {object} labels - Object with labels and their values | ||
* @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) { | ||
if (isNumber(labels)) { | ||
return set.call(this, null)(labels, value); | ||
} | ||
return set.call(this, labels)(value, timestamp); | ||
} | ||
/** | ||
* Increment a gauge value | ||
@@ -91,8 +97,8 @@ * @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
*/ | ||
Gauge.prototype.inc = function(labels, value, timestamp) { | ||
inc.call(this, labels)(value, timestamp); | ||
}; | ||
inc(labels, value, timestamp) { | ||
inc.call(this, labels)(value, timestamp); | ||
} | ||
/** | ||
/** | ||
* Decrement a gauge value | ||
@@ -104,58 +110,58 @@ * @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
*/ | ||
Gauge.prototype.dec = function(labels, value, timestamp) { | ||
dec.call(this, labels)(value, timestamp); | ||
}; | ||
dec(labels, value, timestamp) { | ||
dec.call(this, labels)(value, timestamp); | ||
} | ||
/** | ||
* Set the gauge to current unix epoch | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {void} | ||
*/ | ||
Gauge.prototype.setToCurrentTime = function(labels) { | ||
return setToCurrentTime.call(this, labels)(); | ||
}; | ||
/** | ||
* Set the gauge to current unix epoch | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {void} | ||
*/ | ||
setToCurrentTime(labels) { | ||
return setToCurrentTime.call(this, labels)(); | ||
} | ||
/** | ||
* Start a timer | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {function} - Invoke this function to set the duration in seconds since you started the timer. | ||
* @example | ||
* var done = gauge.startTimer(); | ||
* makeXHRRequest(function(err, response) { | ||
* done(); //Duration of the request will be saved | ||
* }); | ||
*/ | ||
Gauge.prototype.startTimer = function(labels) { | ||
return startTimer.call(this, labels)(); | ||
}; | ||
/** | ||
* Start a timer | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {function} - Invoke this function to set the duration in seconds since you started the timer. | ||
* @example | ||
* var done = gauge.startTimer(); | ||
* makeXHRRequest(function(err, response) { | ||
* done(); //Duration of the request will be saved | ||
* }); | ||
*/ | ||
startTimer(labels) { | ||
return startTimer.call(this, labels)(); | ||
} | ||
Gauge.prototype.get = function() { | ||
return { | ||
help: this.help, | ||
name: this.name, | ||
type: type, | ||
values: getProperties(this.hashMap) | ||
}; | ||
}; | ||
get() { | ||
return { | ||
help: this.help, | ||
name: this.name, | ||
type, | ||
values: getProperties(this.hashMap) | ||
}; | ||
} | ||
Gauge.prototype._getValue = function(labels) { | ||
var hash = hashObject(labels || {}); | ||
return this.hashMap[hash] ? this.hashMap[hash].value : 0; | ||
}; | ||
_getValue(labels) { | ||
const hash = hashObject(labels || {}); | ||
return this.hashMap[hash] ? this.hashMap[hash].value : 0; | ||
} | ||
Gauge.prototype.labels = function() { | ||
var labels = getLabels(this.labelNames, arguments); | ||
return { | ||
inc: inc.call(this, labels), | ||
dec: dec.call(this, labels), | ||
set: set.call(this, labels), | ||
setToCurrentTime: setToCurrentTime.call(this, labels), | ||
startTimer: startTimer.call(this, labels) | ||
}; | ||
}; | ||
labels() { | ||
const labels = getLabels(this.labelNames, arguments); | ||
return { | ||
inc: inc.call(this, labels), | ||
dec: dec.call(this, labels), | ||
set: set.call(this, labels), | ||
setToCurrentTime: setToCurrentTime.call(this, labels), | ||
startTimer: startTimer.call(this, labels) | ||
}; | ||
} | ||
} | ||
function setToCurrentTime(labels) { | ||
var gauge = this; | ||
return function() { | ||
gauge.set(labels, new Date().getTime()); | ||
return () => { | ||
this.set(labels, Date.now()); | ||
}; | ||
@@ -165,8 +171,10 @@ } | ||
function startTimer(startLabels) { | ||
var gauge = this; | ||
return function() { | ||
var start = process.hrtime(); | ||
return function(endLabels) { | ||
var delta = process.hrtime(start); | ||
gauge.set(extend(startLabels || {}, endLabels), delta[0] + delta[1] / 1e9); | ||
return () => { | ||
const start = process.hrtime(); | ||
return endLabels => { | ||
const delta = process.hrtime(start); | ||
this.set( | ||
Object.assign(startLabels || {}, endLabels), | ||
delta[0] + delta[1] / 1e9 | ||
); | ||
}; | ||
@@ -177,6 +185,9 @@ }; | ||
function dec(labels) { | ||
var gauge = this; | ||
return function(value, timestamp) { | ||
var data = convertLabelsAndValues(labels, value); | ||
gauge.set(data.labels, gauge._getValue(data.labels) - (data.value || 1), timestamp); | ||
return (value, timestamp) => { | ||
const data = convertLabelsAndValues(labels, value); | ||
this.set( | ||
data.labels, | ||
this._getValue(data.labels) - (data.value || 1), | ||
timestamp | ||
); | ||
}; | ||
@@ -186,6 +197,9 @@ } | ||
function inc(labels) { | ||
var gauge = this; | ||
return function(value, timestamp) { | ||
var data = convertLabelsAndValues(labels, value); | ||
gauge.set(data.labels, gauge._getValue(data.labels) + (data.value || 1), timestamp); | ||
return (value, timestamp) => { | ||
const data = convertLabelsAndValues(labels, value); | ||
this.set( | ||
data.labels, | ||
this._getValue(data.labels) + (data.value || 1), | ||
timestamp | ||
); | ||
}; | ||
@@ -195,8 +209,7 @@ } | ||
function set(labels) { | ||
var that = this; | ||
return function(value, timestamp) { | ||
if(!isNumber(value)) { | ||
return (value, timestamp) => { | ||
if (!isNumber(value)) { | ||
throw new Error('Value is not a valid number', value); | ||
} | ||
if(timestamp && !isDate(timestamp) && !isNumber(timestamp)) { | ||
if (timestamp && !isDate(timestamp) && !isNumber(timestamp)) { | ||
throw new Error('Timestamp is not a valid date or number', value); | ||
@@ -207,4 +220,4 @@ } | ||
validateLabels(that.labelNames, labels); | ||
that.hashMap = createValue(that.hashMap, value, labels, timestamp); | ||
validateLabels(this.labelNames, labels); | ||
this.hashMap = createValue(this.hashMap, value, labels, timestamp); | ||
}; | ||
@@ -214,3 +227,3 @@ } | ||
function convertLabelsAndValues(labels, value) { | ||
if(isNumber(labels)) { | ||
if (isNumber(labels)) { | ||
return { | ||
@@ -222,8 +235,7 @@ value: labels, | ||
return { | ||
labels: labels, | ||
value: value | ||
labels, | ||
value | ||
}; | ||
} | ||
module.exports = Gauge; |
@@ -6,134 +6,145 @@ /** | ||
var globalRegistry = require('./register'); | ||
var type = 'histogram'; | ||
var isNumber = require('./util').isNumber; | ||
var extend = require('util-extend'); | ||
var getProperties = require('./util').getPropertiesFromObj; | ||
var getLabels = require('./util').getLabels; | ||
var hashObject = require('./util').hashObject; | ||
var validateLabels = require('./validation').validateLabel; | ||
var validateMetricName = require('./validation').validateMetricName; | ||
var validateLabelNames = require('./validation').validateLabelName; | ||
var isObject = require('./util').isObject; | ||
const globalRegistry = require('./registry').globalRegistry; | ||
const type = 'histogram'; | ||
const isNumber = require('./util').isNumber; | ||
const getProperties = require('./util').getPropertiesFromObj; | ||
const getLabels = require('./util').getLabels; | ||
const hashObject = require('./util').hashObject; | ||
const validateLabels = require('./validation').validateLabel; | ||
const validateMetricName = require('./validation').validateMetricName; | ||
const validateLabelNames = require('./validation').validateLabelName; | ||
const isObject = require('./util').isObject; | ||
const printDeprecationObjectConstructor = require('./util') | ||
.printDeprecationObjectConstructor; | ||
/** | ||
* 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 | ||
* @constructor | ||
*/ | ||
function Histogram(name, help, labelsOrConf, conf) { | ||
var config; | ||
class Histogram { | ||
/** | ||
* 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 | ||
*/ | ||
constructor(name, help, labelsOrConf, conf) { | ||
let config; | ||
if(isObject(name)) { | ||
config = extend( { | ||
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], | ||
labelNames: [], | ||
registers: [ globalRegistry ], | ||
}, name); | ||
} else { | ||
var obj; | ||
var labels = []; | ||
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(Array.isArray(labelsOrConf)) { | ||
obj = conf || {}; | ||
labels = labelsOrConf; | ||
if (!config.registers) { | ||
config.registers = [globalRegistry]; | ||
} | ||
} else { | ||
obj = labelsOrConf || {}; | ||
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] | ||
}; | ||
} | ||
validateInput(config.name, config.help, config.labelNames); | ||
config = { | ||
name: name, | ||
labelNames: labels, | ||
help: help, | ||
buckets: configureUpperbounds(obj.buckets), | ||
registers: [ globalRegistry ] | ||
}; | ||
} | ||
validateInput(config.name, config.help, config.labelNames); | ||
this.name = config.name; | ||
this.help = config.help; | ||
this.name = config.name; | ||
this.help = config.help; | ||
this.upperBounds = config.buckets; | ||
this.bucketValues = this.upperBounds.reduce((acc, upperBound) => { | ||
acc[upperBound] = 0; | ||
return acc; | ||
}, {}); | ||
this.upperBounds = config.buckets; | ||
this.bucketValues = this.upperBounds.reduce(function(acc, upperBound) { | ||
acc[upperBound] = 0; | ||
return acc; | ||
}, {}); | ||
Object.freeze(this.bucketValues); | ||
Object.freeze(this.upperBounds); | ||
this.sum = 0; | ||
this.count = 0; | ||
Object.freeze(this.bucketValues); | ||
Object.freeze(this.upperBounds); | ||
this.sum = 0; | ||
this.count = 0; | ||
this.hashMap = {}; | ||
this.labelNames = config.labelNames || []; | ||
this.hashMap = {}; | ||
this.labelNames = config.labelNames || []; | ||
config.registers.forEach(registryInstance => | ||
registryInstance.registerMetric(this) | ||
); | ||
} | ||
var metric = this; | ||
config.registers.forEach(function(registryInstance) { | ||
registryInstance.registerMetric(metric); | ||
}); | ||
} | ||
/** | ||
* Observe a value in histogram | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @param {Number} value - Value to observe in the histogram | ||
* @returns {void} | ||
*/ | ||
observe(labels, value) { | ||
observe.call(this, labels === 0 ? 0 : labels || {})(value); | ||
} | ||
/** | ||
* Observe a value in histogram | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @param {Number} value - Value to observe in the histogram | ||
* @returns {void} | ||
*/ | ||
Histogram.prototype.observe = function(labels, value) { | ||
observe.call(this, labels === 0 ? 0 : (labels || {}))(value); | ||
}; | ||
Histogram.prototype.get = function() { | ||
var data = getProperties(this.hashMap); | ||
var values = | ||
data.map(extractBucketValuesForExport(this)) | ||
get() { | ||
const data = getProperties(this.hashMap); | ||
const values = data | ||
.map(extractBucketValuesForExport(this)) | ||
.reduce(addSumAndCountForExport(this), []); | ||
return { | ||
name: this.name, | ||
help: this.help, | ||
type: type, | ||
values: values | ||
}; | ||
}; | ||
return { | ||
name: this.name, | ||
help: this.help, | ||
type, | ||
values | ||
}; | ||
} | ||
Histogram.prototype.reset = function() { | ||
this.sum = 0; | ||
this.count = 0; | ||
this.hashMap = {}; | ||
}; | ||
reset() { | ||
this.sum = 0; | ||
this.count = 0; | ||
this.hashMap = {}; | ||
} | ||
/** | ||
* Start a timer that could be used to logging durations | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {function} - Function to invoke when you want to stop the timer and observe the duration in seconds | ||
* @example | ||
* var end = histogram.startTimer(); | ||
* makeExpensiveXHRRequest(function(err, res) { | ||
* end(); //Observe the duration of expensiveXHRRequest | ||
* }); | ||
*/ | ||
Histogram.prototype.startTimer = function(labels) { | ||
return startTimer.call(this, labels)(); | ||
}; | ||
/** | ||
* Start a timer that could be used to logging durations | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {function} - Function to invoke when you want to stop the timer and observe the duration in seconds | ||
* @example | ||
* var end = histogram.startTimer(); | ||
* makeExpensiveXHRRequest(function(err, res) { | ||
* end(); //Observe the duration of expensiveXHRRequest | ||
* }); | ||
*/ | ||
startTimer(labels) { | ||
return startTimer.call(this, labels)(); | ||
} | ||
Histogram.prototype.labels = function() { | ||
var labels = getLabels(this.labelNames, arguments); | ||
return { | ||
observe: observe.call(this, labels), | ||
startTimer: startTimer.call(this, labels) | ||
}; | ||
}; | ||
labels() { | ||
const labels = getLabels(this.labelNames, arguments); | ||
return { | ||
observe: observe.call(this, labels), | ||
startTimer: startTimer.call(this, labels) | ||
}; | ||
} | ||
} | ||
function startTimer(startLabels) { | ||
var histogram = this; | ||
return function() { | ||
var start = process.hrtime(); | ||
return function(endLabels) { | ||
var delta = process.hrtime(start); | ||
histogram.observe(extend(startLabels || {}, endLabels), delta[0] + delta[1] / 1e9); | ||
return () => { | ||
const start = process.hrtime(); | ||
return endLabels => { | ||
const delta = process.hrtime(start); | ||
this.observe( | ||
Object.assign(startLabels || {}, endLabels), | ||
delta[0] + delta[1] / 1e9 | ||
); | ||
}; | ||
@@ -143,19 +154,19 @@ }; | ||
function validateInput(name, help, labels) { | ||
if(!help) { | ||
if (!help) { | ||
throw new Error('Missing mandatory help parameter'); | ||
} | ||
if(!name) { | ||
if (!name) { | ||
throw new Error('Missing mandatory name parameter'); | ||
} | ||
if(!validateMetricName(name)) { | ||
if (!validateMetricName(name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
if(!validateLabelNames(labels)) { | ||
if (!validateLabelNames(labels)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
labels.forEach(function(label) { | ||
if(label === 'le') { | ||
labels.forEach(label => { | ||
if (label === 'le') { | ||
throw new Error('le is a reserved label keyword'); | ||
@@ -167,4 +178,16 @@ } | ||
function configureUpperbounds(configuredBuckets) { | ||
var 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); | ||
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); | ||
} | ||
@@ -178,5 +201,5 @@ | ||
return { | ||
labels: labels, | ||
value: value, | ||
metricName: metricName | ||
labels, | ||
value, | ||
metricName | ||
}; | ||
@@ -186,8 +209,7 @@ } | ||
function findBound(upperBounds, value) { | ||
for(var i = 0; i < upperBounds.length; i++) { | ||
var bound = upperBounds[i]; | ||
if(value <= bound) { | ||
for (let i = 0; i < upperBounds.length; i++) { | ||
const bound = upperBounds[i]; | ||
if (value <= bound) { | ||
return bound; | ||
} | ||
} | ||
@@ -198,18 +220,20 @@ return -1; | ||
function observe(labels) { | ||
var histogram = this; | ||
return function(value) { | ||
var labelValuePair = convertLabelsAndValues(labels, value); | ||
return value => { | ||
const labelValuePair = convertLabelsAndValues(labels, value); | ||
validateLabels(histogram.labelNames, labelValuePair.labels); | ||
if(!isNumber(labelValuePair.value)) { | ||
validateLabels(this.labelNames, labelValuePair.labels); | ||
if (!isNumber(labelValuePair.value)) { | ||
throw new Error('Value is not a valid number', labelValuePair.value); | ||
} | ||
var hash = hashObject(labelValuePair.labels); | ||
var valueFromMap = histogram.hashMap[hash]; | ||
if(!valueFromMap) { | ||
valueFromMap = createBaseValues(labelValuePair.labels, extend({}, histogram.bucketValues)); | ||
const hash = hashObject(labelValuePair.labels); | ||
let valueFromMap = this.hashMap[hash]; | ||
if (!valueFromMap) { | ||
valueFromMap = createBaseValues( | ||
labelValuePair.labels, | ||
Object.assign({}, this.bucketValues) | ||
); | ||
} | ||
var b = findBound(histogram.upperBounds, labelValuePair.value); | ||
const b = findBound(this.upperBounds, labelValuePair.value); | ||
@@ -219,7 +243,7 @@ valueFromMap.sum += labelValuePair.value; | ||
if(valueFromMap.bucketValues.hasOwnProperty(b)) { | ||
if (valueFromMap.bucketValues.hasOwnProperty(b)) { | ||
valueFromMap.bucketValues[b] += 1; | ||
} | ||
histogram.hashMap[hash] = valueFromMap; | ||
this.hashMap[hash] = valueFromMap; | ||
}; | ||
@@ -230,4 +254,4 @@ } | ||
return { | ||
labels: labels, | ||
bucketValues: bucketValues, | ||
labels, | ||
bucketValues, | ||
sum: 0, | ||
@@ -239,3 +263,3 @@ count: 0 | ||
function convertLabelsAndValues(labels, value) { | ||
if(isNumber(labels)) { | ||
if (isNumber(labels)) { | ||
return { | ||
@@ -247,4 +271,4 @@ value: labels, | ||
return { | ||
labels: labels, | ||
value: value | ||
labels, | ||
value | ||
}; | ||
@@ -254,5 +278,7 @@ } | ||
function extractBucketValuesForExport(histogram) { | ||
return function(bucketData) { | ||
var buckets = histogram.upperBounds.map(createBucketValues(bucketData, histogram)); | ||
return { buckets: buckets, data: bucketData }; | ||
return bucketData => { | ||
const buckets = histogram.upperBounds.map( | ||
createBucketValues(bucketData, histogram) | ||
); | ||
return { buckets, data: bucketData }; | ||
}; | ||
@@ -262,9 +288,15 @@ } | ||
function addSumAndCountForExport(histogram) { | ||
return function(acc, d) { | ||
return (acc, d) => { | ||
acc = acc.concat(d.buckets); | ||
var infLabel = extend({ le: '+Inf' }, d.data.labels); | ||
acc.push(createValuePair(infLabel, d.data.count, histogram.name + '_bucket')); | ||
acc.push(createValuePair(d.data.labels, d.data.sum, histogram.name + '_sum')); | ||
acc.push(createValuePair(d.data.labels, d.data.count, histogram.name + '_count')); | ||
const infLabel = Object.assign({ le: '+Inf' }, d.data.labels); | ||
acc.push( | ||
createValuePair(infLabel, d.data.count, `${histogram.name}_bucket`) | ||
); | ||
acc.push( | ||
createValuePair(d.data.labels, d.data.sum, `${histogram.name}_sum`) | ||
); | ||
acc.push( | ||
createValuePair(d.data.labels, d.data.count, `${histogram.name}_count`) | ||
); | ||
return acc; | ||
@@ -275,7 +307,7 @@ }; | ||
function createBucketValues(bucket, histogram) { | ||
var acc = 0; | ||
return function(upperBound) { | ||
let acc = 0; | ||
return upperBound => { | ||
acc += bucket.bucketValues[upperBound]; | ||
var lbls = extend({ le: upperBound }, bucket.labels); | ||
var valuePair = createValuePair(lbls, acc, histogram.name + '_bucket'); | ||
const lbls = Object.assign({ le: upperBound }, bucket.labels); | ||
const valuePair = createValuePair(lbls, acc, `${histogram.name}_bucket`); | ||
return valuePair; | ||
@@ -282,0 +314,0 @@ }; |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
const Gauge = require('../gauge'); | ||
var NODEJS_EVENTLOOP_LAG = 'nodejs_eventloop_lag_seconds'; | ||
const NODEJS_EVENTLOOP_LAG = 'nodejs_eventloop_lag_seconds'; | ||
function reportEventloopLag(start, gauge) { | ||
var delta = process.hrtime(start); | ||
var nanosec = delta[0] * 1e9 + delta[1]; | ||
var seconds = nanosec / 1e9; | ||
const delta = process.hrtime(start); | ||
const nanosec = delta[0] * 1e9 + delta[1]; | ||
const seconds = nanosec / 1e9; | ||
@@ -15,7 +15,11 @@ gauge.set(seconds, Date.now()); | ||
module.exports = function() { | ||
var gauge = new Gauge(NODEJS_EVENTLOOP_LAG, 'Lag of event loop in seconds.'); | ||
module.exports = registry => { | ||
const gauge = new Gauge({ | ||
name: NODEJS_EVENTLOOP_LAG, | ||
help: 'Lag of event loop in seconds.', | ||
registers: registry ? [registry] : undefined | ||
}); | ||
return function() { | ||
var start = process.hrtime(); | ||
return () => { | ||
const start = process.hrtime(); | ||
setImmediate(reportEventloopLag, start, gauge); | ||
@@ -22,0 +26,0 @@ }; |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
var safeMemoryUsage = require('./helpers/safeMemoryUsage'); | ||
const Gauge = require('../gauge'); | ||
const safeMemoryUsage = require('./helpers/safeMemoryUsage'); | ||
var NODEJS_HEAP_SIZE_TOTAL = 'nodejs_heap_size_total_bytes'; | ||
var NODEJS_HEAP_SIZE_USED = 'nodejs_heap_size_used_bytes'; | ||
var NODEJS_EXTERNAL_MEMORY = 'nodejs_external_memory_bytes'; | ||
const NODEJS_HEAP_SIZE_TOTAL = 'nodejs_heap_size_total_bytes'; | ||
const NODEJS_HEAP_SIZE_USED = 'nodejs_heap_size_used_bytes'; | ||
const NODEJS_EXTERNAL_MEMORY = 'nodejs_external_memory_bytes'; | ||
module.exports = function() { | ||
if(typeof process.memoryUsage !== 'function') { | ||
return function() { | ||
}; | ||
module.exports = registry => { | ||
if (typeof process.memoryUsage !== 'function') { | ||
return () => {}; | ||
} | ||
var heapSizeTotal = new Gauge(NODEJS_HEAP_SIZE_TOTAL, 'Process heap size from node.js in bytes.'); | ||
var heapSizeUsed = new Gauge(NODEJS_HEAP_SIZE_USED, 'Process heap size used from node.js in bytes.'); | ||
const registers = registry ? [registry] : undefined; | ||
var usage = safeMemoryUsage(); | ||
if(usage && usage.external) { | ||
var externalMemUsed = new Gauge(NODEJS_EXTERNAL_MEMORY, 'Nodejs external memory size in bytes.'); | ||
const heapSizeTotal = new Gauge({ | ||
name: NODEJS_HEAP_SIZE_TOTAL, | ||
help: 'Process heap size from node.js in bytes.', | ||
registers | ||
}); | ||
const heapSizeUsed = new Gauge({ | ||
name: NODEJS_HEAP_SIZE_USED, | ||
help: 'Process heap size used from node.js in bytes.', | ||
registers | ||
}); | ||
let externalMemUsed; | ||
const usage = safeMemoryUsage(); | ||
if (usage && usage.external) { | ||
externalMemUsed = new Gauge({ | ||
name: NODEJS_EXTERNAL_MEMORY, | ||
help: 'Nodejs external memory size in bytes.', | ||
registers | ||
}); | ||
} | ||
return function() { | ||
// process.memoryUsage() can throw EMFILE errors, see #67 | ||
var memUsage = safeMemoryUsage(); | ||
if(memUsage) { | ||
var now = Date.now(); | ||
return () => { | ||
// process.memoryUsage() can throw EMFILE errors, see #67 | ||
const memUsage = safeMemoryUsage(); | ||
if (memUsage) { | ||
const now = Date.now(); | ||
heapSizeTotal.set(memUsage.heapTotal, now); | ||
heapSizeUsed.set(memUsage.heapUsed, now); | ||
if(memUsage.external && externalMemUsed) { | ||
if (memUsage.external && externalMemUsed) { | ||
externalMemUsed.set(memUsage.external, now); | ||
@@ -36,6 +50,14 @@ } | ||
return {total: heapSizeTotal, used: heapSizeUsed, external: externalMemUsed}; | ||
return { | ||
total: heapSizeTotal, | ||
used: heapSizeUsed, | ||
external: externalMemUsed | ||
}; | ||
}; | ||
}; | ||
module.exports.metricNames = [NODEJS_HEAP_SIZE_TOTAL, NODEJS_HEAP_SIZE_USED, NODEJS_EXTERNAL_MEMORY]; | ||
module.exports.metricNames = [ | ||
NODEJS_HEAP_SIZE_TOTAL, | ||
NODEJS_HEAP_SIZE_USED, | ||
NODEJS_EXTERNAL_MEMORY | ||
]; |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
var v8; | ||
const Gauge = require('../gauge'); | ||
let v8; | ||
@@ -9,37 +9,37 @@ try { | ||
} 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 | ||
// node version is too old | ||
// probably we can use v8-heap-space-statistics for >=node-4.0.0 and <node-6.0.0 | ||
} | ||
var METRICS = [ | ||
'total', | ||
'used', | ||
'available' | ||
]; | ||
const METRICS = ['total', 'used', 'available']; | ||
var NODEJS_HEAP_SIZE = {}; | ||
const NODEJS_HEAP_SIZE = {}; | ||
METRICS.forEach(function(metricType) { | ||
NODEJS_HEAP_SIZE[metricType] = 'nodejs_heap_space_size_' + metricType + '_bytes'; | ||
METRICS.forEach(metricType => { | ||
NODEJS_HEAP_SIZE[metricType] = `nodejs_heap_space_size_${metricType}_bytes`; | ||
}); | ||
module.exports = function() { | ||
if(typeof v8 === 'undefined' || typeof v8.getHeapSpaceStatistics !== 'function') { | ||
return function() { | ||
}; | ||
module.exports = registry => { | ||
if ( | ||
typeof v8 === 'undefined' || | ||
typeof v8.getHeapSpaceStatistics !== 'function' | ||
) { | ||
return () => {}; | ||
} | ||
var gauges = {}; | ||
const registers = registry ? [registry] : undefined; | ||
METRICS.forEach(function(metricType) { | ||
gauges[metricType] = new Gauge( | ||
NODEJS_HEAP_SIZE[metricType], | ||
'Process heap space size ' + metricType + ' from node.js in bytes.', | ||
['space'] | ||
); | ||
const gauges = {}; | ||
METRICS.forEach(metricType => { | ||
gauges[metricType] = new Gauge({ | ||
name: NODEJS_HEAP_SIZE[metricType], | ||
help: `Process heap space size ${metricType} from node.js in bytes.`, | ||
labelNames: ['space'], | ||
registers | ||
}); | ||
}); | ||
return function() { | ||
var data = { | ||
return () => { | ||
const data = { | ||
total: {}, | ||
@@ -49,6 +49,9 @@ used: {}, | ||
}; | ||
var now = Date.now(); | ||
const now = Date.now(); | ||
v8.getHeapSpaceStatistics().forEach(function onEachSpace(space) { | ||
var spaceName = space.space_name.substr(0, space.space_name.indexOf('_space')); | ||
v8.getHeapSpaceStatistics().forEach(space => { | ||
const spaceName = space.space_name.substr( | ||
0, | ||
space.space_name.indexOf('_space') | ||
); | ||
@@ -59,5 +62,9 @@ data.total[spaceName] = space.space_size; | ||
gauges.total.set({space: spaceName}, space.space_size, now); | ||
gauges.used.set({space: spaceName}, space.space_used_size, now); | ||
gauges.available.set({space: spaceName}, space.space_available_size, now); | ||
gauges.total.set({ space: spaceName }, space.space_size, now); | ||
gauges.used.set({ space: spaceName }, space.space_used_size, now); | ||
gauges.available.set( | ||
{ space: spaceName }, | ||
space.space_available_size, | ||
now | ||
); | ||
}); | ||
@@ -69,4 +76,4 @@ | ||
module.exports.metricNames = METRICS.map(function(metricType) { | ||
return NODEJS_HEAP_SIZE[metricType]; | ||
}); | ||
module.exports.metricNames = METRICS.map( | ||
metricType => NODEJS_HEAP_SIZE[metricType] | ||
); |
'use strict'; | ||
function safeMemoryUsage() { | ||
var memoryUsage; | ||
let memoryUsage; | ||
try { | ||
memoryUsage = process.memoryUsage(); | ||
} catch (ex) { | ||
// empty | ||
} | ||
@@ -10,0 +10,0 @@ |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
var linuxVariant = require('./osMemoryHeapLinux'); | ||
var safeMemoryUsage = require('./helpers/safeMemoryUsage'); | ||
const Gauge = require('../gauge'); | ||
const linuxVariant = require('./osMemoryHeapLinux'); | ||
const safeMemoryUsage = require('./helpers/safeMemoryUsage'); | ||
var PROCESS_RESIDENT_MEMORY = 'process_resident_memory_bytes'; | ||
const PROCESS_RESIDENT_MEMORY = 'process_resident_memory_bytes'; | ||
var notLinuxVariant = function() { | ||
var residentMemGauge = new Gauge(PROCESS_RESIDENT_MEMORY, 'Resident memory size in bytes.'); | ||
function notLinuxVariant(registry) { | ||
const residentMemGauge = new Gauge({ | ||
name: PROCESS_RESIDENT_MEMORY, | ||
help: 'Resident memory size in bytes.', | ||
registers: registry ? [registry] : undefined | ||
}); | ||
return function() { | ||
var memUsage = safeMemoryUsage(); | ||
return () => { | ||
const memUsage = safeMemoryUsage(); | ||
// I don't think the other things returned from `process.memoryUsage()` is relevant to a standard export | ||
if(memUsage) { | ||
if (memUsage) { | ||
residentMemGauge.set(memUsage.rss, Date.now()); | ||
} | ||
}; | ||
}; | ||
} | ||
module.exports = function() { | ||
return process.platform === 'linux' ? linuxVariant() : notLinuxVariant(); | ||
}; | ||
module.exports = registry => | ||
process.platform === 'linux' | ||
? linuxVariant(registry) | ||
: notLinuxVariant(registry); | ||
module.exports.metricNames = process.platform === 'linux' ? linuxVariant.metricNames : [PROCESS_RESIDENT_MEMORY]; | ||
module.exports.metricNames = | ||
process.platform === 'linux' | ||
? linuxVariant.metricNames | ||
: [PROCESS_RESIDENT_MEMORY]; |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
var fs = require('fs'); | ||
const Gauge = require('../gauge'); | ||
const fs = require('fs'); | ||
var values = ['VmSize', 'VmRSS', 'VmData']; | ||
const values = ['VmSize', 'VmRSS', 'VmData']; | ||
var PROCESS_RESIDENT_MEMORY = 'process_resident_memory_bytes'; | ||
var PROCESS_VIRTUAL_MEMORY = 'process_virtual_memory_bytes'; | ||
var PROCESS_HEAP = 'process_heap_bytes'; | ||
const PROCESS_RESIDENT_MEMORY = 'process_resident_memory_bytes'; | ||
const PROCESS_VIRTUAL_MEMORY = 'process_virtual_memory_bytes'; | ||
const PROCESS_HEAP = 'process_heap_bytes'; | ||
function structureOutput(input) { | ||
var returnValue = {}; | ||
const returnValue = {}; | ||
input.split('\n') | ||
.filter(function(s) { | ||
return values.some(function(value) { | ||
return s.indexOf(value) === 0; | ||
}); | ||
}) | ||
.forEach(function(string) { | ||
var split = string.split(':'); | ||
input | ||
.split('\n') | ||
.filter(s => values.some(value => s.indexOf(value) === 0)) | ||
.forEach(string => { | ||
const split = string.split(':'); | ||
// Get the value | ||
var value = split[1].trim(); | ||
let value = split[1].trim(); | ||
// Remove trailing ` kb` | ||
@@ -37,14 +34,27 @@ value = value.substr(0, value.length - 3); | ||
module.exports = function() { | ||
var residentMemGauge = new Gauge(PROCESS_RESIDENT_MEMORY, 'Resident memory size in bytes.'); | ||
var virtualMemGauge = new Gauge(PROCESS_VIRTUAL_MEMORY, 'Virtual memory size in bytes.'); | ||
var heapSizeMemGauge = new Gauge(PROCESS_HEAP , 'Process heap size in bytes.'); | ||
module.exports = registry => { | ||
const registers = registry ? [registry] : undefined; | ||
const residentMemGauge = new Gauge({ | ||
name: PROCESS_RESIDENT_MEMORY, | ||
help: 'Resident memory size in bytes.', | ||
registers | ||
}); | ||
const virtualMemGauge = new Gauge({ | ||
name: PROCESS_VIRTUAL_MEMORY, | ||
help: 'Virtual memory size in bytes.', | ||
registers | ||
}); | ||
const heapSizeMemGauge = new Gauge({ | ||
name: PROCESS_HEAP, | ||
help: 'Process heap size in bytes.', | ||
registers | ||
}); | ||
return function() { | ||
fs.readFile('/proc/self/status', 'utf8', function(err, status) { | ||
if(err) { | ||
return () => { | ||
fs.readFile('/proc/self/status', 'utf8', (err, status) => { | ||
if (err) { | ||
return; | ||
} | ||
var now = Date.now(); | ||
var structuredOutput = structureOutput(status); | ||
const now = Date.now(); | ||
const structuredOutput = structureOutput(status); | ||
@@ -58,2 +68,6 @@ residentMemGauge.set(structuredOutput.VmRSS, now); | ||
module.exports.metricNames = [PROCESS_RESIDENT_MEMORY, PROCESS_VIRTUAL_MEMORY, PROCESS_HEAP]; | ||
module.exports.metricNames = [ | ||
PROCESS_RESIDENT_MEMORY, | ||
PROCESS_VIRTUAL_MEMORY, | ||
PROCESS_HEAP | ||
]; |
'use strict'; | ||
var Counter = require('../counter'); | ||
var PROCESS_CPU_USER_SECONDS = 'process_cpu_user_seconds_total'; | ||
var PROCESS_CPU_SYSTEM_SECONDS = 'process_cpu_system_seconds_total'; | ||
var PROCESS_CPU_SECONDS = 'process_cpu_seconds_total'; | ||
const Counter = require('../counter'); | ||
const PROCESS_CPU_USER_SECONDS = 'process_cpu_user_seconds_total'; | ||
const PROCESS_CPU_SYSTEM_SECONDS = 'process_cpu_system_seconds_total'; | ||
const PROCESS_CPU_SECONDS = 'process_cpu_seconds_total'; | ||
module.exports = function() { | ||
module.exports = registry => { | ||
// Don't do anything if the function doesn't exist (introduced in node@6.1.0) | ||
if(typeof process.cpuUsage !== 'function') { | ||
return function() { | ||
}; | ||
if (typeof process.cpuUsage !== 'function') { | ||
return () => {}; | ||
} | ||
var cpuUserUsageCounter = new Counter(PROCESS_CPU_USER_SECONDS, | ||
'Total user CPU time spent in seconds.'); | ||
var cpuSystemUsageCounter = new Counter(PROCESS_CPU_SYSTEM_SECONDS, | ||
'Total system CPU time spent in seconds.'); | ||
var cpuUsageCounter = new Counter(PROCESS_CPU_SECONDS, | ||
'Total user and system CPU time spent in seconds.'); | ||
const registers = registry ? [registry] : undefined; | ||
var lastCpuUsage = process.cpuUsage(); | ||
const cpuUserUsageCounter = new Counter({ | ||
name: PROCESS_CPU_USER_SECONDS, | ||
help: 'Total user CPU time spent in seconds.', | ||
registers | ||
}); | ||
const cpuSystemUsageCounter = new Counter({ | ||
name: PROCESS_CPU_SYSTEM_SECONDS, | ||
help: 'Total system CPU time spent in seconds.', | ||
registers | ||
}); | ||
const cpuUsageCounter = new Counter({ | ||
name: PROCESS_CPU_SECONDS, | ||
help: 'Total user and system CPU time spent in seconds.', | ||
registers | ||
}); | ||
return function() { | ||
var cpuUsage = process.cpuUsage(); | ||
var now = Date.now(); | ||
let lastCpuUsage = process.cpuUsage(); | ||
var userUsageMicros = cpuUsage.user - lastCpuUsage.user; | ||
var systemUsageMicros = cpuUsage.system - lastCpuUsage.system; | ||
return () => { | ||
const cpuUsage = process.cpuUsage(); | ||
const now = Date.now(); | ||
const userUsageMicros = cpuUsage.user - lastCpuUsage.user; | ||
const systemUsageMicros = cpuUsage.system - lastCpuUsage.system; | ||
lastCpuUsage = cpuUsage; | ||
@@ -40,3 +50,5 @@ | ||
module.exports.metricNames = [ | ||
PROCESS_CPU_USER_SECONDS, PROCESS_CPU_SYSTEM_SECONDS, PROCESS_CPU_SECONDS | ||
PROCESS_CPU_USER_SECONDS, | ||
PROCESS_CPU_SYSTEM_SECONDS, | ||
PROCESS_CPU_SECONDS | ||
]; |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
const Gauge = require('../gauge'); | ||
var NODEJS_ACTIVE_HANDLES = 'nodejs_active_handles_total'; | ||
const NODEJS_ACTIVE_HANDLES = 'nodejs_active_handles_total'; | ||
module.exports = function() { | ||
module.exports = registry => { | ||
// Don't do anything if the function is removed in later nodes (exists in node@6) | ||
if(typeof process._getActiveHandles !== 'function') { | ||
return function() { | ||
}; | ||
if (typeof process._getActiveHandles !== 'function') { | ||
return () => {}; | ||
} | ||
var gauge = new Gauge(NODEJS_ACTIVE_HANDLES, 'Number of active handles.'); | ||
const gauge = new Gauge({ | ||
name: NODEJS_ACTIVE_HANDLES, | ||
help: 'Number of active handles.', | ||
registers: registry ? [registry] : undefined | ||
}); | ||
return function() { | ||
return () => { | ||
gauge.set(process._getActiveHandles().length, Date.now()); | ||
@@ -18,0 +21,0 @@ }; |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
var fs = require('fs'); | ||
const Gauge = require('../gauge'); | ||
const fs = require('fs'); | ||
var PROCESS_MAX_FDS = 'process_max_fds'; | ||
const PROCESS_MAX_FDS = 'process_max_fds'; | ||
module.exports = function() { | ||
var isSet = false; | ||
module.exports = registry => { | ||
let isSet = false; | ||
if(process.platform !== 'linux') { | ||
return function() { | ||
}; | ||
if (process.platform !== 'linux') { | ||
return () => {}; | ||
} | ||
const fileDescriptorsGauge = new Gauge({ | ||
name: PROCESS_MAX_FDS, | ||
help: 'Maximum number of open file descriptors.', | ||
registers: registry ? [registry] : undefined | ||
}); | ||
var fileDescriptorsGauge = new Gauge(PROCESS_MAX_FDS, 'Maximum number of open file descriptors.'); | ||
return function() { | ||
if(isSet) { | ||
return () => { | ||
if (isSet) { | ||
return; | ||
} | ||
fs.readFile('/proc/sys/fs/file-max', 'utf8', function(err, maxFds) { | ||
if(err) { | ||
fs.readFile('/proc/sys/fs/file-max', 'utf8', (err, maxFds) => { | ||
if (err) { | ||
return; | ||
@@ -26,0 +28,0 @@ } |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
var fs = require('fs'); | ||
const Gauge = require('../gauge'); | ||
const fs = require('fs'); | ||
var PROCESS_OPEN_FDS = 'process_open_fds'; | ||
const PROCESS_OPEN_FDS = 'process_open_fds'; | ||
module.exports = function() { | ||
if(process.platform !== 'linux') { | ||
return function() { | ||
}; | ||
module.exports = registry => { | ||
if (process.platform !== 'linux') { | ||
return () => {}; | ||
} | ||
var fileDescriptorsGauge = new Gauge(PROCESS_OPEN_FDS, 'Number of open file descriptors.'); | ||
const fileDescriptorsGauge = new Gauge({ | ||
name: PROCESS_OPEN_FDS, | ||
help: 'Number of open file descriptors.', | ||
registers: registry ? [registry] : undefined | ||
}); | ||
return function() { | ||
fs.readdir('/proc/self/fd', function(err, list) { | ||
if(err) { | ||
return () => { | ||
fs.readdir('/proc/self/fd', (err, list) => { | ||
if (err) { | ||
return; | ||
@@ -20,0 +23,0 @@ } |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
const Gauge = require('../gauge'); | ||
var NODEJS_ACTIVE_REQUESTS = 'nodejs_active_requests_total'; | ||
const NODEJS_ACTIVE_REQUESTS = 'nodejs_active_requests_total'; | ||
module.exports = function() { | ||
module.exports = registry => { | ||
// Don't do anything if the function is removed in later nodes (exists in node@6) | ||
if(typeof process._getActiveRequests !== 'function') { | ||
return function() { | ||
}; | ||
if (typeof process._getActiveRequests !== 'function') { | ||
return () => {}; | ||
} | ||
var gauge = new Gauge(NODEJS_ACTIVE_REQUESTS, 'Number of active requests.'); | ||
const gauge = new Gauge({ | ||
name: NODEJS_ACTIVE_REQUESTS, | ||
help: 'Number of active requests.', | ||
registers: registry ? [registry] : undefined | ||
}); | ||
return function() { | ||
return () => { | ||
gauge.set(process._getActiveRequests().length, Date.now()); | ||
@@ -18,0 +21,0 @@ }; |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
var nowInSeconds = Math.round(Date.now() / 1000 - process.uptime()); | ||
const Gauge = require('../gauge'); | ||
const nowInSeconds = Math.round(Date.now() / 1000 - process.uptime()); | ||
var PROCESS_START_TIME = 'process_start_time_seconds'; | ||
const PROCESS_START_TIME = 'process_start_time_seconds'; | ||
module.exports = function() { | ||
var cpuUserGauge = new Gauge(PROCESS_START_TIME, 'Start time of the process since unix epoch in seconds.'); | ||
var isSet = false; | ||
module.exports = registry => { | ||
const cpuUserGauge = new Gauge({ | ||
name: PROCESS_START_TIME, | ||
help: 'Start time of the process since unix epoch in seconds.', | ||
registers: registry ? [registry] : undefined | ||
}); | ||
let isSet = false; | ||
return function() { | ||
if(isSet) { | ||
return () => { | ||
if (isSet) { | ||
return; | ||
@@ -15,0 +19,0 @@ } |
'use strict'; | ||
var Gauge = require('../gauge'); | ||
var version = process.version; | ||
var versionSegments = version.slice(1).split('.').map(Number); | ||
const Gauge = require('../gauge'); | ||
const version = process.version; | ||
const versionSegments = version.slice(1).split('.').map(Number); | ||
var NODE_VERSION_INFO = 'nodejs_version_info'; | ||
const NODE_VERSION_INFO = 'nodejs_version_info'; | ||
module.exports = function() { | ||
var nodeVersionGauge = new Gauge(NODE_VERSION_INFO, 'Node.js version info.', ['version', 'major', 'minor', 'patch']); | ||
var isSet = false; | ||
module.exports = registry => { | ||
const nodeVersionGauge = new Gauge({ | ||
name: NODE_VERSION_INFO, | ||
help: 'Node.js version info.', | ||
labelNames: ['version', 'major', 'minor', 'patch'], | ||
registers: registry ? [registry] : undefined | ||
}); | ||
let isSet = false; | ||
return function() { | ||
if(isSet) { | ||
return () => { | ||
if (isSet) { | ||
return; | ||
} | ||
nodeVersionGauge.labels(version, versionSegments[0], versionSegments[1], versionSegments[2]).set(1); | ||
nodeVersionGauge | ||
.labels( | ||
version, | ||
versionSegments[0], | ||
versionSegments[1], | ||
versionSegments[2] | ||
) | ||
.set(1); | ||
isSet = true; | ||
@@ -19,0 +31,0 @@ }; |
'use strict'; | ||
var url = require('url'); | ||
var http = require('http'); | ||
var https = require('https'); | ||
var register = require('./register'); | ||
const url = require('url'); | ||
const http = require('http'); | ||
const https = require('https'); | ||
const globalRegistry = require('./registry').globalRegistry; | ||
function Pushgateway(gatewayUrl, options, registry) { | ||
if(!registry) { | ||
registry = register; | ||
class Pushgateway { | ||
constructor(gatewayUrl, options, registry) { | ||
if (!registry) { | ||
registry = globalRegistry; | ||
} | ||
this.registry = registry; | ||
this.gatewayUrl = gatewayUrl; | ||
this.requestOptions = Object.assign({}, options); | ||
} | ||
this.registry = registry; | ||
this.gatewayUrl = gatewayUrl; | ||
this.requestOptions = Object.assign({}, options); | ||
} | ||
Pushgateway.prototype.pushAdd = function(params, callback) { | ||
if(!params || !params.jobName) { | ||
throw new Error('Missing jobName parameter'); | ||
} | ||
pushAdd(params, callback) { | ||
if (!params || !params.jobName) { | ||
throw new Error('Missing jobName parameter'); | ||
} | ||
useGateway.call(this, 'POST', params.jobName, params.groupings, callback); | ||
}; | ||
Pushgateway.prototype.push = function(params, callback) { | ||
if(!params || !params.jobName) { | ||
throw new Error('Missing jobName parameter'); | ||
useGateway.call(this, 'POST', params.jobName, params.groupings, callback); | ||
} | ||
useGateway.call(this, 'PUT', params.jobName, params.groupings, callback); | ||
}; | ||
Pushgateway.prototype.delete = function(params, callback) { | ||
if(!params || !params.jobName) { | ||
throw new Error('Missing jobName parameter'); | ||
push(params, callback) { | ||
if (!params || !params.jobName) { | ||
throw new Error('Missing jobName parameter'); | ||
} | ||
useGateway.call(this, 'PUT', params.jobName, params.groupings, callback); | ||
} | ||
useGateway.call(this, 'DELETE', params.jobName, params.groupings, callback); | ||
}; | ||
delete(params, callback) { | ||
if (!params || !params.jobName) { | ||
throw new Error('Missing jobName parameter'); | ||
} | ||
useGateway.call(this, 'DELETE', params.jobName, params.groupings, callback); | ||
} | ||
} | ||
function useGateway(method, job, groupings, callback) { | ||
var gatewayUrlParsed = url.parse(this.gatewayUrl); | ||
var gatewayUrlPath = gatewayUrlParsed.pathname && gatewayUrlParsed.pathname !== '/' ? gatewayUrlParsed.pathname : ''; | ||
var path = [gatewayUrlPath, '/metrics/job/', encodeURIComponent(job), generateGroupings(groupings)].join(''); | ||
const gatewayUrlParsed = url.parse(this.gatewayUrl); | ||
const gatewayUrlPath = | ||
gatewayUrlParsed.pathname && gatewayUrlParsed.pathname !== '/' | ||
? gatewayUrlParsed.pathname | ||
: ''; | ||
const path = `${gatewayUrlPath}/metrics/job/${encodeURIComponent( | ||
job | ||
)}${generateGroupings(groupings)}`; | ||
var target = url.resolve(this.gatewayUrl, path); | ||
var requestParams = url.parse(target); | ||
var httpModule = isHttps(requestParams.href) ? https : http; | ||
var options = Object.assign(requestParams, this.requestOptions, { | ||
method: method | ||
const target = url.resolve(this.gatewayUrl, path); | ||
const requestParams = url.parse(target); | ||
const httpModule = isHttps(requestParams.href) ? https : http; | ||
const options = Object.assign(requestParams, this.requestOptions, { | ||
method | ||
}); | ||
var req = httpModule.request(options, function(res) { | ||
var body = ''; | ||
const req = httpModule.request(options, res => { | ||
let body = ''; | ||
res.setEncoding('utf8'); | ||
res.on('data', function(chunk) { | ||
res.on('data', chunk => { | ||
body += chunk; | ||
}); | ||
res.on('end', function() { | ||
res.on('end', () => { | ||
callback(null, res, body); | ||
}); | ||
}); | ||
req.on('error', function(err) { | ||
req.on('error', err => { | ||
callback(err); | ||
}); | ||
if(method !== 'DELETE') { | ||
if (method !== 'DELETE') { | ||
req.write(this.registry.metrics()); | ||
@@ -73,8 +80,10 @@ } | ||
function generateGroupings(groupings) { | ||
if(!groupings) { | ||
if (!groupings) { | ||
return ''; | ||
} | ||
return Object.keys(groupings).map(function(key) { | ||
return ['/', encodeURIComponent(key), '/', encodeURIComponent(groupings[key])].join(''); | ||
}).join(''); | ||
return Object.keys(groupings) | ||
.map( | ||
key => `/${encodeURIComponent(key)}/${encodeURIComponent(groupings[key])}` | ||
) | ||
.join(''); | ||
} | ||
@@ -81,0 +90,0 @@ |
@@ -7,3 +7,3 @@ 'use strict'; | ||
function escapeLabelValue(str) { | ||
if(typeof str !== 'string') { | ||
if (typeof str !== 'string') { | ||
return str; | ||
@@ -13,29 +13,30 @@ } | ||
} | ||
var registry = (function() { | ||
var _metrics = {}; | ||
var self; | ||
function Registry() { | ||
self = this; | ||
class Registry { | ||
constructor() { | ||
this._metrics = {}; | ||
this._defaultLabels = {}; | ||
} | ||
Registry.prototype.getMetricsAsArray = function() { | ||
return Object.keys(_metrics) | ||
.map(self.getSingleMetric, self); | ||
}; | ||
getMetricsAsArray() { | ||
return Object.keys(this._metrics).map(this.getSingleMetric, this); | ||
} | ||
Registry.prototype.getMetricAsPrometheusString = function(metric) { | ||
var item = metric.get(); | ||
var name = escapeString(item.name); | ||
var help = escapeString(item.help); | ||
getMetricAsPrometheusString(metric) { | ||
const item = metric.get(); | ||
const name = escapeString(item.name); | ||
let help = escapeString(item.help); | ||
help = ['#', 'HELP', name, help].join(' '); | ||
var type = ['#', 'TYPE', name, item.type].join(' '); | ||
const type = ['#', 'TYPE', name, item.type].join(' '); | ||
var values = (item.values || []).reduce(function(valAcc, val) { | ||
var labels = Object.keys(val.labels || {}).map(function(key) { | ||
return key + '="' + escapeLabelValue(val.labels[key]) + '"'; | ||
}); | ||
const values = (item.values || []).reduce((valAcc, val) => { | ||
const merged = Object.assign({}, this._defaultLabels, val.labels); | ||
var metricName = val.metricName || item.name; | ||
if(labels.length) { | ||
metricName += '{' + labels.join(',') + '}'; | ||
const labels = Object.keys(merged).map( | ||
key => `${key}="${escapeLabelValue(merged[key])}"` | ||
); | ||
let metricName = val.metricName || item.name; | ||
if (labels.length) { | ||
metricName += `{${labels.join(',')}}`; | ||
} | ||
@@ -48,57 +49,68 @@ | ||
var acc = [help, type, values].join('\n'); | ||
const acc = [help, type, values].join('\n'); | ||
return acc; | ||
}; | ||
} | ||
Registry.prototype.metrics = function() { | ||
return self.getMetricsAsArray() | ||
metrics() { | ||
return this.getMetricsAsArray() | ||
.map(this.getMetricAsPrometheusString, this) | ||
.join('\n'); | ||
}; | ||
} | ||
Registry.prototype.registerMetric = function(metricFn) { | ||
if(_metrics[metricFn.name] && _metrics[metricFn.name] !== metricFn) { | ||
throw new Error('A metric with the name ' + metricFn.name + ' has already been registered.'); | ||
registerMetric(metricFn) { | ||
if ( | ||
this._metrics[metricFn.name] && | ||
this._metrics[metricFn.name] !== metricFn | ||
) { | ||
throw new Error( | ||
`A metric with the name ${metricFn.name} has already been registered.` | ||
); | ||
} | ||
_metrics[metricFn.name] = metricFn; | ||
}; | ||
this._metrics[metricFn.name] = metricFn; | ||
} | ||
Registry.prototype.clear = function() { | ||
_metrics = {}; | ||
}; | ||
clear() { | ||
this._metrics = {}; | ||
this._defaultLabels = {}; | ||
} | ||
Registry.prototype.getMetricsAsJSON = function() { | ||
return self.getMetricsAsArray().map(function(metric) { | ||
return metric.get(); | ||
}); | ||
}; | ||
getMetricsAsJSON() { | ||
return this.getMetricsAsArray().map(metric => metric.get()); | ||
} | ||
Registry.prototype.removeSingleMetric = function(name) { | ||
delete _metrics[name]; | ||
}; | ||
removeSingleMetric(name) { | ||
delete this._metrics[name]; | ||
} | ||
Registry.prototype.getSingleMetricAsString = function(name) { | ||
return this.getMetricAsPrometheusString(_metrics[name]); | ||
}; | ||
getSingleMetricAsString(name) { | ||
return this.getMetricAsPrometheusString(this._metrics[name]); | ||
} | ||
Registry.prototype.getSingleMetric = function(name) { | ||
return _metrics[name]; | ||
}; | ||
getSingleMetric(name) { | ||
return this._metrics[name]; | ||
} | ||
Registry.prototype.contentType = 'text/plain; version=0.0.4; charset=utf-8'; | ||
return new Registry(); | ||
}); | ||
setDefaultLabels(labels) { | ||
this._defaultLabels = labels; | ||
} | ||
module.exports = registry; | ||
get contentType() { | ||
return 'text/plain; version=0.0.4; charset=utf-8'; | ||
} | ||
registry.merge = function(registers) { | ||
var mergedRegistry = new registry(); | ||
static merge(registers) { | ||
const mergedRegistry = new Registry(); | ||
var metricsToMerge = registers.reduce(function(acc, reg) { | ||
return acc.concat(reg.getMetricsAsArray()); | ||
}, []); | ||
const metricsToMerge = registers.reduce( | ||
(acc, reg) => acc.concat(reg.getMetricsAsArray()), | ||
[] | ||
); | ||
metricsToMerge.forEach(mergedRegistry.registerMetric); | ||
return mergedRegistry; | ||
}; | ||
metricsToMerge.forEach(mergedRegistry.registerMetric, mergedRegistry); | ||
return mergedRegistry; | ||
} | ||
} | ||
module.exports = Registry; | ||
module.exports.globalRegistry = new Registry(); |
@@ -6,105 +6,134 @@ /** | ||
var globalRegistry = require('./register'); | ||
var type = 'summary'; | ||
var isNumber = require('./util').isNumber; | ||
var extend = require('util-extend'); | ||
var getProperties = require('./util').getPropertiesFromObj; | ||
var getLabels = require('./util').getLabels; | ||
var hashObject = require('./util').hashObject; | ||
var validateLabels = require('./validation').validateLabel; | ||
var validateMetricName = require('./validation').validateMetricName; | ||
var validateLabelNames = require('./validation').validateLabelName; | ||
var TDigest = require('tdigest').TDigest; | ||
var isObject = require('util').isObject; | ||
var extend = require('util-extend'); | ||
const globalRegistry = require('./registry').globalRegistry; | ||
const type = 'summary'; | ||
const isNumber = require('./util').isNumber; | ||
const getProperties = require('./util').getPropertiesFromObj; | ||
const getLabels = require('./util').getLabels; | ||
const hashObject = require('./util').hashObject; | ||
const validateLabels = require('./validation').validateLabel; | ||
const validateMetricName = require('./validation').validateMetricName; | ||
const validateLabelNames = require('./validation').validateLabelName; | ||
const TDigest = require('tdigest').TDigest; | ||
const isObject = require('util').isObject; | ||
const printDeprecationObjectConstructor = require('./util') | ||
.printDeprecationObjectConstructor; | ||
/** | ||
* 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 | ||
* @constructor | ||
*/ | ||
function Summary(name, help, labelsOrConf, conf) { | ||
var config; | ||
if(isObject(name)) { | ||
config = extend({ | ||
percentiles: [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999], | ||
labelNames: [], | ||
registers: [ globalRegistry ], | ||
}, name); | ||
} else { | ||
var obj; | ||
var labels = []; | ||
class Summary { | ||
/** | ||
* 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 | ||
*/ | ||
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(Array.isArray(labelsOrConf)) { | ||
obj = conf || {}; | ||
labels = labelsOrConf; | ||
if (!config.registers) { | ||
config.registers = [globalRegistry]; | ||
} | ||
} else { | ||
obj = labelsOrConf || {}; | ||
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] | ||
}; | ||
} | ||
config = { | ||
name: name, | ||
help: help, | ||
labelNames: labels, | ||
percentiles: configurePercentiles(obj.percentiles), | ||
registers: [ globalRegistry ] | ||
}; | ||
} | ||
validateInput(config.name, config.help, config.labelNames); | ||
validateInput(config.name, config.help, config.labelNames); | ||
this.name = config.name; | ||
this.help = config.help; | ||
this.name = config.name; | ||
this.help = config.help; | ||
this.percentiles = config.percentiles; | ||
this.hashMap = {}; | ||
this.labelNames = config.labelNames || []; | ||
this.percentiles = config.percentiles; | ||
this.hashMap = {}; | ||
this.labelNames = config.labelNames || []; | ||
config.registers.forEach(registryInstance => | ||
registryInstance.registerMetric(this) | ||
); | ||
} | ||
var metric = this; | ||
config.registers.forEach(function(registryInstance) { | ||
registryInstance.registerMetric(metric); | ||
}); | ||
} | ||
/** | ||
* Observe a value | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @param {Number} value - Value to observe | ||
* @returns {void} | ||
*/ | ||
observe(labels, value) { | ||
observe.call(this, labels === 0 ? 0 : labels || {})(value); | ||
} | ||
/** | ||
* Observe a value | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @param {Number} value - Value to observe | ||
* @returns {void} | ||
*/ | ||
Summary.prototype.observe = function(labels, value) { | ||
observe.call(this, labels === 0 ? 0 : (labels || {}))(value); | ||
}; | ||
get() { | ||
const data = getProperties(this.hashMap); | ||
const values = []; | ||
data.forEach(s => { | ||
extractSummariesForExport(s, this.percentiles).forEach(v => { | ||
values.push(v); | ||
}); | ||
values.push(getSumForExport(s, this)); | ||
values.push(getCountForExport(s, this)); | ||
}); | ||
Summary.prototype.get = function() { | ||
var summary = this; | ||
var data = getProperties(summary.hashMap); | ||
var values = []; | ||
data.forEach(function(s) { | ||
extractSummariesForExport(s, summary.percentiles).forEach(function(v) { | ||
values.push(v); | ||
return { | ||
name: this.name, | ||
help: this.help, | ||
type, | ||
values | ||
}; | ||
} | ||
reset() { | ||
const data = getProperties(this.hashMap); | ||
data.forEach(s => { | ||
s.td.reset(); | ||
s.count = 0; | ||
s.sum = 0; | ||
}); | ||
values.push(getSumForExport(s, summary)); | ||
values.push(getCountForExport(s, summary)); | ||
}); | ||
} | ||
return { | ||
name: this.name, | ||
help: this.help, | ||
type: type, | ||
values: values | ||
}; | ||
}; | ||
/** | ||
* Start a timer that could be used to logging durations | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {function} - Function to invoke when you want to stop the timer and observe the duration in seconds | ||
* @example | ||
* var end = summary.startTimer(); | ||
* makeExpensiveXHRRequest(function(err, res) { | ||
* end(); //Observe the duration of expensiveXHRRequest | ||
* }); | ||
*/ | ||
startTimer(labels) { | ||
return startTimer.call(this, labels)(); | ||
} | ||
Summary.prototype.reset = function() { | ||
var data = getProperties(this.hashMap); | ||
data.forEach(function(s) { | ||
s.td.reset(); | ||
s.count = 0; | ||
s.sum = 0; | ||
}); | ||
}; | ||
labels() { | ||
const labels = getLabels(this.labelNames, arguments); | ||
return { | ||
observe: observe.call(this, labels), | ||
startTimer: startTimer.call(this, labels) | ||
}; | ||
} | ||
} | ||
@@ -114,6 +143,6 @@ function extractSummariesForExport(summaryOfLabels, percentiles) { | ||
return percentiles.map(function(percentile) { | ||
var percentileValue = summaryOfLabels.td.percentile(percentile); | ||
return percentiles.map(percentile => { | ||
const percentileValue = summaryOfLabels.td.percentile(percentile); | ||
return { | ||
labels: extend({ quantile: percentile }, summaryOfLabels.labels), | ||
labels: Object.assign({ quantile: percentile }, summaryOfLabels.labels), | ||
value: percentileValue ? percentileValue : 0 | ||
@@ -126,3 +155,3 @@ }; | ||
return { | ||
metricName: summary.name + '_count', | ||
metricName: `${summary.name}_count`, | ||
labels: value.labels, | ||
@@ -135,3 +164,3 @@ value: value.count | ||
return { | ||
metricName: summary.name + '_sum', | ||
metricName: `${summary.name}_sum`, | ||
labels: value.labels, | ||
@@ -142,32 +171,11 @@ value: value.sum | ||
/** | ||
* Start a timer that could be used to logging durations | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {function} - Function to invoke when you want to stop the timer and observe the duration in seconds | ||
* @example | ||
* var end = summary.startTimer(); | ||
* makeExpensiveXHRRequest(function(err, res) { | ||
* end(); //Observe the duration of expensiveXHRRequest | ||
* }); | ||
*/ | ||
Summary.prototype.startTimer = function(labels) { | ||
return startTimer.call(this, labels)(); | ||
}; | ||
Summary.prototype.labels = function() { | ||
var labels = getLabels(this.labelNames, arguments); | ||
return { | ||
observe: observe.call(this, labels), | ||
startTimer: startTimer.call(this, labels) | ||
}; | ||
}; | ||
function startTimer(startLabels) { | ||
var summary = this; | ||
return function() { | ||
var start = process.hrtime(); | ||
return function(endLabels) { | ||
var delta = process.hrtime(start); | ||
summary.observe(extend(startLabels || {}, endLabels), delta[0] + delta[1] / 1e9); | ||
return () => { | ||
const start = process.hrtime(); | ||
return endLabels => { | ||
const delta = process.hrtime(start); | ||
this.observe( | ||
Object.assign(startLabels || {}, endLabels), | ||
delta[0] + delta[1] / 1e9 | ||
); | ||
}; | ||
@@ -178,19 +186,19 @@ }; | ||
function validateInput(name, help, labels) { | ||
if(!help) { | ||
if (!help) { | ||
throw new Error('Missing mandatory help parameter'); | ||
} | ||
if(!name) { | ||
if (!name) { | ||
throw new Error('Missing mandatory name parameter'); | ||
} | ||
if(!validateMetricName(name)) { | ||
if (!validateMetricName(name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
if(!validateLabelNames(labels)) { | ||
if (!validateLabelNames(labels)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
labels.forEach(function(label) { | ||
if(label === 'quantile') { | ||
labels.forEach(label => { | ||
if (label === 'quantile') { | ||
throw new Error('quantile is a reserved label keyword'); | ||
@@ -202,4 +210,6 @@ } | ||
function configurePercentiles(configuredPercentiles) { | ||
var defaultPercentiles = [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999]; | ||
return [].concat((configuredPercentiles || defaultPercentiles)).sort(sortAscending); | ||
const defaultPercentiles = [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999]; | ||
return [] | ||
.concat(configuredPercentiles || defaultPercentiles) | ||
.sort(sortAscending); | ||
} | ||
@@ -211,34 +221,14 @@ | ||
function createValuePair(labels, value, metricName) { | ||
return { | ||
labels: labels, | ||
value: value, | ||
metricName: metricName | ||
}; | ||
} | ||
function findBound(upperBounds, value) { | ||
for(var i = 0; i < upperBounds.length; i++) { | ||
var bound = upperBounds[i]; | ||
if(value <= bound) { | ||
return bound; | ||
} | ||
} | ||
return -1; | ||
} | ||
function observe(labels) { | ||
var summary = this; | ||
return function(value) { | ||
var labelValuePair = convertLabelsAndValues(labels, value); | ||
return value => { | ||
const labelValuePair = convertLabelsAndValues(labels, value); | ||
validateLabels(summary.labelNames, summary.labels); | ||
if(!isNumber(labelValuePair.value)) { | ||
validateLabels(this.labelNames, this.labels); | ||
if (!isNumber(labelValuePair.value)) { | ||
throw new Error('Value is not a valid number', labelValuePair.value); | ||
} | ||
var hash = hashObject(labelValuePair.labels); | ||
var summaryOfLabel = summary.hashMap[hash]; | ||
if(!summaryOfLabel) { | ||
const hash = hashObject(labelValuePair.labels); | ||
let summaryOfLabel = this.hashMap[hash]; | ||
if (!summaryOfLabel) { | ||
summaryOfLabel = { | ||
@@ -255,3 +245,3 @@ labels: labelValuePair.labels, | ||
summaryOfLabel.sum += labelValuePair.value; | ||
summary.hashMap[hash] = summaryOfLabel; | ||
this.hashMap[hash] = summaryOfLabel; | ||
}; | ||
@@ -261,3 +251,3 @@ } | ||
function convertLabelsAndValues(labels, value) { | ||
if(isNumber(labels)) { | ||
if (isNumber(labels)) { | ||
return { | ||
@@ -269,4 +259,4 @@ value: labels, | ||
return { | ||
labels: labels, | ||
value: value | ||
labels, | ||
value | ||
}; | ||
@@ -273,0 +263,0 @@ } |
'use strict'; | ||
const deprecationsEmitted = {}; | ||
exports.isNumber = isNumber; | ||
@@ -7,15 +9,14 @@ exports.isDate = isDate; | ||
exports.getPropertiesFromObj = function(hashMap) { | ||
var obj = Object.keys(hashMap).map(function(x) { | ||
return hashMap[x]; | ||
}); | ||
const obj = Object.keys(hashMap).map(x => hashMap[x]); | ||
return obj; | ||
}; | ||
exports.setValue = function setValue(hashMap, value, labels, timestamp) { | ||
var hash = hashObject(labels); | ||
const hash = hashObject(labels); | ||
hashMap[hash] = { | ||
value: isNumber(value) ? value : 0, | ||
labels: labels || {}, | ||
timestamp: isDate(timestamp) ? timestamp.valueOf() : isNumber(timestamp) ? timestamp : undefined | ||
timestamp: isDate(timestamp) | ||
? timestamp.valueOf() | ||
: isNumber(timestamp) ? timestamp : undefined | ||
}; | ||
@@ -25,9 +26,10 @@ return hashMap; | ||
// TODO: For node 6, use rest params | ||
exports.getLabels = function(labelNames, args) { | ||
if(labelNames.length !== args.length) { | ||
if (labelNames.length !== args.length) { | ||
throw new Error('Invalid number of arguments'); | ||
} | ||
var argsAsArray = Array.prototype.slice.call(args); | ||
return labelNames.reduce(function(acc, label, index) { | ||
const argsAsArray = Array.prototype.slice.call(args); | ||
return labelNames.reduce((acc, label, index) => { | ||
acc[label] = argsAsArray[index]; | ||
@@ -38,3 +40,2 @@ return acc; | ||
function hashObject(labels) { | ||
@@ -44,14 +45,14 @@ // We don't actually need a hash here. We just need a string that | ||
// calls with equivalent labels objects. | ||
var keys = Object.keys(labels); | ||
if(keys.length === 0) { | ||
let keys = Object.keys(labels); | ||
if (keys.length === 0) { | ||
return ''; | ||
} | ||
// else | ||
if(keys.length > 1) { | ||
keys = keys.sort(); // need consistency across calls | ||
if (keys.length > 1) { | ||
keys = keys.sort(); // need consistency across calls | ||
} | ||
var elems = []; | ||
for(var i = 0; i < keys.length; i++) { | ||
elems.push(keys[i] + ':' + labels[keys[i]]); | ||
const elems = []; | ||
for (let i = 0; i < keys.length; i++) { | ||
elems.push(`${keys[i]}:${labels[keys[i]]}`); | ||
} | ||
@@ -72,1 +73,29 @@ return elems.join(','); | ||
}; | ||
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} })\`.` | ||
); | ||
}; |
'use strict'; | ||
var util = require('util'); | ||
const util = require('util'); | ||
// These are from https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels | ||
var metricRegexp = /^[a-zA-Z_:][a-zA-Z0-9_:]*$/; | ||
var labelRegexp = /^[a-zA-Z_][a-zA-Z0-9_]*$/; | ||
const metricRegexp = /^[a-zA-Z_:][a-zA-Z0-9_:]*$/; | ||
const labelRegexp = /^[a-zA-Z_][a-zA-Z0-9_]*$/; | ||
@@ -14,5 +14,5 @@ exports.validateMetricName = function(name) { | ||
exports.validateLabelName = function(names) { | ||
var valid = true; | ||
(names || []).forEach(function(name) { | ||
if(!labelRegexp.test(name)) { | ||
let valid = true; | ||
(names || []).forEach(name => { | ||
if (!labelRegexp.test(name)) { | ||
valid = false; | ||
@@ -25,7 +25,11 @@ } | ||
exports.validateLabel = function validateLabel(savedLabels, labels) { | ||
Object.keys(labels).forEach(function(label) { | ||
if(savedLabels.indexOf(label) === -1) { | ||
throw new Error('Added label "' + label + '" is not included in initial labelset: ' + util.inspect(savedLabels)); | ||
Object.keys(labels).forEach(label => { | ||
if (savedLabels.indexOf(label) === -1) { | ||
throw new Error( | ||
`Added label "${label}" is not included in initial labelset: ${util.inspect( | ||
savedLabels | ||
)}` | ||
); | ||
} | ||
}); | ||
}; |
{ | ||
"name": "prom-client", | ||
"version": "9.1.1", | ||
"version": "10.0.0", | ||
"description": "Client for prometheus", | ||
@@ -11,10 +11,11 @@ "main": "index.js", | ||
], | ||
"directories": { | ||
"test": "test" | ||
"engines": { | ||
"node": ">=4" | ||
}, | ||
"scripts": { | ||
"test": "npm run lint && npm run compile-typescript && npm run test-unit", | ||
"lint": "node-version-gte-4 && eslint . || node-version-lt-4", | ||
"test-unit": "mocha --recursive test/", | ||
"compile-typescript": "tsc index.d.ts --noImplicitAny" | ||
"lint": "eslint .", | ||
"test-unit": "jest", | ||
"compile-typescript": "tsc index.d.ts --noImplicitAny", | ||
"precommit": "lint-staged" | ||
}, | ||
@@ -34,17 +35,30 @@ "repository": { | ||
"devDependencies": { | ||
"chai": "^3.4.1", | ||
"eslint": "^3.5.0", | ||
"eslint": "^4.1.1", | ||
"eslint-plugin-prettier": "^2.1.2", | ||
"express": "^4.13.3", | ||
"mocha": "^3.2.0", | ||
"mockery": "^2.0.0", | ||
"nock": "^9.0.11", | ||
"node-version-check": "^2.1.1", | ||
"sinon": "^2.0.0", | ||
"husky": "^0.13.4", | ||
"jest": "^20.0.4", | ||
"lint-staged": "^4.0.0", | ||
"lolex": "^1.6.0", | ||
"prettier": "1.5.2", | ||
"typescript": "^2.0.3" | ||
}, | ||
"dependencies": { | ||
"tdigest": "^0.1.1", | ||
"util-extend": "^1.0.1" | ||
"tdigest": "^0.1.1" | ||
}, | ||
"types": "./index.d.ts" | ||
"types": "./index.d.ts", | ||
"jest": { | ||
"testEnvironment": "node", | ||
"testRegex": ".*Test\\.js$" | ||
}, | ||
"lint-staged": { | ||
"*.js": [ | ||
"eslint --fix", | ||
"git add" | ||
], | ||
"*.ts": [ | ||
"prettier --write --use-tabs --single-quote", | ||
"git add" | ||
] | ||
} | ||
} |
103
README.md
@@ -26,14 +26,27 @@ # 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) | ||
The function returned from `collectDefaultMetrics` takes 1 option, a timeout for how often the probe should | ||
be fired. By default probes are launched every 10 seconds, but this can be modified like this: | ||
`collectDefaultMetrics` takes 1 options object with 2 entries, a timeout for how often the probe should be fired and a | ||
registry to which metrics should be registered. By default probes are launched every 10 seconds, but this can be | ||
modified like this: | ||
```js | ||
var client = require('prom-client'); | ||
const client = require('prom-client'); | ||
var collectDefaultMetrics = client.collectDefaultMetrics; | ||
const collectDefaultMetrics = client.collectDefaultMetrics; | ||
// Probe every 5th second. | ||
collectDefaultMetrics(5000); | ||
collectDefaultMetrics({ timeout: 5000 }); | ||
```` | ||
To register metrics to another registry, pass it in as `register`: | ||
```js | ||
const client = require('prom-client'); | ||
const collectDefaultMetrics = client.collectDefaultMetrics; | ||
const Registry = client.Registry; | ||
const register = new Registry(); | ||
collectDefaultMetrics({ register }); | ||
```` | ||
You can get the full list of metrics by inspecting `client.collectDefaultMetrics.metricsList`. | ||
@@ -47,7 +60,7 @@ | ||
```js | ||
var client = require('prom-client'); | ||
const client = require('prom-client'); | ||
var collectDefaultMetrics = client.collectDefaultMetrics; | ||
const collectDefaultMetrics = client.collectDefaultMetrics; | ||
var interval = collectDefaultMetrics(); | ||
const interval = collectDefaultMetrics(); | ||
@@ -67,3 +80,3 @@ // ... some time later | ||
```js | ||
var client = require('prom-client'); | ||
const client = require('prom-client'); | ||
@@ -81,4 +94,4 @@ clearInterval(client.collectDefaultMetrics()); | ||
```js | ||
var client = require('prom-client'); | ||
var counter = new client.Counter({ name: 'metric_name', help: 'metric_help' }); | ||
const client = require('prom-client'); | ||
const counter = new client.Counter({ name: 'metric_name', help: 'metric_help' }); | ||
counter.inc(); // Inc with 1 | ||
@@ -93,4 +106,4 @@ counter.inc(10); // Inc with 10 | ||
```js | ||
var client = require('prom-client'); | ||
var gauge = new client.Gauge({ name: 'metric_name', help: 'metric_help' }); | ||
const client = require('prom-client'); | ||
const gauge = new client.Gauge({ name: 'metric_name', help: 'metric_help' }); | ||
gauge.set(10); // Set to 10 | ||
@@ -108,3 +121,3 @@ gauge.inc(); // Inc with 1 | ||
var end = gauge.startTimer(); | ||
const end = gauge.startTimer(); | ||
xhrRequest(function(err, res) { | ||
@@ -123,3 +136,3 @@ end(); // Sets value to xhrRequests duration in seconds | ||
```js | ||
var client = require('prom-client'); | ||
const client = require('prom-client'); | ||
new client.Histogram({ name: 'metric_name', help: 'metric_help', buckets: [ 0.10, 5, 15, 50, 100, 500 ] }); | ||
@@ -129,3 +142,3 @@ ``` | ||
```js | ||
var client = require('prom-client'); | ||
const client = require('prom-client'); | ||
new client.Histogram({ name: 'metric_name', help: 'metric_help', labelNames: [ 'status_code' ], buckets: [ 0.10, 5, 15, 50, 100, 500 ] }); | ||
@@ -137,4 +150,4 @@ ``` | ||
```js | ||
var client = require('prom-client'); | ||
var histogram = new client.Histogram({ name: 'metric_name', help: 'metric_help' }); | ||
const client = require('prom-client'); | ||
const histogram = new client.Histogram({ name: 'metric_name', help: 'metric_help' }); | ||
histogram.observe(10); // Observe value in histogram | ||
@@ -145,3 +158,3 @@ ``` | ||
```js | ||
var end = histogram.startTimer(); | ||
const end = histogram.startTimer(); | ||
xhrRequest(function(err, res) { | ||
@@ -161,3 +174,3 @@ end(); // Observes the value to xhrRequests duration in seconds | ||
```js | ||
var client = require('prom-client'); | ||
const client = require('prom-client'); | ||
new client.Summary({ name: 'metric_name', help: 'metric_help', percentiles: [ 0.01, 0.1, 0.9, 0.99 ] }); | ||
@@ -169,4 +182,4 @@ ``` | ||
```js | ||
var client = require('prom-client'); | ||
var summary = new client.Summary({ name: 'metric_name', help: 'metric_help' }); | ||
const client = require('prom-client'); | ||
const summary = new client.Summary({ name: 'metric_name', help: 'metric_help' }); | ||
summary.observe(10); | ||
@@ -177,3 +190,3 @@ ``` | ||
```js | ||
var end = summary.startTimer(); | ||
const end = summary.startTimer(); | ||
xhrRequest(function(err, res) { | ||
@@ -188,4 +201,4 @@ end(); // Observes the value to xhrRequests duration in seconds | ||
```js | ||
var client = require('prom-client'); | ||
var gauge = new client.Gauge({ name: 'metric_name', help: 'metric_help', labelNames: [ 'method', 'statusCode' ] }); | ||
const client = require('prom-client'); | ||
const gauge = new client.Gauge({ name: 'metric_name', help: 'metric_help', labelNames: [ 'method', 'statusCode' ] }); | ||
@@ -198,3 +211,3 @@ gauge.set({ method: 'GET', statusCode: '200' }, 100); // 1st version, Set value 100 with method set to GET and statusCode to 200 | ||
```js | ||
var end = startTimer({ method: 'GET' }); // Set method to GET, we don't know statusCode yet | ||
const end = startTimer({ method: 'GET' }); // Set method to GET, we don't know statusCode yet | ||
xhrRequest(function(err, res) { | ||
@@ -209,2 +222,22 @@ if (err) { | ||
##### Default Labels (segmented by registry) | ||
Static labels may be applied to every metric emitted by a registry: | ||
```js | ||
const client = require('prom-client'); | ||
const defaultLabels = { serviceName: "api-v1" }; | ||
client.register.setDefaultLabels(defaultLabels); | ||
``` | ||
This will output metrics in the following way: | ||
``` | ||
# HELP process_resident_memory_bytes Resident memory size in bytes. | ||
# TYPE process_resident_memory_bytes gauge | ||
process_resident_memory_bytes{serviceName="api-v1"} 33853440 1498510040309 | ||
``` | ||
Default labels will be overridden if there is a name conflict. | ||
`register.clear()` will clear default labels. | ||
#### Timestamps | ||
@@ -237,10 +270,10 @@ | ||
```js | ||
var client = require('prom-client'); | ||
var registry = new client.Registry(); | ||
var counter = new client.Counter({name: 'metric_name', help: 'metric_help', registers: [ registry ]}); | ||
var histogram = new client.Histogram({name: 'metric_name', help: 'metric_help', registers: [ ]}); | ||
const client = require('prom-client'); | ||
const registry = new client.Registry(); | ||
const counter = new client.Counter({name: 'metric_name', help: 'metric_help', registers: [ registry ]}); | ||
const histogram = new client.Histogram({name: 'metric_name', help: 'metric_help', registers: [ ]}); | ||
registry.registerMetric(histogram); | ||
counter.inc(); | ||
var mergedRegistries = client.Registry.merge([registry, client.register]); | ||
const mergedRegistries = client.Registry.merge([registry, client.register]); | ||
``` | ||
@@ -252,3 +285,3 @@ | ||
##### Geting a single metric for Prometheus displaying | ||
##### Getting a single metric for Prometheus displaying | ||
@@ -271,4 +304,4 @@ If you need to output a single metric for Prometheus, you can use `register.getSingleMetricAsString(*name of metric*)`, it will output a string for Prometheus to consume. | ||
```js | ||
var client = require('prom-client'); | ||
var gateway = new client.Pushgateway('http://127.0.0.1:9091'); | ||
const client = require('prom-client'); | ||
let gateway = new client.Pushgateway('http://127.0.0.1:9091'); | ||
@@ -292,3 +325,3 @@ gateway.pushAdd({ jobName: 'test' }, function(err, resp, body) { }); //Add metric and overwrite old ones | ||
```js | ||
var client = require('prom-client'); | ||
const client = require('prom-client'); | ||
new client.Histogram({ | ||
@@ -295,0 +328,0 @@ name: 'metric_name', |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
85531
1
2109
325
2
29
1
- Removedutil-extend@^1.0.1
- Removedutil-extend@1.0.3(transitive)