UNPKG

@biorate/axios-prometheus

Version:

Axios-prometheus HTTP interface

195 lines 8.77 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AxiosPrometheus = void 0; const fs_1 = require("fs"); const tools_1 = require("@biorate/tools"); const inversion_1 = require("@biorate/inversion"); const axios_1 = require("@biorate/axios"); const prometheus_1 = require("@biorate/prometheus"); const opentelemetry_1 = require("@biorate/opentelemetry"); const lodash_1 = require("lodash"); __exportStar(require("@biorate/axios"), exports); class AxiosPrometheus extends axios_1.Axios { static mockFileName(name) { return `Axios.${name}.snap`; } static checkMockDir(directory) { try { const dir = tools_1.path.create(process.cwd(), directory); const stats = (0, fs_1.statSync)(dir); if (!stats.isDirectory()) return null; return dir; } catch (_a) { return null; } } static mockFilePath(filename) { let directory = inversion_1.container.get(inversion_1.Types.Config).get('axios.mock.directory', null); if (!directory) directory = this.checkMockDir('test'); if (!directory) directory = this.checkMockDir('tests'); if (!directory) directory = process.cwd(); return tools_1.path.create(directory, '__snapshots__', filename !== null && filename !== void 0 ? filename : ''); } static getMockData(instance, filename) { return JSON.parse((0, fs_1.readFileSync)(this.mockFilePath(filename), 'utf8')); } static getMock(instance, options) { const filename = this.mockFileName(instance.constructor.name); try { return (0, lodash_1.get)(this.getMockData(instance, filename), `${instance.constructor.name}.${JSON.stringify(options)}`); } catch (e) { console.warn(`Axios mock snap file [${filename}] doesn't exists, or corrupted., because of [${e === null || e === void 0 ? void 0 : e.message}]`); } } static setMock(instance, result, options) { let data; const filename = this.mockFileName(instance.constructor.name); try { data = this.getMockData(instance, filename); } catch (_a) { data = {}; } (0, lodash_1.set)(data, `${instance.constructor.name}.${JSON.stringify(options)}`, (0, lodash_1.pick)(result, ...this.mockFields)); try { (0, fs_1.mkdirSync)(this.mockFilePath(), { recursive: true }); } catch (_b) { } try { (0, fs_1.writeFileSync)(this.mockFilePath(filename), JSON.stringify(data, null, ' '), 'utf8'); } catch (e) { console.warn(`Can't write Axios mock snap file [${filename}], because of [${e === null || e === void 0 ? void 0 : e.message}]`); } } get config() { return inversion_1.container.get(inversion_1.Types.Config); } getStartTime() { return process.hrtime(); } log(statusCode, startTime) { const diff = process.hrtime(startTime); const time = diff[0] * 1e3 + diff[1] * 1e-6; const msTo = tools_1.time.msTo; this.counter .labels({ method: this.method, uri: this.baseURL + this.url, status: statusCode, }) .inc(); this.histogram .labels({ method: this.method, uri: this.baseURL + this.url, status: statusCode, }) .observe(msTo(time, 's')); } stringify(data) { return typeof data === 'object' ? JSON.stringify(data) : String(data); } needTrace(url, span) { if (!span) return false; const excluded = this.config.get('AxiosPrometheus.tracing.excluded', []); for (const item of excluded) { if (typeof item === 'string' && url.startsWith(item)) return false; if (item instanceof RegExp && item.test(url)) return false; } return true; } fullUrl(params) { var _a, _b; return (_b = (_a = params === null || params === void 0 ? void 0 : params.baseURL) !== null && _a !== void 0 ? _a : '' + (params === null || params === void 0 ? void 0 : params.url)) !== null && _b !== void 0 ? _b : ''; } async before(params) { await super.before(params); const span = opentelemetry_1.trace.getActiveSpan(); const url = this.fullUrl(params); if (!this.needTrace(url, span)) return; span.setAttribute('outgoing.request.url', this.stringify(url)); span.setAttribute('outgoing.request.body', this.stringify(params === null || params === void 0 ? void 0 : params.data)); span.setAttribute('outgoing.request.headers', this.stringify(params === null || params === void 0 ? void 0 : params.headers)); span.setAttribute('outgoing.request.method', this.stringify(params === null || params === void 0 ? void 0 : params.method)); span.setAttribute('outgoing.request.params', this.stringify(params === null || params === void 0 ? void 0 : params.path)); span.setAttribute('outgoing.request.query', this.stringify(params === null || params === void 0 ? void 0 : params.params)); } async after(result, startTime, params) { await super.after(result, startTime, params); this.log(result.status, startTime); const span = opentelemetry_1.trace.getActiveSpan(); const url = this.fullUrl(params); if (!this.needTrace(url, span)) return; span.setAttribute('outgoing.response.headers', this.stringify(result.headers)); span.setAttribute('outgoing.response.statusCode', this.stringify(result.status)); span.setAttribute('outgoing.response.data', this.stringify(result.data)); } async catch(e, startTime, params) { await super.catch(e, startTime, params); if (!('response' in e)) return; this.log(e.response.status, startTime); const span = opentelemetry_1.trace.getActiveSpan(); const url = this.fullUrl(params); if (!this.needTrace(url, span)) return; span.setAttribute('outgoing.response.headers', this.stringify(e.response.headers)); span.setAttribute('outgoing.response.statusCode', this.stringify(e.response.status)); span.setAttribute('outgoing.response.data', this.stringify(e.response.data)); } } AxiosPrometheus.mockFields = ['data', 'status', 'statusText']; __decorate([ (0, prometheus_1.counter)({ name: 'http_client_requests_seconds_count', help: 'Http client requests count', labelNames: ['method', 'uri', 'status'], }), __metadata("design:type", Object) ], AxiosPrometheus.prototype, "counter", void 0); __decorate([ (0, prometheus_1.histogram)({ name: 'http_client_requests_seconds', help: 'Http client requests seconds bucket', labelNames: ['method', 'uri', 'status'], buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 0.3, 0.5, 1, 2, 3, 5, 10], }), __metadata("design:type", Object) ], AxiosPrometheus.prototype, "histogram", void 0); exports.AxiosPrometheus = AxiosPrometheus; //# sourceMappingURL=index.js.map