137 lines
3.2 KiB
JavaScript
137 lines
3.2 KiB
JavaScript
'use strict';
|
|
|
|
const url = require('url');
|
|
const http = require('http');
|
|
const https = require('https');
|
|
const { gzipSync } = require('zlib');
|
|
const { globalRegistry } = require('./registry');
|
|
|
|
class Pushgateway {
|
|
constructor(gatewayUrl, options, registry) {
|
|
if (!registry) {
|
|
registry = globalRegistry;
|
|
}
|
|
this.registry = registry;
|
|
this.gatewayUrl = gatewayUrl;
|
|
const { requireJobName, ...requestOptions } = {
|
|
requireJobName: true,
|
|
...options,
|
|
};
|
|
this.requireJobName = requireJobName;
|
|
this.requestOptions = requestOptions;
|
|
}
|
|
|
|
pushAdd(params = {}) {
|
|
if (this.requireJobName && !params.jobName) {
|
|
throw new Error('Missing jobName parameter');
|
|
}
|
|
|
|
return useGateway.call(this, 'POST', params.jobName, params.groupings);
|
|
}
|
|
|
|
push(params = {}) {
|
|
if (this.requireJobName && !params.jobName) {
|
|
throw new Error('Missing jobName parameter');
|
|
}
|
|
|
|
return useGateway.call(this, 'PUT', params.jobName, params.groupings);
|
|
}
|
|
|
|
delete(params = {}) {
|
|
if (this.requireJobName && !params.jobName) {
|
|
throw new Error('Missing jobName parameter');
|
|
}
|
|
|
|
return useGateway.call(this, 'DELETE', params.jobName, params.groupings);
|
|
}
|
|
}
|
|
async function useGateway(method, job, groupings) {
|
|
// `URL` first added in v6.13.0
|
|
// eslint-disable-next-line n/no-deprecated-api
|
|
const gatewayUrlParsed = url.parse(this.gatewayUrl);
|
|
const gatewayUrlPath =
|
|
gatewayUrlParsed.pathname && gatewayUrlParsed.pathname !== '/'
|
|
? gatewayUrlParsed.pathname
|
|
: '';
|
|
const jobPath = job
|
|
? `/job/${encodeURIComponent(job)}${generateGroupings(groupings)}`
|
|
: '';
|
|
const path = `${gatewayUrlPath}/metrics${jobPath}`;
|
|
|
|
// eslint-disable-next-line n/no-deprecated-api
|
|
const target = url.resolve(this.gatewayUrl, path);
|
|
// eslint-disable-next-line n/no-deprecated-api
|
|
const requestParams = url.parse(target);
|
|
const httpModule = isHttps(requestParams.href) ? https : http;
|
|
const options = Object.assign(requestParams, this.requestOptions, {
|
|
method,
|
|
});
|
|
|
|
return new Promise((resolve, reject) => {
|
|
if (method === 'DELETE' && options.headers) {
|
|
delete options.headers['Content-Encoding'];
|
|
}
|
|
const req = httpModule.request(options, resp => {
|
|
let body = '';
|
|
resp.setEncoding('utf8');
|
|
resp.on('data', chunk => {
|
|
body += chunk;
|
|
});
|
|
resp.on('end', () => {
|
|
if (resp.statusCode >= 400) {
|
|
reject(
|
|
new Error(`push failed with status ${resp.statusCode}, ${body}`),
|
|
);
|
|
} else {
|
|
resolve({ resp, body });
|
|
}
|
|
});
|
|
});
|
|
req.on('error', err => {
|
|
reject(err);
|
|
});
|
|
|
|
req.on('timeout', () => {
|
|
req.destroy(new Error('Pushgateway request timed out'));
|
|
});
|
|
|
|
if (method !== 'DELETE') {
|
|
this.registry
|
|
.metrics()
|
|
.then(metrics => {
|
|
if (
|
|
options.headers &&
|
|
options.headers['Content-Encoding'] === 'gzip'
|
|
) {
|
|
metrics = gzipSync(metrics);
|
|
}
|
|
req.write(metrics);
|
|
req.end();
|
|
})
|
|
.catch(err => {
|
|
reject(err);
|
|
});
|
|
} else {
|
|
req.end();
|
|
}
|
|
});
|
|
}
|
|
|
|
function generateGroupings(groupings) {
|
|
if (!groupings) {
|
|
return '';
|
|
}
|
|
return Object.keys(groupings)
|
|
.map(
|
|
key =>
|
|
`/${encodeURIComponent(key)}/${encodeURIComponent(groupings[key])}`,
|
|
)
|
|
.join('');
|
|
}
|
|
|
|
function isHttps(href) {
|
|
return href.search(/^https/) !== -1;
|
|
}
|
|
|
|
module.exports = Pushgateway;
|