1'use strict'; 2 3const { 4 NumberIsNaN, 5 NumberIsInteger, 6 NumberMAX_SAFE_INTEGER, 7 ObjectSetPrototypeOf, 8 SafeMap, 9 Symbol, 10 TypeError, 11} = primordials; 12 13const { 14 Histogram: _Histogram 15} = internalBinding('performance'); 16 17const { 18 customInspectSymbol: kInspect, 19} = require('internal/util'); 20 21const { inspect } = require('util'); 22 23const { 24 codes: { 25 ERR_INVALID_ARG_VALUE, 26 ERR_INVALID_ARG_TYPE, 27 ERR_OUT_OF_RANGE, 28 }, 29} = require('internal/errors'); 30 31const kDestroy = Symbol('kDestroy'); 32const kHandle = Symbol('kHandle'); 33const kMap = Symbol('kMap'); 34 35const { 36 kClone, 37 kDeserialize, 38 JSTransferable, 39} = require('internal/worker/js_transferable'); 40 41class Histogram extends JSTransferable { 42 constructor(internal) { 43 super(); 44 this[kHandle] = internal; 45 this[kMap] = new SafeMap(); 46 } 47 48 [kInspect](depth, options) { 49 if (depth < 0) 50 return this; 51 52 const opts = { 53 ...options, 54 depth: options.depth == null ? null : options.depth - 1 55 }; 56 57 return `Histogram ${inspect({ 58 min: this.min, 59 max: this.max, 60 mean: this.mean, 61 exceeds: this.exceeds, 62 stddev: this.stddev, 63 percentiles: this.percentiles, 64 }, opts)}`; 65 } 66 67 get min() { 68 return this[kHandle]?.min(); 69 } 70 71 get max() { 72 return this[kHandle]?.max(); 73 } 74 75 get mean() { 76 return this[kHandle]?.mean(); 77 } 78 79 get exceeds() { 80 return this[kHandle]?.exceeds(); 81 } 82 83 get stddev() { 84 return this[kHandle]?.stddev(); 85 } 86 87 percentile(percentile) { 88 if (typeof percentile !== 'number') 89 throw new ERR_INVALID_ARG_TYPE('percentile', 'number', percentile); 90 91 if (NumberIsNaN(percentile) || percentile <= 0 || percentile > 100) 92 throw new ERR_INVALID_ARG_VALUE.RangeError('percentile', percentile); 93 94 return this[kHandle]?.percentile(percentile); 95 } 96 97 get percentiles() { 98 this[kMap].clear(); 99 this[kHandle]?.percentiles(this[kMap]); 100 return this[kMap]; 101 } 102 103 reset() { 104 this[kHandle]?.reset(); 105 } 106 107 [kDestroy]() { 108 this[kHandle] = undefined; 109 } 110 111 [kClone]() { 112 const handle = this[kHandle]; 113 return { 114 data: { handle }, 115 deserializeInfo: 'internal/histogram:InternalHistogram' 116 }; 117 } 118 119 [kDeserialize]({ handle }) { 120 this[kHandle] = handle; 121 } 122} 123 124class RecordableHistogram extends Histogram { 125 constructor() { 126 // eslint-disable-next-line no-restricted-syntax 127 throw new TypeError('illegal constructor'); 128 } 129 130 record(val) { 131 if (typeof val === 'bigint') { 132 this[kHandle]?.record(val); 133 return; 134 } 135 136 if (!NumberIsInteger(val)) 137 throw new ERR_INVALID_ARG_TYPE('val', ['integer', 'bigint'], val); 138 139 if (val < 1 || val > NumberMAX_SAFE_INTEGER) 140 throw new ERR_OUT_OF_RANGE('val', 'a safe integer greater than 0', val); 141 142 this[kHandle]?.record(val); 143 } 144 145 recordDelta() { 146 this[kHandle]?.recordDelta(); 147 } 148 149 [kClone]() { 150 const handle = this[kHandle]; 151 return { 152 data: { handle }, 153 deserializeInfo: 'internal/histogram:InternalRecordableHistogram' 154 }; 155 } 156} 157 158class InternalHistogram extends JSTransferable { 159 constructor(handle) { 160 super(); 161 this[kHandle] = handle; 162 this[kMap] = new SafeMap(); 163 } 164} 165 166class InternalRecordableHistogram extends JSTransferable { 167 constructor(handle) { 168 super(); 169 this[kHandle] = handle; 170 this[kMap] = new SafeMap(); 171 } 172} 173 174InternalHistogram.prototype.constructor = Histogram; 175ObjectSetPrototypeOf( 176 InternalHistogram.prototype, 177 Histogram.prototype); 178 179InternalRecordableHistogram.prototype.constructor = RecordableHistogram; 180ObjectSetPrototypeOf( 181 InternalRecordableHistogram.prototype, 182 RecordableHistogram.prototype); 183 184function createHistogram() { 185 return new InternalRecordableHistogram(new _Histogram()); 186} 187 188module.exports = { 189 Histogram, 190 RecordableHistogram, 191 InternalHistogram, 192 InternalRecordableHistogram, 193 kDestroy, 194 kHandle, 195 createHistogram, 196}; 197