27 #define NSOLID_PROCESS_METRICS_STRINGS(V) \
28 V(std::string, title, title, EOther) \
29 V(std::string, user, user, EOther)
31 #define NSOLID_PROCESS_METRICS_NUMBERS(V) \
32 V(uint64_t, timestamp, timestamp, ECounter) \
33 V(uint64_t, uptime, uptime, ECounter) \
34 V(uint64_t, system_uptime, systemUptime, ECounter) \
35 V(uint64_t, free_mem, freeMem, EGauge) \
36 V(uint64_t, block_input_op_count, blockInputOpCount, ECounter) \
37 V(uint64_t, block_output_op_count, blockOutputOpCount, ECounter) \
38 V(uint64_t, ctx_switch_involuntary_count, \
39 ctxSwitchInvoluntaryCount, \
41 V(uint64_t, ctx_switch_voluntary_count, ctxSwitchVoluntaryCount, ECounter) \
42 V(uint64_t, ipc_received_count, ipcReceivedCount, ECounter) \
43 V(uint64_t, ipc_sent_count, ipcSentCount, ECounter) \
44 V(uint64_t, page_fault_hard_count, pageFaultHardCount, ECounter) \
45 V(uint64_t, page_fault_soft_count, pageFaultSoftCount, ECounter) \
46 V(uint64_t, signal_count, signalCount, ECounter) \
47 V(uint64_t, swap_count, swapCount, ECounter) \
48 V(uint64_t, rss, rss, EGauge) \
49 V(double, load_1m, load1m, EGauge) \
50 V(double, load_5m, load5m, EGauge) \
51 V(double, load_15m, load15m, EGauge) \
52 V(double, cpu_user_percent, cpuUserPercent, EGauge) \
53 V(double, cpu_system_percent, cpuSystemPercent, EGauge) \
54 V(double, cpu_percent, cpuPercent, EGauge)
56 #define NSOLID_PROCESS_METRICS(V) \
57 NSOLID_PROCESS_METRICS_STRINGS(V) \
58 NSOLID_PROCESS_METRICS_NUMBERS(V)
60 #define NSOLID_ENV_METRICS(V) \
61 V(uint64_t, thread_id, threadId, EOther) \
62 V(uint64_t, timestamp, timestamp, ECounter) \
63 V(uint64_t, active_handles, activeHandles, EGauge) \
64 V(uint64_t, active_requests, activeRequests, EGauge) \
65 V(uint64_t, total_heap_size, heapTotal, EGauge) \
66 V(uint64_t, total_heap_size_executable, totalHeapSizeExecutable, EGauge) \
67 V(uint64_t, total_physical_size, totalPhysicalSize, EGauge) \
68 V(uint64_t, total_available_size, totalAvailableSize, EGauge) \
69 V(uint64_t, used_heap_size, heapUsed, EGauge) \
70 V(uint64_t, heap_size_limit, heapSizeLimit, EGauge) \
71 V(uint64_t, malloced_memory, mallocedMemory, EGauge) \
72 V(uint64_t, external_memory, externalMem, EGauge) \
73 V(uint64_t, peak_malloced_memory, peakMallocedMemory, EGauge) \
74 V(uint64_t, number_of_native_contexts, numberOfNativeContexts, EGauge) \
75 V(uint64_t, number_of_detached_contexts, numberOfDetachedContexts, EGauge) \
76 V(uint64_t, gc_count, gcCount, ECounter) \
77 V(uint64_t, gc_forced_count, gcForcedCount, ECounter) \
78 V(uint64_t, gc_full_count, gcFullCount, ECounter) \
79 V(uint64_t, gc_major_count, gcMajorCount, ECounter) \
80 V(double, gc_dur_us99_ptile, gcDurUs99Ptile, ESeries) \
81 V(double, gc_dur_us_median, gcDurUsMedian, ESeries) \
82 V(uint64_t, dns_count, dnsCount, ECounter) \
83 V(uint64_t, http_client_abort_count, httpClientAbortCount, ECounter) \
84 V(uint64_t, http_client_count, httpClientCount, ECounter) \
85 V(uint64_t, http_server_abort_count, httpServerAbortCount, ECounter) \
86 V(uint64_t, http_server_count, httpServerCount, ECounter) \
87 V(double, dns99_ptile, dns99Ptile, ESeries) \
88 V(double, dns_median, dnsMedian, ESeries) \
89 V(double, http_client99_ptile, httpClient99Ptile, ESeries) \
90 V(double, http_client_median, httpClientMedian, ESeries) \
91 V(double, http_server99_ptile, httpServer99Ptile, ESeries) \
92 V(double, http_server_median, httpServerMedian, ESeries) \
93 V(uint64_t, loop_idle_time, loopIdleTime, EGauge) \
94 V(uint64_t, loop_iterations, loopIterations, ECounter) \
95 V(uint64_t, loop_iter_with_events, loopIterWithEvents, ECounter) \
96 V(uint64_t, events_processed, eventsProcessed, ECounter) \
97 V(uint64_t, events_waiting, eventsWaiting, EGauge) \
98 V(uint64_t, provider_delay, providerDelay, EGauge) \
99 V(uint64_t, processing_delay, processingDelay, EGauge) \
100 V(double, loop_utilization, loopUtilization, EGauge) \
101 V(double, res_5s, res5s, EGauge) \
102 V(double, res_1m, res1m, EGauge) \
103 V(double, res_5m, res5m, EGauge) \
104 V(double, res_15m, res15m, EGauge) \
105 V(uint64_t, loop_total_count, loopTotalCount, ECounter) \
106 V(double, loop_avg_tasks, loopAvgTasks, EGauge) \
107 V(double, loop_estimated_lag, loopEstimatedLag, EGauge) \
108 V(double, loop_idle_percent, loopIdlePercent, EGauge)
110 #define NSOLID_ERRORS(V) \
111 V(SUCCESS, 0, "Success") \
112 V(NOT_LICENSED, 1, "N|Solid Runtime is not Licensed")
118 #define V(Type, Value, Msg) \
119 NSOLID_E_##Type = Value,
122 #define X(Type, Msg) \
123 NSOLID_E_UV_ ## Type = UV_ ## Type,
129 class ProcessMetrics;
135 using on_block_loop_hook_proxy_sig = void(*)(uint64_t, std::string,
void*);
136 using on_unblock_loop_hook_proxy_sig = on_block_loop_hook_proxy_sig;
137 using thread_added_hook_proxy_sig = void(*)(uint64_t,
void*);
138 using thread_removed_hook_proxy_sig = thread_added_hook_proxy_sig;
139 using on_license_proxy_sig = void(*)(bool, uint64_t,
void*);
140 using deleter_sig = void(*)(
void*);
142 template <
typename G>
143 void on_block_loop_hook_proxy_(uint64_t, std::string,
void*);
144 template <
typename G>
145 void on_unblock_loop_hook_proxy_(uint64_t, std::string,
void*);
146 template <
typename G>
147 void thread_added_hook_proxy_(uint64_t thread_id,
void* data);
148 template <
typename G>
149 void thread_removed_hook_proxy_(uint64_t thread_id,
void* data);
150 template <
typename G>
151 void license_hook_proxy_(
bool licensed, uint64_t expiration,
void* g);
152 template <
typename G>
153 void delete_proxy_(
void* g);
156 int on_block_loop_hook_(uint64_t,
158 on_block_loop_hook_proxy_sig,
160 int on_unblock_loop_hook_(
void*, on_unblock_loop_hook_proxy_sig, deleter_sig);
161 int thread_added_hook_(
void*, thread_added_hook_proxy_sig, deleter_sig);
162 int thread_removed_hook_(
void*,
163 thread_removed_hook_proxy_sig,
165 void SetOnLicenseHook(on_license_proxy_sig,
void*, deleter_sig);
188 class NODE_EXTERN ProcessMetrics {
199 ~ProcessMetrics() =
default;
206 #define PM1(Type, CName, JSName, MType) Type CName;
207 NSOLID_PROCESS_METRICS_STRINGS(PM1)
209 #define PM2(Type, CName, JSName, MType) Type CName = 0;
210 NSOLID_PROCESS_METRICS_NUMBERS(PM2)
221 std::string toJSON();
230 int Get(MetricsStor* stor);
241 uint64_t cpu_prev_[3];
242 uint64_t cpu_prev_time_;
250 class NODE_EXTERN ThreadMetrics {
253 using thread_metrics_proxy_sig = void(*)(ThreadMetrics*);
260 #define EM(Type, CName, JSName, MType) Type CName = 0;
261 NSOLID_ENV_METRICS(EM)
271 explicit ThreadMetrics(uint64_t thread_id);
272 ThreadMetrics() =
delete;
285 std::string toJSON();
294 int Get(MetricsStor* stor);
307 template <
typename Cb,
typename... Data>
308 int Update(Cb&& cb, Data&&... data);
311 int get_thread_metrics_();
312 static void get_general_metrics_(
void* inst, ThreadMetrics* tm);
313 static void get_heap_stats_(
void* inst, ThreadMetrics* tm);
314 static void get_event_loop_stats_(
void* inst, ThreadMetrics* tm);
315 static void get_http_dns_stats_(
void* inst, ThreadMetrics* tm);
316 static void get_gc_stats_(
void* inst, ThreadMetrics* tm);
318 template <
typename G>
319 static void thread_metrics_proxy_(ThreadMetrics* tm);
321 uint64_t thread_id_ = 0xFFFFFFFFFFFFFFFF;
322 uint64_t prev_idle_time_ = 0;
323 uint64_t prev_call_time_;
324 uint64_t current_hrtime_;
325 void* user_data_ =
nullptr;
326 thread_metrics_proxy_sig proxy_;
328 uv_mutex_t stor_lock_;
343 class NODE_EXTERN MetricsStream {
351 enum class Type: uint32_t {
353 kRawHttpClient = 1 << 1,
354 kRawHttpServer = 1 << 2,
355 kRawGcRegular = 1 << 3,
356 kRawGcForced = 1 << 4,
358 kRawGcMajor = 1 << 6,
362 using metrics_stream_bucket = std::vector<std::tuple<Type, double>>;
363 using metrics_stream_proxy_sig = void(*)(MetricsStream*,
364 metrics_stream_bucket,
373 explicit MetricsStream(uint64_t thread_id);
374 MetricsStream() =
delete;
402 template <
typename Cb,
typename... Data>
403 int Start(uint32_t flags,
423 template <
typename G>
424 static void metrics_stream_proxy_(MetricsStream*,
425 metrics_stream_bucket,
427 template <
typename G>
428 static void deleter_(
void*);
430 int DoStart(uint32_t flags,
433 metrics_stream_proxy_sig,
438 std::unique_ptr<Impl> impl_;
448 using cpu_profiler_proxy_sig = void(*)(int, std::string,
void*);
463 template <
typename Cb,
typename... Data>
464 static int TakeProfile(uint64_t thread_id,
475 static int StopProfile(uint64_t thread_id);
478 static int get_cpu_profile_(uint64_t thread_id,
480 cpu_profiler_proxy_sig proxy,
482 template <
typename G>
483 static void cpu_profiler_proxy_(
int status, std::string json,
void* data);
493 using snapshot_proxy_sig = void(*)(int, std::string,
void*);
506 template <
typename Cb,
typename... Data>
507 int TakeSnapshot(uint64_t thread_id, Cb&& cb, Data&&... data);
510 int get_snapshot_(uint64_t thread_id,
511 snapshot_proxy_sig proxy,
513 template <
typename G>
514 static void snapshot_proxy_(
int status, std::string profile,
void* data);
525 NODE_EXTERN
int ModuleInfo(uint64_t thread_id, std::string* json);
549 template <
typename Cb,
typename... Data>
561 template <
typename Cb,
typename... Data>
575 template <
typename Cb,
typename... Data>
588 template <
typename Cb,
typename... Data>
602 template <
typename Cb,
typename... Data>
609 NODE_EXTERN
void License(std::string token);
629 NODE_EXTERN uint64_t
ThreadId(v8::Local<v8::Context> context);
635 template <
typename Cb,
typename... Data>
638 using namespace std::placeholders;
639 using UserData = decltype(std::bind(
640 std::forward<Cb>(cb), _1, std::forward<Data>(data)...));
643 std::unique_ptr<UserData> user_data = std::make_unique<UserData>(std::bind(
644 std::forward<Cb>(cb), _1, std::forward<Data>(data)...));
646 user_data_ =
static_cast<void*
>(user_data.get());
647 proxy_ = thread_metrics_proxy_<UserData>;
648 stor_.thread_id = thread_id_;
650 int er = get_thread_metrics_();
657 template <
typename G>
658 void ThreadMetrics::thread_metrics_proxy_(ThreadMetrics* tm) {
659 G* g =
static_cast<G*
>(tm->user_data_);
660 tm->user_data_ =
nullptr;
661 tm->proxy_ =
nullptr;
667 template <
typename Cb,
typename... Data>
674 using namespace std::placeholders;
675 using UserData = decltype(std::bind(
676 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
679 UserData* user_data =
new UserData(std::bind(
680 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
681 int err = DoStart(flags,
684 metrics_stream_proxy_<UserData>,
685 internal::delete_proxy_<UserData>,
686 static_cast<void*
>(user_data));
695 template <
typename G>
696 void MetricsStream::metrics_stream_proxy_(
697 MetricsStream* ms, metrics_stream_bucket bucket,
void* g) {
698 (*
static_cast<G*
>(g))(ms, bucket);
702 template <
typename Cb,
typename... Data>
708 using namespace std::placeholders;
709 using UserData = decltype(std::bind(
710 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
714 std::unique_ptr<UserData> user_data = std::make_unique<UserData>(std::bind(
715 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
717 int er = get_cpu_profile_(thread_id,
719 cpu_profiler_proxy_<UserData>,
727 template <
typename G>
728 void CpuProfiler::cpu_profiler_proxy_(
int status,
731 (*
static_cast<G*
>(data))(status, json);
732 delete static_cast<G*
>(data);
736 template <
typename Cb,
typename... Data>
741 using namespace std::placeholders;
742 using UserData = decltype(std::bind(
743 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
747 std::unique_ptr<UserData> user_data = std::make_unique<UserData>(std::bind(
748 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
750 int er = get_snapshot_(thread_id,
751 snapshot_proxy_<UserData>,
759 template <
typename G>
760 void Snapshot::snapshot_proxy_(
int status, std::string profile,
void* data) {
761 (*
static_cast<G*
>(data))(status, profile);
762 delete static_cast<G*
>(data);
766 template <
typename Cb,
typename... Data>
769 using namespace std::placeholders;
770 using UserData = decltype(std::bind(
771 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
775 std::unique_ptr<UserData> user_data = std::make_unique<UserData>(std::bind(
776 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
778 int er = internal::on_block_loop_hook_(
781 internal::on_block_loop_hook_proxy_<UserData>,
782 internal::delete_proxy_<UserData>);
789 template <
typename Cb,
typename... Data>
792 using namespace std::placeholders;
793 using UserData = decltype(std::bind(
794 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
798 std::unique_ptr<UserData> user_data = std::make_unique<UserData>(std::bind(
799 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
801 int er = internal::on_unblock_loop_hook_(
803 internal::on_unblock_loop_hook_proxy_<UserData>,
804 internal::delete_proxy_<UserData>);
811 template <
typename Cb,
typename... Data>
814 using namespace std::placeholders;
815 using UserData = decltype(std::bind(
816 std::forward<Cb>(cb), _1, std::forward<Data>(data)...));
819 return NSOLID_E_NOT_LICENSED;
822 std::unique_ptr<UserData> user_data = std::make_unique<UserData>(std::bind(
823 std::forward<Cb>(cb), _1, std::forward<Data>(data)...));
825 int er = internal::thread_added_hook_(
827 internal::thread_added_hook_proxy_<UserData>,
828 internal::delete_proxy_<UserData>);
835 template <
typename Cb,
typename... Data>
838 using namespace std::placeholders;
839 using UserData = decltype(std::bind(
840 std::forward<Cb>(cb), _1, std::forward<Data>(data)...));
843 return NSOLID_E_NOT_LICENSED;
846 std::unique_ptr<UserData> user_data = std::make_unique<UserData>(std::bind(
847 std::forward<Cb>(cb), _1, std::forward<Data>(data)...));
849 int er = internal::thread_removed_hook_(
851 internal::thread_removed_hook_proxy_<UserData>,
852 internal::delete_proxy_<UserData>);
859 template <
typename Cb,
typename... Data>
862 using namespace std::placeholders;
863 using UserData = decltype(std::bind(
864 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
868 UserData* user_data =
new UserData(std::bind(
869 std::forward<Cb>(cb), _1, _2, std::forward<Data>(data)...));
871 internal::SetOnLicenseHook(internal::license_hook_proxy_<UserData>,
873 internal::delete_proxy_<UserData>);
880 template <
typename G>
881 void on_block_loop_hook_proxy_(uint64_t thread_id,
884 (*
static_cast<G*
>(data))(thread_id, info);
887 template <
typename G>
888 void on_unblock_loop_hook_proxy_(uint64_t thread_id,
891 (*
static_cast<G*
>(data))(thread_id, info);
894 template <
typename G>
895 void thread_added_hook_proxy_(uint64_t thread_id,
void* data) {
896 (*
static_cast<G*
>(data))(thread_id);
899 template <
typename G>
900 void thread_removed_hook_proxy_(uint64_t thread_id,
void* data) {
901 (*
static_cast<G*
>(data))(thread_id);
904 template <
typename G>
905 void license_hook_proxy_(
bool licensed, uint64_t expiration,
void* g) {
906 (*
static_cast<G*
>(g))(licensed, expiration);
909 template <
typename G>
910 void delete_proxy_(
void* g) {
911 delete static_cast<G*
>(g);
920 #endif // SRC_NSOLID_H_