skywalking-backend-js-netease
Version:
The NodeJS agent for Apache SkyWalking
141 lines • 5.98 kB
JavaScript
;
/*!
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const AgentConfig_1 = tslib_1.__importDefault(require("../config/AgentConfig"));
const http_grpc_pb_1 = require("../proto/tunnel/http_grpc_pb");
const AuthInterceptor_1 = tslib_1.__importDefault(require("../agent/protocol/grpc/AuthInterceptor"));
const http_pb_1 = require("../proto/tunnel/http_pb");
const logging_1 = require("../logging");
const grpc_js_1 = require("@grpc/grpc-js");
const prom_client_1 = tslib_1.__importDefault(require("prom-client"));
const os_1 = tslib_1.__importDefault(require("os"));
const logger = logging_1.createLogger(__filename);
/**
* use grpc tunnel to send http request
*/
class GrpcPushgateway extends prom_client_1.default.Pushgateway {
constructor(url, options, registry) {
super(`http://${url}`, {}, registry);
this.registry = registry || new prom_client_1.default.Registry();
this.options = options;
this.httpReportServiceClient = new http_grpc_pb_1.HttpReportServiceClient(url, AgentConfig_1.default.secure ? grpc_js_1.credentials.createSsl() : grpc_js_1.credentials.createInsecure());
this.lastCpu = this.cpu();
const _that = this;
this.cpuPercGuage = new prom_client_1.default.Gauge({
name: 'process_cpu_percentage',
help: 'current process cpu usage percentage.',
registers: [this.registry],
labelNames: [],
collect: function () {
const current = _that.cpu();
const [all, cur] = [current.total - _that.lastCpu.total, current.current - _that.lastCpu.current];
if (all > 0) {
_that.cpuPercGuage.set(cur / all * 100);
}
else {
_that.cpuPercGuage.set(0);
}
_that.lastCpu = current;
},
});
}
cpu() {
const cpus = os_1.default.cpus();
// Accumulate every CPU times values, miliseconds
const total = cpus.map(x => x.times)
.reduce((acc, tv) => acc + tv.idle + tv.irq + tv.nice + tv.sys + tv.user, 0);
// Normalize the one returned by process.cpuUsage() microseconds
// (microseconds VS miliseconds)
const usage = process.cpuUsage();
const current = usage.user + usage.system;
return { total, current: current / 1e3 };
}
push(params) {
if (!params || !params.jobName) {
throw new Error('Missing jobName parameter');
}
return this.useGateway('PUT', params.jobName, params.groupings);
}
useGateway(method, job, groupings) {
const path = `http://127.0.0.1:11800/metrics/job/${encodeURIComponent(job)}${this.generateGroupings(groupings)}`;
return new Promise((resolve, reject) => {
const stream = this.httpReportServiceClient.invoke(AuthInterceptor_1.default(), this.options(), (err, resp) => {
if (err) {
reject(err);
return;
}
resolve({ code: resp.getCode(), body: resp.getBody() });
});
if (method !== 'DELETE') {
this.registry.metrics()
.then(metrics => {
stream.write(new http_pb_1.HttpReqObject().setMethod(method).setUrl(path).setBody(new TextEncoder().encode(metrics)));
stream.end();
})
.catch(err => {
reject(err);
});
}
else {
resolve(null);
}
});
}
generateGroupings(groupings) {
if (!groupings) {
return '';
}
return Object.keys(groupings)
.map(key => `/${encodeURIComponent(key)}/${encodeURIComponent(groupings[key])}`)
.join('');
}
}
class PrometheusPlugin {
constructor() {
this.module = 'prom-client'; // nodejs prom client
this.versions = '*';
}
install() {
const register = new prom_client_1.default.Registry();
prom_client_1.default.collectDefaultMetrics({
register,
gcDurationBuckets: [0.001, 0.01, 0.1, 1, 2, 5],
});
const gateway = new GrpcPushgateway(AgentConfig_1.default.collectorAddress, () => { return { deadline: Date.now() + 30000 }; }, // Set the request timeout to 30000ms
register);
setInterval(() => {
gateway.push({
jobName: 'nodejs_metrics',
groupings: {
product: AgentConfig_1.default.authorization,
instance: AgentConfig_1.default.serviceInstance,
service: AgentConfig_1.default.serviceName,
},
}).then(() => {
logger.debug(`Success sended Node.js VM Metrics`);
}).catch(err => {
logger.error('Failed to send Node.js VM Metrics', err);
});
}, 60000);
}
}
exports.default = new PrometheusPlugin();
//# sourceMappingURL=PrometheusPlugin.js.map