1 #include "histogram.h"  // NOLINT(build/include_inline)
2 #include "base_object-inl.h"
3 #include "histogram-inl.h"
4 #include "memory_tracker-inl.h"
5 #include "node_errors.h"
6 #include "node_external_reference.h"
7 
8 namespace node {
9 
10 using v8::BigInt;
11 using v8::FunctionCallbackInfo;
12 using v8::FunctionTemplate;
13 using v8::Integer;
14 using v8::Isolate;
15 using v8::Local;
16 using v8::Map;
17 using v8::Number;
18 using v8::Object;
19 using v8::String;
20 using v8::Uint32;
21 using v8::Value;
22 
Histogram(const Options& options)23 Histogram::Histogram(const Options& options) {
24   hdr_histogram* histogram;
25   CHECK_EQ(0, hdr_init(options.lowest,
26                        options.highest,
27                        options.figures,
28                        &histogram));
29   histogram_.reset(histogram);
30 }
31 
MemoryInfo(MemoryTracker* tracker) const32 void Histogram::MemoryInfo(MemoryTracker* tracker) const {
33   tracker->TrackFieldWithSize("histogram", GetMemorySize());
34 }
35 
HistogramImpl(const Histogram::Options& options)36 HistogramImpl::HistogramImpl(const Histogram::Options& options)
37     : histogram_(new Histogram(options)) {}
38 
HistogramImpl(std::shared_ptr<Histogram> histogram)39 HistogramImpl::HistogramImpl(std::shared_ptr<Histogram> histogram)
40     : histogram_(std::move(histogram)) {}
41 
HistogramBase( Environment* env, Local<Object> wrap, const Histogram::Options& options)42 HistogramBase::HistogramBase(
43     Environment* env,
44     Local<Object> wrap,
45     const Histogram::Options& options)
46     : BaseObject(env, wrap),
47       HistogramImpl(options) {
48   MakeWeak();
49 }
50 
HistogramBase( Environment* env, Local<Object> wrap, std::shared_ptr<Histogram> histogram)51 HistogramBase::HistogramBase(
52     Environment* env,
53     Local<Object> wrap,
54     std::shared_ptr<Histogram> histogram)
55     : BaseObject(env, wrap),
56       HistogramImpl(std::move(histogram)) {
57   MakeWeak();
58 }
59 
MemoryInfo(MemoryTracker* tracker) const60 void HistogramBase::MemoryInfo(MemoryTracker* tracker) const {
61   tracker->TrackField("histogram", histogram());
62 }
63 
GetCount(const v8::FunctionCallbackInfo<v8::Value>& args)64 void HistogramBase::GetCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
65   HistogramBase* histogram;
66   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
67   double value = static_cast<double>((*histogram)->Count());
68   args.GetReturnValue().Set(value);
69 }
70 
GetCountBigInt( const v8::FunctionCallbackInfo<v8::Value>& args)71 void HistogramBase::GetCountBigInt(
72     const v8::FunctionCallbackInfo<v8::Value>& args) {
73   Environment* env = Environment::GetCurrent(args);
74   HistogramBase* histogram;
75   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
76   args.GetReturnValue().Set(
77       BigInt::NewFromUnsigned(env->isolate(), (*histogram)->Count()));
78 }
79 
GetMin(const FunctionCallbackInfo<Value>& args)80 void HistogramBase::GetMin(const FunctionCallbackInfo<Value>& args) {
81   HistogramBase* histogram;
82   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
83   double value = static_cast<double>((*histogram)->Min());
84   args.GetReturnValue().Set(value);
85 }
86 
GetMinBigInt(const FunctionCallbackInfo<Value>& args)87 void HistogramBase::GetMinBigInt(const FunctionCallbackInfo<Value>& args) {
88   Environment* env = Environment::GetCurrent(args);
89   HistogramBase* histogram;
90   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
91   args.GetReturnValue().Set(BigInt::New(env->isolate(), (*histogram)->Min()));
92 }
93 
GetMax(const FunctionCallbackInfo<Value>& args)94 void HistogramBase::GetMax(const FunctionCallbackInfo<Value>& args) {
95   HistogramBase* histogram;
96   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
97   double value = static_cast<double>((*histogram)->Max());
98   args.GetReturnValue().Set(value);
99 }
100 
GetMaxBigInt(const FunctionCallbackInfo<Value>& args)101 void HistogramBase::GetMaxBigInt(const FunctionCallbackInfo<Value>& args) {
102   Environment* env = Environment::GetCurrent(args);
103   HistogramBase* histogram;
104   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
105   args.GetReturnValue().Set(
106       BigInt::New(env->isolate(), (*histogram)->Max()));
107 }
108 
GetMean(const FunctionCallbackInfo<Value>& args)109 void HistogramBase::GetMean(const FunctionCallbackInfo<Value>& args) {
110   HistogramBase* histogram;
111   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
112   args.GetReturnValue().Set((*histogram)->Mean());
113 }
114 
GetExceeds(const FunctionCallbackInfo<Value>& args)115 void HistogramBase::GetExceeds(const FunctionCallbackInfo<Value>& args) {
116   HistogramBase* histogram;
117   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
118   double value = static_cast<double>((*histogram)->Exceeds());
119   args.GetReturnValue().Set(value);
120 }
121 
GetExceedsBigInt(const FunctionCallbackInfo<Value>& args)122 void HistogramBase::GetExceedsBigInt(const FunctionCallbackInfo<Value>& args) {
123   Environment* env = Environment::GetCurrent(args);
124   HistogramBase* histogram;
125   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
126   args.GetReturnValue().Set(
127       BigInt::NewFromUnsigned(env->isolate(), (*histogram)->Exceeds()));
128 }
129 
GetStddev(const FunctionCallbackInfo<Value>& args)130 void HistogramBase::GetStddev(const FunctionCallbackInfo<Value>& args) {
131   HistogramBase* histogram;
132   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
133   args.GetReturnValue().Set((*histogram)->Stddev());
134 }
135 
GetPercentile(const FunctionCallbackInfo<Value>& args)136 void HistogramBase::GetPercentile(const FunctionCallbackInfo<Value>& args) {
137   HistogramBase* histogram;
138   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
139   CHECK(args[0]->IsNumber());
140   double percentile = args[0].As<Number>()->Value();
141   double value = static_cast<double>((*histogram)->Percentile(percentile));
142   args.GetReturnValue().Set(value);
143 }
144 
GetPercentileBigInt( const FunctionCallbackInfo<Value>& args)145 void HistogramBase::GetPercentileBigInt(
146     const FunctionCallbackInfo<Value>& args) {
147   Environment* env = Environment::GetCurrent(args);
148   HistogramBase* histogram;
149   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
150   CHECK(args[0]->IsNumber());
151   double percentile = args[0].As<Number>()->Value();
152   int64_t value = (*histogram)->Percentile(percentile);
153   args.GetReturnValue().Set(BigInt::New(env->isolate(), value));
154 }
155 
GetPercentiles(const FunctionCallbackInfo<Value>& args)156 void HistogramBase::GetPercentiles(const FunctionCallbackInfo<Value>& args) {
157   Environment* env = Environment::GetCurrent(args);
158   HistogramBase* histogram;
159   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
160   CHECK(args[0]->IsMap());
161   Local<Map> map = args[0].As<Map>();
162   (*histogram)->Percentiles([map, env](double key, int64_t value) {
163     USE(map->Set(
164           env->context(),
165           Number::New(env->isolate(), key),
166           Number::New(env->isolate(), static_cast<double>(value))));
167   });
168 }
169 
GetPercentilesBigInt( const FunctionCallbackInfo<Value>& args)170 void HistogramBase::GetPercentilesBigInt(
171     const FunctionCallbackInfo<Value>& args) {
172   Environment* env = Environment::GetCurrent(args);
173   HistogramBase* histogram;
174   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
175   CHECK(args[0]->IsMap());
176   Local<Map> map = args[0].As<Map>();
177   (*histogram)->Percentiles([map, env](double key, int64_t value) {
178     USE(map->Set(
179           env->context(),
180           Number::New(env->isolate(), key),
181           BigInt::New(env->isolate(), value)));
182   });
183 }
184 
DoReset(const FunctionCallbackInfo<Value>& args)185 void HistogramBase::DoReset(const FunctionCallbackInfo<Value>& args) {
186   HistogramBase* histogram;
187   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
188   (*histogram)->Reset();
189 }
190 
RecordDelta(const FunctionCallbackInfo<Value>& args)191 void HistogramBase::RecordDelta(const FunctionCallbackInfo<Value>& args) {
192   HistogramBase* histogram;
193   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
194   (*histogram)->RecordDelta();
195 }
196 
Record(const FunctionCallbackInfo<Value>& args)197 void HistogramBase::Record(const FunctionCallbackInfo<Value>& args) {
198   Environment* env = Environment::GetCurrent(args);
199   CHECK_IMPLIES(!args[0]->IsNumber(), args[0]->IsBigInt());
200   bool lossless = true;
201   int64_t value = args[0]->IsBigInt()
202       ? args[0].As<BigInt>()->Int64Value(&lossless)
203       : static_cast<int64_t>(args[0].As<Number>()->Value());
204   if (!lossless || value < 1)
205     return THROW_ERR_OUT_OF_RANGE(env, "value is out of range");
206   HistogramBase* histogram;
207   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
208   (*histogram)->Record(value);
209 }
210 
Add(const FunctionCallbackInfo<Value>& args)211 void HistogramBase::Add(const FunctionCallbackInfo<Value>& args) {
212   Environment* env = Environment::GetCurrent(args);
213   HistogramBase* histogram;
214   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
215 
216   CHECK(GetConstructorTemplate(env)->HasInstance(args[0]));
217   HistogramBase* other;
218   ASSIGN_OR_RETURN_UNWRAP(&other, args[0]);
219 
220   double count = (*histogram)->Add(*(other->histogram()));
221   args.GetReturnValue().Set(count);
222 }
223 
Create( Environment* env, const Histogram::Options& options)224 BaseObjectPtr<HistogramBase> HistogramBase::Create(
225     Environment* env,
226     const Histogram::Options& options) {
227   Local<Object> obj;
228   if (!GetConstructorTemplate(env)
229           ->InstanceTemplate()
230           ->NewInstance(env->context()).ToLocal(&obj)) {
231     return BaseObjectPtr<HistogramBase>();
232   }
233 
234   return MakeBaseObject<HistogramBase>(env, obj, options);
235 }
236 
Create( Environment* env, std::shared_ptr<Histogram> histogram)237 BaseObjectPtr<HistogramBase> HistogramBase::Create(
238     Environment* env,
239     std::shared_ptr<Histogram> histogram) {
240   Local<Object> obj;
241   if (!GetConstructorTemplate(env)
242           ->InstanceTemplate()
243           ->NewInstance(env->context()).ToLocal(&obj)) {
244     return BaseObjectPtr<HistogramBase>();
245   }
246   return MakeBaseObject<HistogramBase>(env, obj, std::move(histogram));
247 }
248 
New(const FunctionCallbackInfo<Value>& args)249 void HistogramBase::New(const FunctionCallbackInfo<Value>& args) {
250   CHECK(args.IsConstructCall());
251   Environment* env = Environment::GetCurrent(args);
252 
253   CHECK_IMPLIES(!args[0]->IsNumber(), args[0]->IsBigInt());
254   CHECK_IMPLIES(!args[1]->IsNumber(), args[1]->IsBigInt());
255   CHECK(args[2]->IsUint32());
256 
257   int64_t lowest = 1;
258   int64_t highest = std::numeric_limits<int64_t>::max();
259 
260   bool lossless_ignored;
261 
262   if (args[0]->IsNumber()) {
263     lowest = args[0].As<Integer>()->Value();
264   } else if (args[0]->IsBigInt()) {
265     lowest = args[0].As<BigInt>()->Int64Value(&lossless_ignored);
266   }
267 
268   if (args[1]->IsNumber()) {
269     highest = args[1].As<Integer>()->Value();
270   } else if (args[1]->IsBigInt()) {
271     highest = args[1].As<BigInt>()->Int64Value(&lossless_ignored);
272   }
273 
274   int32_t figures = args[2].As<Uint32>()->Value();
275   new HistogramBase(env, args.This(), Histogram::Options {
276     lowest, highest, figures
277   });
278 }
279 
GetConstructorTemplate( Environment* env)280 Local<FunctionTemplate> HistogramBase::GetConstructorTemplate(
281     Environment* env) {
282   Local<FunctionTemplate> tmpl = env->histogram_ctor_template();
283   if (tmpl.IsEmpty()) {
284     Isolate* isolate = env->isolate();
285     tmpl = NewFunctionTemplate(isolate, New);
286     Local<String> classname =
287         FIXED_ONE_BYTE_STRING(env->isolate(), "Histogram");
288     tmpl->SetClassName(classname);
289     tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
290 
291     tmpl->InstanceTemplate()->SetInternalFieldCount(
292         HistogramBase::kInternalFieldCount);
293     SetProtoMethodNoSideEffect(isolate, tmpl, "count", GetCount);
294     SetProtoMethodNoSideEffect(isolate, tmpl, "countBigInt", GetCountBigInt);
295     SetProtoMethodNoSideEffect(isolate, tmpl, "exceeds", GetExceeds);
296     SetProtoMethodNoSideEffect(
297         isolate, tmpl, "exceedsBigInt", GetExceedsBigInt);
298     SetProtoMethodNoSideEffect(isolate, tmpl, "min", GetMin);
299     SetProtoMethodNoSideEffect(isolate, tmpl, "minBigInt", GetMinBigInt);
300     SetProtoMethodNoSideEffect(isolate, tmpl, "max", GetMax);
301     SetProtoMethodNoSideEffect(isolate, tmpl, "maxBigInt", GetMaxBigInt);
302     SetProtoMethodNoSideEffect(isolate, tmpl, "mean", GetMean);
303     SetProtoMethodNoSideEffect(isolate, tmpl, "stddev", GetStddev);
304     SetProtoMethodNoSideEffect(isolate, tmpl, "percentile", GetPercentile);
305     SetProtoMethodNoSideEffect(
306         isolate, tmpl, "percentileBigInt", GetPercentileBigInt);
307     SetProtoMethodNoSideEffect(isolate, tmpl, "percentiles", GetPercentiles);
308     SetProtoMethodNoSideEffect(
309         isolate, tmpl, "percentilesBigInt", GetPercentilesBigInt);
310     SetProtoMethod(isolate, tmpl, "reset", DoReset);
311     SetProtoMethod(isolate, tmpl, "record", Record);
312     SetProtoMethod(isolate, tmpl, "recordDelta", RecordDelta);
313     SetProtoMethod(isolate, tmpl, "add", Add);
314     env->set_histogram_ctor_template(tmpl);
315   }
316   return tmpl;
317 }
318 
RegisterExternalReferences( ExternalReferenceRegistry* registry)319 void HistogramBase::RegisterExternalReferences(
320     ExternalReferenceRegistry* registry) {
321   registry->Register(New);
322   registry->Register(GetCount);
323   registry->Register(GetCountBigInt);
324   registry->Register(GetExceeds);
325   registry->Register(GetExceedsBigInt);
326   registry->Register(GetMin);
327   registry->Register(GetMinBigInt);
328   registry->Register(GetMax);
329   registry->Register(GetMaxBigInt);
330   registry->Register(GetMean);
331   registry->Register(GetStddev);
332   registry->Register(GetPercentile);
333   registry->Register(GetPercentileBigInt);
334   registry->Register(GetPercentiles);
335   registry->Register(GetPercentilesBigInt);
336   registry->Register(DoReset);
337   registry->Register(Record);
338   registry->Register(RecordDelta);
339   registry->Register(Add);
340 }
341 
Initialize(Environment* env, Local<Object> target)342 void HistogramBase::Initialize(Environment* env, Local<Object> target) {
343   SetConstructorFunction(env->context(),
344                          target,
345                          "Histogram",
346                          GetConstructorTemplate(env),
347                          SetConstructorFunctionFlag::NONE);
348 }
349 
Deserialize( Environment* env, v8::Local<v8::Context> context, std::unique_ptr<worker::TransferData> self)350 BaseObjectPtr<BaseObject> HistogramBase::HistogramTransferData::Deserialize(
351     Environment* env,
352     v8::Local<v8::Context> context,
353     std::unique_ptr<worker::TransferData> self) {
354   return Create(env, std::move(histogram_));
355 }
356 
CloneForMessaging() const357 std::unique_ptr<worker::TransferData> HistogramBase::CloneForMessaging() const {
358   return std::make_unique<HistogramTransferData>(this);
359 }
360 
MemoryInfo( MemoryTracker* tracker) const361 void HistogramBase::HistogramTransferData::MemoryInfo(
362     MemoryTracker* tracker) const {
363   tracker->TrackField("histogram", histogram_);
364 }
365 
GetConstructorTemplate( Environment* env)366 Local<FunctionTemplate> IntervalHistogram::GetConstructorTemplate(
367     Environment* env) {
368   Local<FunctionTemplate> tmpl = env->intervalhistogram_constructor_template();
369   if (tmpl.IsEmpty()) {
370     Isolate* isolate = env->isolate();
371     tmpl = NewFunctionTemplate(isolate, nullptr);
372     tmpl->Inherit(HandleWrap::GetConstructorTemplate(env));
373     tmpl->SetClassName(OneByteString(isolate, "Histogram"));
374     tmpl->InstanceTemplate()->SetInternalFieldCount(
375         HistogramBase::kInternalFieldCount);
376     SetProtoMethodNoSideEffect(isolate, tmpl, "count", GetCount);
377     SetProtoMethodNoSideEffect(isolate, tmpl, "countBigInt", GetCountBigInt);
378     SetProtoMethodNoSideEffect(isolate, tmpl, "exceeds", GetExceeds);
379     SetProtoMethodNoSideEffect(
380         isolate, tmpl, "exceedsBigInt", GetExceedsBigInt);
381     SetProtoMethodNoSideEffect(isolate, tmpl, "min", GetMin);
382     SetProtoMethodNoSideEffect(isolate, tmpl, "minBigInt", GetMinBigInt);
383     SetProtoMethodNoSideEffect(isolate, tmpl, "max", GetMax);
384     SetProtoMethodNoSideEffect(isolate, tmpl, "maxBigInt", GetMaxBigInt);
385     SetProtoMethodNoSideEffect(isolate, tmpl, "mean", GetMean);
386     SetProtoMethodNoSideEffect(isolate, tmpl, "stddev", GetStddev);
387     SetProtoMethodNoSideEffect(isolate, tmpl, "percentile", GetPercentile);
388     SetProtoMethodNoSideEffect(
389         isolate, tmpl, "percentileBigInt", GetPercentileBigInt);
390     SetProtoMethodNoSideEffect(isolate, tmpl, "percentiles", GetPercentiles);
391     SetProtoMethodNoSideEffect(
392         isolate, tmpl, "percentilesBigInt", GetPercentilesBigInt);
393     SetProtoMethod(isolate, tmpl, "reset", DoReset);
394     SetProtoMethod(isolate, tmpl, "start", Start);
395     SetProtoMethod(isolate, tmpl, "stop", Stop);
396     env->set_intervalhistogram_constructor_template(tmpl);
397   }
398   return tmpl;
399 }
400 
RegisterExternalReferences( ExternalReferenceRegistry* registry)401 void IntervalHistogram::RegisterExternalReferences(
402     ExternalReferenceRegistry* registry) {
403   registry->Register(GetCount);
404   registry->Register(GetCountBigInt);
405   registry->Register(GetExceeds);
406   registry->Register(GetExceedsBigInt);
407   registry->Register(GetMin);
408   registry->Register(GetMinBigInt);
409   registry->Register(GetMax);
410   registry->Register(GetMaxBigInt);
411   registry->Register(GetMean);
412   registry->Register(GetStddev);
413   registry->Register(GetPercentile);
414   registry->Register(GetPercentileBigInt);
415   registry->Register(GetPercentiles);
416   registry->Register(GetPercentilesBigInt);
417   registry->Register(DoReset);
418   registry->Register(Start);
419   registry->Register(Stop);
420 }
421 
IntervalHistogram( Environment* env, Local<Object> wrap, AsyncWrap::ProviderType type, int32_t interval, std::function<void(Histogram&)> on_interval, const Histogram::Options& options)422 IntervalHistogram::IntervalHistogram(
423     Environment* env,
424     Local<Object> wrap,
425     AsyncWrap::ProviderType type,
426     int32_t interval,
427     std::function<void(Histogram&)> on_interval,
428     const Histogram::Options& options)
429     : HandleWrap(
430           env,
431           wrap,
432           reinterpret_cast<uv_handle_t*>(&timer_),
433           type),
434       HistogramImpl(options),
435       interval_(interval),
436       on_interval_(std::move(on_interval)) {
437   MakeWeak();
438   uv_timer_init(env->event_loop(), &timer_);
439 }
440 
Create( Environment* env, int32_t interval, std::function<void(Histogram&)> on_interval, const Histogram::Options& options)441 BaseObjectPtr<IntervalHistogram> IntervalHistogram::Create(
442     Environment* env,
443     int32_t interval,
444     std::function<void(Histogram&)> on_interval,
445     const Histogram::Options& options) {
446   Local<Object> obj;
447   if (!GetConstructorTemplate(env)
448           ->InstanceTemplate()
449           ->NewInstance(env->context()).ToLocal(&obj)) {
450     return BaseObjectPtr<IntervalHistogram>();
451   }
452 
453   return MakeBaseObject<IntervalHistogram>(
454       env,
455       obj,
456       AsyncWrap::PROVIDER_ELDHISTOGRAM,
457       interval,
458       std::move(on_interval),
459       options);
460 }
461 
TimerCB(uv_timer_t* handle)462 void IntervalHistogram::TimerCB(uv_timer_t* handle) {
463   IntervalHistogram* histogram =
464       ContainerOf(&IntervalHistogram::timer_, handle);
465 
466   Histogram* h = histogram->histogram().get();
467 
468   histogram->on_interval_(*h);
469 }
470 
MemoryInfo(MemoryTracker* tracker) const471 void IntervalHistogram::MemoryInfo(MemoryTracker* tracker) const {
472   tracker->TrackField("histogram", histogram());
473 }
474 
OnStart(StartFlags flags)475 void IntervalHistogram::OnStart(StartFlags flags) {
476   if (enabled_ || IsHandleClosing()) return;
477   enabled_ = true;
478   if (flags == StartFlags::RESET)
479     histogram()->Reset();
480   uv_timer_start(&timer_, TimerCB, interval_, interval_);
481   uv_unref(reinterpret_cast<uv_handle_t*>(&timer_));
482 }
483 
OnStop()484 void IntervalHistogram::OnStop() {
485   if (!enabled_ || IsHandleClosing()) return;
486   enabled_ = false;
487   uv_timer_stop(&timer_);
488 }
489 
Start(const FunctionCallbackInfo<Value>& args)490 void IntervalHistogram::Start(const FunctionCallbackInfo<Value>& args) {
491   IntervalHistogram* histogram;
492   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
493   histogram->OnStart(args[0]->IsTrue() ? StartFlags::RESET : StartFlags::NONE);
494 }
495 
Stop(const FunctionCallbackInfo<Value>& args)496 void IntervalHistogram::Stop(const FunctionCallbackInfo<Value>& args) {
497   IntervalHistogram* histogram;
498   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
499   histogram->OnStop();
500 }
501 
GetCount(const FunctionCallbackInfo<Value>& args)502 void IntervalHistogram::GetCount(const FunctionCallbackInfo<Value>& args) {
503   IntervalHistogram* histogram;
504   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
505   double value = static_cast<double>((*histogram)->Count());
506   args.GetReturnValue().Set(value);
507 }
508 
GetCountBigInt( const v8::FunctionCallbackInfo<v8::Value>& args)509 void IntervalHistogram::GetCountBigInt(
510     const v8::FunctionCallbackInfo<v8::Value>& args) {
511   Environment* env = Environment::GetCurrent(args);
512   IntervalHistogram* histogram;
513   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
514   args.GetReturnValue().Set(
515       BigInt::NewFromUnsigned(env->isolate(), (*histogram)->Count()));
516 }
517 
GetMin(const FunctionCallbackInfo<Value>& args)518 void IntervalHistogram::GetMin(const FunctionCallbackInfo<Value>& args) {
519   IntervalHistogram* histogram;
520   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
521   double value = static_cast<double>((*histogram)->Min());
522   args.GetReturnValue().Set(value);
523 }
524 
GetMinBigInt(const FunctionCallbackInfo<Value>& args)525 void IntervalHistogram::GetMinBigInt(const FunctionCallbackInfo<Value>& args) {
526   Environment* env = Environment::GetCurrent(args);
527   IntervalHistogram* histogram;
528   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
529   args.GetReturnValue().Set(BigInt::New(env->isolate(), (*histogram)->Min()));
530 }
531 
GetMax(const FunctionCallbackInfo<Value>& args)532 void IntervalHistogram::GetMax(const FunctionCallbackInfo<Value>& args) {
533   IntervalHistogram* histogram;
534   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
535   double value = static_cast<double>((*histogram)->Max());
536   args.GetReturnValue().Set(value);
537 }
538 
GetMaxBigInt(const FunctionCallbackInfo<Value>& args)539 void IntervalHistogram::GetMaxBigInt(const FunctionCallbackInfo<Value>& args) {
540   Environment* env = Environment::GetCurrent(args);
541   IntervalHistogram* histogram;
542   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
543   args.GetReturnValue().Set(BigInt::New(env->isolate(), (*histogram)->Min()));
544 }
545 
GetMean(const FunctionCallbackInfo<Value>& args)546 void IntervalHistogram::GetMean(const FunctionCallbackInfo<Value>& args) {
547   IntervalHistogram* histogram;
548   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
549   args.GetReturnValue().Set((*histogram)->Mean());
550 }
551 
GetExceeds(const FunctionCallbackInfo<Value>& args)552 void IntervalHistogram::GetExceeds(const FunctionCallbackInfo<Value>& args) {
553   IntervalHistogram* histogram;
554   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
555   double value = static_cast<double>((*histogram)->Exceeds());
556   args.GetReturnValue().Set(value);
557 }
558 
GetExceedsBigInt( const FunctionCallbackInfo<Value>& args)559 void IntervalHistogram::GetExceedsBigInt(
560     const FunctionCallbackInfo<Value>& args) {
561   Environment* env = Environment::GetCurrent(args);
562   IntervalHistogram* histogram;
563   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
564   args.GetReturnValue().Set(
565       BigInt::New(env->isolate(), (*histogram)->Exceeds()));
566 }
567 
GetStddev(const FunctionCallbackInfo<Value>& args)568 void IntervalHistogram::GetStddev(const FunctionCallbackInfo<Value>& args) {
569   IntervalHistogram* histogram;
570   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
571   args.GetReturnValue().Set((*histogram)->Stddev());
572 }
573 
GetPercentile(const FunctionCallbackInfo<Value>& args)574 void IntervalHistogram::GetPercentile(const FunctionCallbackInfo<Value>& args) {
575   IntervalHistogram* histogram;
576   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
577   CHECK(args[0]->IsNumber());
578   double percentile = args[0].As<Number>()->Value();
579   double value = static_cast<double>((*histogram)->Percentile(percentile));
580   args.GetReturnValue().Set(value);
581 }
582 
GetPercentileBigInt( const FunctionCallbackInfo<Value>& args)583 void IntervalHistogram::GetPercentileBigInt(
584     const FunctionCallbackInfo<Value>& args) {
585   Environment* env = Environment::GetCurrent(args);
586   IntervalHistogram* histogram;
587   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
588   CHECK(args[0]->IsNumber());
589   double percentile = args[0].As<Number>()->Value();
590   int64_t value = (*histogram)->Percentile(percentile);
591   args.GetReturnValue().Set(BigInt::New(env->isolate(), value));
592 }
593 
GetPercentiles( const FunctionCallbackInfo<Value>& args)594 void IntervalHistogram::GetPercentiles(
595     const FunctionCallbackInfo<Value>& args) {
596   Environment* env = Environment::GetCurrent(args);
597   IntervalHistogram* histogram;
598   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
599   CHECK(args[0]->IsMap());
600   Local<Map> map = args[0].As<Map>();
601   (*histogram)->Percentiles([map, env](double key, int64_t value) {
602     USE(map->Set(
603           env->context(),
604           Number::New(env->isolate(), key),
605           Number::New(env->isolate(), static_cast<double>(value))));
606   });
607 }
608 
GetPercentilesBigInt( const FunctionCallbackInfo<Value>& args)609 void IntervalHistogram::GetPercentilesBigInt(
610     const FunctionCallbackInfo<Value>& args) {
611   Environment* env = Environment::GetCurrent(args);
612   IntervalHistogram* histogram;
613   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
614   CHECK(args[0]->IsMap());
615   Local<Map> map = args[0].As<Map>();
616   (*histogram)->Percentiles([map, env](double key, int64_t value) {
617     USE(map->Set(
618           env->context(),
619           Number::New(env->isolate(), key),
620           BigInt::New(env->isolate(), value)));
621   });
622 }
623 
DoReset(const FunctionCallbackInfo<Value>& args)624 void IntervalHistogram::DoReset(const FunctionCallbackInfo<Value>& args) {
625   IntervalHistogram* histogram;
626   ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
627   (*histogram)->Reset();
628 }
629 
630 std::unique_ptr<worker::TransferData>
CloneForMessaging() const631 IntervalHistogram::CloneForMessaging() const {
632   return std::make_unique<HistogramBase::HistogramTransferData>(histogram());
633 }
634 
635 }  // namespace node
636