#ifndef SRC_HISTOGRAM_H_ #define SRC_HISTOGRAM_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include #include "base_object.h" #include "memory_tracker.h" #include "node_messaging.h" #include "util.h" #include "uv.h" #include "v8.h" #include #include #include #include namespace node { class ExternalReferenceRegistry; constexpr int kDefaultHistogramFigures = 3; class Histogram : public MemoryRetainer { public: struct Options { int64_t lowest = 1; int64_t highest = std::numeric_limits::max(); int figures = kDefaultHistogramFigures; }; explicit Histogram(const Options& options); virtual ~Histogram() = default; inline bool Record(int64_t value); inline void Reset(); inline int64_t Min() const; inline int64_t Max() const; inline double Mean() const; inline double Stddev() const; inline int64_t Percentile(double percentile) const; inline size_t Exceeds() const { return exceeds_; } inline size_t Count() const; inline uint64_t RecordDelta(); inline double Add(const Histogram& other); // Iterator is a function type that takes two doubles as argument, one for // percentile and one for the value at that percentile. template inline void Percentiles(Iterator&& fn); inline size_t GetMemorySize() const; void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(Histogram) SET_SELF_SIZE(Histogram) private: using HistogramPointer = DeleteFnPtr; HistogramPointer histogram_; uint64_t prev_ = 0; size_t exceeds_ = 0; size_t count_ = 0; Mutex mutex_; }; class HistogramImpl { public: enum InternalFields { kSlot = BaseObject::kSlot, kImplField = BaseObject::kInternalFieldCount, kInternalFieldCount }; explicit HistogramImpl( const Histogram::Options& options = Histogram::Options {}); explicit HistogramImpl(std::shared_ptr histogram); Histogram* operator->() { return histogram_.get(); } const std::shared_ptr& histogram() const { return histogram_; } static void DoReset(const v8::FunctionCallbackInfo& args); static void GetCountBigInt(const v8::FunctionCallbackInfo& args); static void GetMinBigInt(const v8::FunctionCallbackInfo& args); static void GetMaxBigInt(const v8::FunctionCallbackInfo& args); static void GetExceedsBigInt(const v8::FunctionCallbackInfo& args); static void GetCount(const v8::FunctionCallbackInfo& args); static void GetMin(const v8::FunctionCallbackInfo& args); static void GetMax(const v8::FunctionCallbackInfo& args); static void GetMean(const v8::FunctionCallbackInfo& args); static void GetExceeds(const v8::FunctionCallbackInfo& args); static void GetStddev(const v8::FunctionCallbackInfo& args); static void GetPercentile(const v8::FunctionCallbackInfo& args); static void GetPercentileBigInt( const v8::FunctionCallbackInfo& args); static void GetPercentiles(const v8::FunctionCallbackInfo& args); static void GetPercentilesBigInt( const v8::FunctionCallbackInfo& args); static void FastReset(v8::Local unused, v8::Local receiver); static double FastGetCount(v8::Local unused, v8::Local receiver); static double FastGetMin(v8::Local unused, v8::Local receiver); static double FastGetMax(v8::Local unused, v8::Local receiver); static double FastGetMean(v8::Local unused, v8::Local receiver); static double FastGetExceeds(v8::Local unused, v8::Local receiver); static double FastGetStddev(v8::Local unused, v8::Local receiver); static double FastGetPercentile(v8::Local unused, v8::Local receiver, const double percentile); static void AddMethods(v8::Isolate* isolate, v8::Local tmpl); static void RegisterExternalReferences(ExternalReferenceRegistry* registry); static HistogramImpl* FromJSObject(v8::Local value); private: std::shared_ptr histogram_; static v8::CFunction fast_reset_; static v8::CFunction fast_get_count_; static v8::CFunction fast_get_min_; static v8::CFunction fast_get_max_; static v8::CFunction fast_get_mean_; static v8::CFunction fast_get_exceeds_; static v8::CFunction fast_get_stddev_; static v8::CFunction fast_get_percentile_; }; class HistogramBase final : public BaseObject, public HistogramImpl { public: static v8::Local GetConstructorTemplate( IsolateData* isolate_data); static void Initialize(IsolateData* isolate_data, v8::Local target); static void RegisterExternalReferences(ExternalReferenceRegistry* registry); static BaseObjectPtr Create( Environment* env, const Histogram::Options& options = Histogram::Options {}); static BaseObjectPtr Create( Environment* env, std::shared_ptr histogram); static void New(const v8::FunctionCallbackInfo& args); void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(HistogramBase) SET_SELF_SIZE(HistogramBase) static void Record(const v8::FunctionCallbackInfo& args); static void RecordDelta(const v8::FunctionCallbackInfo& args); static void Add(const v8::FunctionCallbackInfo& args); static void FastRecord( v8::Local unused, v8::Local receiver, const int64_t value, v8::FastApiCallbackOptions& options); // NOLINT(runtime/references) static void FastRecordDelta(v8::Local unused, v8::Local receiver); HistogramBase( Environment* env, v8::Local wrap, const Histogram::Options& options = Histogram::Options {}); HistogramBase( Environment* env, v8::Local wrap, std::shared_ptr histogram); BaseObject::TransferMode GetTransferMode() const override { return TransferMode::kCloneable; } std::unique_ptr CloneForMessaging() const override; class HistogramTransferData : public worker::TransferData { public: explicit HistogramTransferData(const HistogramBase* histogram) : histogram_(histogram->histogram()) {} explicit HistogramTransferData(std::shared_ptr histogram) : histogram_(std::move(histogram)) {} BaseObjectPtr Deserialize( Environment* env, v8::Local context, std::unique_ptr self) override; void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(HistogramTransferData) SET_SELF_SIZE(HistogramTransferData) private: std::shared_ptr histogram_; }; private: static v8::CFunction fast_record_; static v8::CFunction fast_record_delta_; }; class IntervalHistogram final : public HandleWrap, public HistogramImpl { public: enum class StartFlags { NONE, RESET }; static void RegisterExternalReferences(ExternalReferenceRegistry* registry); static v8::Local GetConstructorTemplate( Environment* env); static BaseObjectPtr Create( Environment* env, int32_t interval, std::function on_interval, const Histogram::Options& options); IntervalHistogram( Environment* env, v8::Local wrap, AsyncWrap::ProviderType type, int32_t interval, std::function on_interval, const Histogram::Options& options = Histogram::Options {}); static void Start(const v8::FunctionCallbackInfo& args); static void Stop(const v8::FunctionCallbackInfo& args); static void FastStart(v8::Local unused, v8::Local receiver, bool reset); static void FastStop(v8::Local unused, v8::Local receiver); BaseObject::TransferMode GetTransferMode() const override { return TransferMode::kCloneable; } std::unique_ptr CloneForMessaging() const override; void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(IntervalHistogram) SET_SELF_SIZE(IntervalHistogram) private: static void TimerCB(uv_timer_t* handle); void OnStart(StartFlags flags = StartFlags::RESET); void OnStop(); bool enabled_ = false; int32_t interval_ = 0; std::function on_interval_; uv_timer_t timer_; static v8::CFunction fast_start_; static v8::CFunction fast_stop_; }; } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_HISTOGRAM_H_