httpMetrics.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const shimmer = require("shimmer");
  4. const debug_1 = require("debug");
  5. const configuration_1 = require("../configuration");
  6. const serviceManager_1 = require("../serviceManager");
  7. const histogram_1 = require("../utils/metrics/histogram");
  8. const requireMiddle = require("require-in-the-middle");
  9. const metrics_1 = require("../services/metrics");
  10. class HttpMetricsConfig {
  11. }
  12. exports.HttpMetricsConfig = HttpMetricsConfig;
  13. class HttpMetrics {
  14. constructor() {
  15. this.defaultConf = {
  16. http: true
  17. };
  18. this.metrics = new Map();
  19. this.logger = debug_1.default('axm:features:metrics:http');
  20. this.modules = {};
  21. }
  22. init(config) {
  23. if (config === false)
  24. return;
  25. if (config === undefined) {
  26. config = this.defaultConf;
  27. }
  28. if (typeof config !== 'object') {
  29. config = this.defaultConf;
  30. }
  31. this.logger('init');
  32. configuration_1.default.configureModule({
  33. latency: true
  34. });
  35. this.metricService = serviceManager_1.ServiceManager.get('metrics');
  36. if (this.metricService === undefined)
  37. return this.logger(`Failed to load metric service`);
  38. this.logger('hooking to require');
  39. this.hookRequire();
  40. }
  41. registerHttpMetric() {
  42. if (this.metricService === undefined)
  43. return this.logger(`Failed to load metric service`);
  44. const histogram = new histogram_1.default();
  45. const p50 = {
  46. name: `HTTP Mean Latency`,
  47. id: 'internal/http/builtin/latency/p50',
  48. type: metrics_1.MetricType.histogram,
  49. historic: true,
  50. implementation: histogram,
  51. unit: 'ms',
  52. handler: () => {
  53. const percentiles = histogram.percentiles([0.5]);
  54. return percentiles[0.5];
  55. }
  56. };
  57. const p95 = {
  58. name: `HTTP P95 Latency`,
  59. id: 'internal/http/builtin/latency/p95',
  60. type: metrics_1.MetricType.histogram,
  61. historic: true,
  62. implementation: histogram,
  63. handler: () => {
  64. const percentiles = histogram.percentiles([0.95]);
  65. return percentiles[0.95];
  66. },
  67. unit: 'ms'
  68. };
  69. const meter = {
  70. name: 'HTTP',
  71. historic: true,
  72. id: 'internal/http/builtin/reqs',
  73. unit: 'req/min'
  74. };
  75. this.metricService.registerMetric(p50);
  76. this.metricService.registerMetric(p95);
  77. this.metrics.set('http.latency', histogram);
  78. this.metrics.set('http.meter', this.metricService.meter(meter));
  79. }
  80. registerHttpsMetric() {
  81. if (this.metricService === undefined)
  82. return this.logger(`Failed to load metric service`);
  83. const histogram = new histogram_1.default();
  84. const p50 = {
  85. name: `HTTPS Mean Latency`,
  86. id: 'internal/https/builtin/latency/p50',
  87. type: metrics_1.MetricType.histogram,
  88. historic: true,
  89. implementation: histogram,
  90. unit: 'ms',
  91. handler: () => {
  92. const percentiles = histogram.percentiles([0.5]);
  93. return percentiles[0.5];
  94. }
  95. };
  96. const p95 = {
  97. name: `HTTPS P95 Latency`,
  98. id: 'internal/https/builtin/latency/p95',
  99. type: metrics_1.MetricType.histogram,
  100. historic: true,
  101. implementation: histogram,
  102. handler: () => {
  103. const percentiles = histogram.percentiles([0.95]);
  104. return percentiles[0.95];
  105. },
  106. unit: 'ms'
  107. };
  108. const meter = {
  109. name: 'HTTPS',
  110. historic: true,
  111. id: 'internal/https/builtin/reqs',
  112. unit: 'req/min'
  113. };
  114. this.metricService.registerMetric(p50);
  115. this.metricService.registerMetric(p95);
  116. this.metrics.set('https.latency', histogram);
  117. this.metrics.set('https.meter', this.metricService.meter(meter));
  118. }
  119. destroy() {
  120. if (this.modules.http !== undefined) {
  121. this.logger('unwraping http module');
  122. shimmer.unwrap(this.modules.http, 'emit');
  123. this.modules.http = undefined;
  124. }
  125. if (this.modules.https !== undefined) {
  126. this.logger('unwraping https module');
  127. shimmer.unwrap(this.modules.https, 'emit');
  128. this.modules.https = undefined;
  129. }
  130. if (this.hooks) {
  131. this.hooks.unhook();
  132. }
  133. this.logger('destroy');
  134. }
  135. hookHttp(nodule, name) {
  136. if (nodule.Server === undefined || nodule.Server.prototype === undefined)
  137. return;
  138. if (this.modules[name] !== undefined)
  139. return this.logger(`Module ${name} already hooked`);
  140. this.logger(`Hooking to ${name} module`);
  141. this.modules[name] = nodule.Server.prototype;
  142. if (name === 'http') {
  143. this.registerHttpMetric();
  144. }
  145. else if (name === 'https') {
  146. this.registerHttpsMetric();
  147. }
  148. const self = this;
  149. shimmer.wrap(nodule.Server.prototype, 'emit', (original) => {
  150. return function (event, req, res) {
  151. if (event !== 'request')
  152. return original.apply(this, arguments);
  153. const meter = self.metrics.get(`${name}.meter`);
  154. if (meter !== undefined) {
  155. meter.mark();
  156. }
  157. const latency = self.metrics.get(`${name}.latency`);
  158. if (latency === undefined)
  159. return original.apply(this, arguments);
  160. if (res === undefined || res === null)
  161. return original.apply(this, arguments);
  162. const startTime = Date.now();
  163. res.once('finish', _ => {
  164. latency.update(Date.now() - startTime);
  165. });
  166. return original.apply(this, arguments);
  167. };
  168. });
  169. }
  170. hookRequire() {
  171. this.hooks = requireMiddle(['http', 'https'], (exports, name) => {
  172. this.hookHttp(exports, name);
  173. return exports;
  174. });
  175. }
  176. }
  177. exports.default = HttpMetrics;
  178. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cE1ldHJpY3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbWV0cmljcy9odHRwTWV0cmljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZLENBQUE7O0FBRVosbUNBQWtDO0FBQ2xDLGlDQUF5QjtBQUN6QixvREFBNEM7QUFFNUMsc0RBQWtEO0FBRWxELDBEQUFrRDtBQUNsRCx1REFBc0Q7QUFFdEQsaURBSzRCO0FBRTVCLE1BQWEsaUJBQWlCO0NBRTdCO0FBRkQsOENBRUM7QUFFRCxNQUFxQixXQUFXO0lBQWhDO1FBRVUsZ0JBQVcsR0FBc0I7WUFDdkMsSUFBSSxFQUFFLElBQUk7U0FDWCxDQUFBO1FBQ08sWUFBTyxHQUFxQixJQUFJLEdBQUcsRUFBZSxDQUFBO1FBQ2xELFdBQU0sR0FBUSxlQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQTtRQUVoRCxZQUFPLEdBQVEsRUFBRSxDQUFBO0lBaUszQixDQUFDO0lBOUpDLElBQUksQ0FBRSxNQUFvQztRQUN4QyxJQUFJLE1BQU0sS0FBSyxLQUFLO1lBQUUsT0FBTTtRQUM1QixJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUU7WUFDeEIsTUFBTSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUE7U0FDMUI7UUFDRCxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsRUFBRTtZQUM5QixNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQTtTQUMxQjtRQUNELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDbkIsdUJBQWEsQ0FBQyxlQUFlLENBQUM7WUFDNUIsT0FBTyxFQUFFLElBQUk7U0FDZCxDQUFDLENBQUE7UUFDRixJQUFJLENBQUMsYUFBYSxHQUFHLCtCQUFjLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBQ2xELElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTO1lBQUUsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLCtCQUErQixD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