diff --git a/src/commands/parser.cc b/src/commands/parser.cc index 019c2c7..93209dd 100644 --- a/src/commands/parser.cc +++ b/src/commands/parser.cc @@ -13,6 +13,15 @@ using nlohmann::json; using std::exception; using std::string; +#define HANDLE_COMMANDS(cmd_str, handle) \ + if (strcmp(cmd.c_str(), #cmd_str) == 0) { \ + handle( \ + parsed, FmtMessage, \ + [traceid](json data) { SuccessValue(traceid, data); }, \ + [traceid](string message) { ErrorValue(traceid, message); }); \ + handled = true; \ + } + void ParseCmd(char *command) { Debug("parser", "received command: %s", command); json parsed; @@ -36,33 +45,30 @@ void ParseCmd(char *command) { return; } -#define V(cmd_str, handle) \ - if (strcmp(cmd.c_str(), #cmd_str) == 0) { \ - handle( \ - parsed, FmtMessage, \ - [traceid](json data) { SuccessValue(traceid, data); }, \ - [traceid](string message) { ErrorValue(traceid, message); }); \ - handled = true; \ - } // get version - V(check_version, GetXprofilerVersion) + HANDLE_COMMANDS(check_version, GetXprofilerVersion) + // get/set config - V(get_config, GetXprofilerConfig) - V(set_config, SetXprofilerConfig) + HANDLE_COMMANDS(get_config, GetXprofilerConfig) + HANDLE_COMMANDS(set_config, SetXprofilerConfig) + // cpu profiling - V(start_cpu_profiling, StartCpuProfiling) - V(stop_cpu_profiling, StopCpuProfiling) + HANDLE_COMMANDS(start_cpu_profiling, StartCpuProfiling) + HANDLE_COMMANDS(stop_cpu_profiling, StopCpuProfiling) + // heapdump - V(heapdump, Heapdump) + HANDLE_COMMANDS(heapdump, Heapdump) + // sampling heap profiling - V(start_heap_profiling, StartSamplingHeapProfiling) - V(stop_heap_profiling, StopSamplingHeapProfiling) + HANDLE_COMMANDS(start_heap_profiling, StartSamplingHeapProfiling) + HANDLE_COMMANDS(stop_heap_profiling, StopSamplingHeapProfiling) + // gc profiling - V(start_gc_profiling, StartGcProfiling) - V(stop_gc_profiling, StopGcProfiling) + HANDLE_COMMANDS(start_gc_profiling, StartGcProfiling) + HANDLE_COMMANDS(stop_gc_profiling, StopGcProfiling) + // node report - V(diag_report, GetNodeReport) -#undef V + HANDLE_COMMANDS(diag_report, GetNodeReport) // not match any commands if (!handled) { diff --git a/src/commands/report/javascript_stack.cc b/src/commands/report/javascript_stack.cc index 31f091a..9529724 100644 --- a/src/commands/report/javascript_stack.cc +++ b/src/commands/report/javascript_stack.cc @@ -60,7 +60,8 @@ void SetJavaScriptStack(JSONWriter* writer) { else writer->json_keyvalue("pcAddress", "nullptr"); -#if (NODE_MODULE_VERSION >= 0x0040) +#if (NODE_VERSION_AT_LEAST(10, 12, 0)) + // needs v8 version >= 6.8 Local frame = stack->GetFrame(isolate, i); #else Local frame = stack->GetFrame(i); diff --git a/src/commands/send.cc b/src/commands/send.cc index f2687d1..1fce70f 100644 --- a/src/commands/send.cc +++ b/src/commands/send.cc @@ -5,7 +5,7 @@ namespace xprofiler { using nlohmann::json; using std::string; -#define V(ok, res) \ +#define SEND_VALUE(ok, res) \ result["ok"] = ok; \ result["traceid"] = traceid; \ result[#res] = res; \ @@ -13,13 +13,11 @@ using std::string; void ErrorValue(string traceid, string message) { json result; - V(false, message); + SEND_VALUE(false, message); } void SuccessValue(string traceid, json data) { json result; - V(true, data); + SEND_VALUE(true, data); } - -#undef V } // namespace xprofiler \ No newline at end of file diff --git a/src/commands/simple/config.cc b/src/commands/simple/config.cc index b78c2e0..f2d77a8 100644 --- a/src/commands/simple/config.cc +++ b/src/commands/simple/config.cc @@ -6,6 +6,20 @@ namespace xprofiler { using nlohmann::json; using std::exception; +#define HANDLE_CONFIG_SETTING(ret, key, func) \ + if (options.find(#key) != options.end()) { \ + ret value; \ + XpfError err; \ + value = GetJsonValue(options, #key, err); \ + if (err.Fail()) { \ + error(format("%s", err.GetErrMessage())); \ + return; \ + } \ + Set##func(value); \ + setted = true; \ + data[#key] = Get##func(); \ + } + COMMAND_CALLBACK(GetXprofilerConfig) { json data; data["log_dir"] = GetLogDir(); @@ -22,24 +36,12 @@ COMMAND_CALLBACK(SetXprofilerConfig) { json options = command["options"]; bool setted = false; json data; -#define V(ret, key, func) \ - if (options.find(#key) != options.end()) { \ - ret value; \ - XpfError err; \ - value = GetJsonValue(options, #key, err); \ - if (err.Fail()) { \ - error(format("%s", err.GetErrMessage())); \ - return; \ - } \ - Set##func(value); \ - setted = true; \ - data[#key] = Get##func(); \ - } - V(bool, enable_log_uv_handles, EnableLogUvHandles) - V(LOG_LEVEL, log_level, LogLevel) - V(LOG_TYPE, log_type, LogType) - V(bool, enable_fatal_error_hook, EnableFatalErrorHook) -#undef V + + HANDLE_CONFIG_SETTING(LOG_LEVEL, log_level, LogLevel) + HANDLE_CONFIG_SETTING(LOG_TYPE, log_type, LogType) + HANDLE_CONFIG_SETTING(bool, enable_log_uv_handles, EnableLogUvHandles) + HANDLE_CONFIG_SETTING(bool, enable_fatal_error_hook, EnableFatalErrorHook) + if (!setted) error(format("not support setting config %s", options.dump().c_str())); else diff --git a/src/configure.cc b/src/configure.cc index 0193f44..71246fb 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -1,5 +1,4 @@ -#include "library/common.h" -#include "nan.h" +#include "configure.h" namespace xprofiler { using Nan::FunctionCallbackInfo; @@ -19,94 +18,50 @@ using v8::Value; static string log_dir = "/tmp"; static uint32_t log_interval = 60; -static bool enable_log_uv_handles = true; -static bool log_format_alinode = false; static LOG_LEVEL log_level = LOG_ERROR; static LOG_TYPE log_type = LOG_TO_FILE; +static bool enable_log_uv_handles = true; +static bool log_format_alinode = false; static bool enable_fatal_error_hook = true; -#define COVERT_STRING(key) \ - if (key##_value->IsString()) { \ - Local key##_string = To(key##_value).ToLocalChecked(); \ - Utf8String key##_utf8string(key##_string); \ - key = *key##_utf8string; \ - } - -#define CONVERT_UINT32(key) \ - if (key##_value->IsUint32()) key = To(key##_value).ToChecked(); - -#define CONVERT_UINT32_V2(key, type) \ - if (key##_value->IsUint32()) \ - key = static_cast(To(key##_value).ToChecked()); - -#define CONVERT_BOOL(key) \ - if (key##_value->IsBoolean()) key = To(key##_value).ToChecked(); - void Configure(const FunctionCallbackInfo &info) { if (!info[0]->IsObject()) { ThrowTypeError(New("config must be object!").ToLocalChecked()); return; } Local config = To(info[0]).ToLocalChecked(); -#define S(key) \ - Local key##_value = \ - Get(config, New(#key).ToLocalChecked()).ToLocalChecked(); -#define V(key, cvrt) S(key) cvrt(key) -#define W(key, cvrt, type) S(key) cvrt(key, type) - // set log dir - V(log_dir, COVERT_STRING) - - // set log interval - V(log_interval, CONVERT_UINT32) - - // enable collecting uv handles - V(enable_log_uv_handles, CONVERT_BOOL) - - // log format: standard or alinode - V(log_format_alinode, CONVERT_BOOL) - // log level: 0 info, 1 error, 2 debug - W(log_level, CONVERT_UINT32_V2, LOG_LEVEL) + COVERT_STRING(log_dir) + CONVERT_UINT32(log_interval) + CONVERT_UINT32_WITH_TYPE(log_level, LOG_LEVEL) + CONVERT_UINT32_WITH_TYPE(log_type, LOG_TYPE) + CONVERT_BOOL(enable_log_uv_handles) + CONVERT_BOOL(log_format_alinode) + CONVERT_BOOL(enable_fatal_error_hook) - // log type: 0 file, 1 ttl - W(log_type, CONVERT_UINT32_V2, LOG_TYPE) - - // enable fatal error hook - V(enable_fatal_error_hook, CONVERT_BOOL) -#undef S -#undef V -#undef W info.GetReturnValue().Set(New(true)); } void GetConfig(const FunctionCallbackInfo &info) { Local config = New(); -#define V(key, type) \ - Set(config, New(#key).ToLocalChecked(), \ - New(key).ToLocalChecked()); -#define W(key, type) \ - Set(config, New(#key).ToLocalChecked(), New(key)); - V(log_dir, String) - W(log_interval, Number) - W(enable_log_uv_handles, Boolean) - W(log_format_alinode, Boolean) - W(log_level, Number) - W(log_type, Number) - W(enable_fatal_error_hook, Boolean) -#undef V -#undef W + + CONFIG_LOCAL_STRING(log_dir, String) + CONFIG_NATIVE_NUMBER(log_interval, Number) + CONFIG_NATIVE_NUMBER(log_level, Number) + CONFIG_NATIVE_NUMBER(log_type, Number) + CONFIG_NATIVE_NUMBER(enable_log_uv_handles, Boolean) + CONFIG_NATIVE_NUMBER(log_format_alinode, Boolean) + CONFIG_NATIVE_NUMBER(enable_fatal_error_hook, Boolean) + info.GetReturnValue().Set(config); } -#define V(ret, func, vari) \ - ret Get##func() { return vari; } \ - void Set##func(ret value) { vari = value; } -V(string, LogDir, log_dir) -V(uint32_t, LogInterval, log_interval) -V(bool, FormatAsAlinode, log_format_alinode) -V(bool, EnableLogUvHandles, enable_log_uv_handles) -V(LOG_LEVEL, LogLevel, log_level) -V(LOG_TYPE, LogType, log_type) -V(bool, EnableFatalErrorHook, enable_fatal_error_hook) -#undef V +// define getter / setter +DEFINE_GET_SET_FUNCTION(LogDir, string, log_dir) +DEFINE_GET_SET_FUNCTION(LogInterval, uint32_t, log_interval) +DEFINE_GET_SET_FUNCTION(LogLevel, LOG_LEVEL, log_level) +DEFINE_GET_SET_FUNCTION(LogType, LOG_TYPE, log_type) +DEFINE_GET_SET_FUNCTION(FormatAsAlinode, bool, log_format_alinode) +DEFINE_GET_SET_FUNCTION(EnableLogUvHandles, bool, enable_log_uv_handles) +DEFINE_GET_SET_FUNCTION(EnableFatalErrorHook, bool, enable_fatal_error_hook) } // namespace xprofiler \ No newline at end of file diff --git a/src/configure.h b/src/configure.h index f3dd2fc..30c70d3 100644 --- a/src/configure.h +++ b/src/configure.h @@ -10,18 +10,58 @@ using Nan::FunctionCallbackInfo; using std::string; using v8::Value; -// normal external -#define V(ret, func) \ - ret Get##func(); \ - void Set##func(ret value); -V(string, LogDir) -V(uint32_t, LogInterval) -V(bool, FormatAsAlinode) -V(bool, EnableLogUvHandles) -V(LOG_LEVEL, LogLevel) -V(LOG_TYPE, LogType) -V(bool, EnableFatalErrorHook) -#undef V +#define DECLARE_GETTER_FUNCTION(func_name, type) type Get##func_name() + +#define DECLARE_SETTER_FUNCTION(func_name, type) void Set##func_name(type value) + +#define DECLARE_GET_SET_FUNCTION(func_name, type) \ + DECLARE_GETTER_FUNCTION(func_name, type); \ + DECLARE_SETTER_FUNCTION(func_name, type); + +#define DEFINE_GET_SET_FUNCTION(func_name, type, vari) \ + DECLARE_GETTER_FUNCTION(func_name, type) { return vari; } \ + DECLARE_SETTER_FUNCTION(func_name, type) { vari = value; } + +#define LOCAL_VALUE(key) \ + Local key##_value = \ + Get(config, New(#key).ToLocalChecked()).ToLocalChecked(); + +#define COVERT_STRING(key) \ + LOCAL_VALUE(key) \ + if (key##_value->IsString()) { \ + Local key##_string = To(key##_value).ToLocalChecked(); \ + Utf8String key##_utf8string(key##_string); \ + key = *key##_utf8string; \ + } + +#define CONVERT_UINT32(key) \ + LOCAL_VALUE(key) \ + if (key##_value->IsUint32()) key = To(key##_value).ToChecked(); + +#define CONVERT_UINT32_WITH_TYPE(key, type) \ + LOCAL_VALUE(key) \ + if (key##_value->IsUint32()) \ + key = static_cast(To(key##_value).ToChecked()); + +#define CONVERT_BOOL(key) \ + LOCAL_VALUE(key) \ + if (key##_value->IsBoolean()) key = To(key##_value).ToChecked(); + +#define CONFIG_LOCAL_STRING(key, type) \ + Set(config, New(#key).ToLocalChecked(), \ + New(key).ToLocalChecked()); + +#define CONFIG_NATIVE_NUMBER(key, type) \ + Set(config, New(#key).ToLocalChecked(), New(key)); + +// declare getter / setter +DECLARE_GET_SET_FUNCTION(LogDir, string) +DECLARE_GET_SET_FUNCTION(LogInterval, uint32_t) +DECLARE_GET_SET_FUNCTION(LogLevel, LOG_LEVEL) +DECLARE_GET_SET_FUNCTION(LogType, LOG_TYPE) +DECLARE_GET_SET_FUNCTION(FormatAsAlinode, bool) +DECLARE_GET_SET_FUNCTION(EnableLogUvHandles, bool) +DECLARE_GET_SET_FUNCTION(EnableFatalErrorHook, bool) // javascript accessible void Configure(const FunctionCallbackInfo &info); diff --git a/src/logbypass/cpu.cc b/src/logbypass/cpu.cc index a190ee3..dfd16f0 100644 --- a/src/logbypass/cpu.cc +++ b/src/logbypass/cpu.cc @@ -1,6 +1,22 @@ #include "../logger.h" #include "../platform/platform.h" +namespace xprofiler { +#define INIT_CPU_PERIOD(period) \ + static double *cpu_##period = new double[period]; \ + static int cpu_##period##_array_index = 0; \ + static int cpu_##period##_array_length = period; + +#define SET_CPU_USAGE(period) \ + bool cpu_##period##_array_not_full = \ + cpu_##period##_array_index < cpu_##period##_array_length; \ + if (cpu_##period##_array_not_full) { \ + cpu_##period[cpu_##period##_array_index++] = cpu_now; \ + } else { \ + cpu_##period##_array_index = 0; \ + cpu_##period[cpu_##period##_array_index++] = cpu_now; \ + } + #define CALAULATE_AVERAGE(total_length, period) \ if (total_length == 0) return; \ for (int i = 0; i < total_length; i++) { \ @@ -8,19 +24,22 @@ } \ cpu_##period##_average = cpu_##period##_average / total_length; -namespace xprofiler { +#define CALAULATE_CPU_USAGE_IN_PERIOD(period) \ + bool cpu_##period##_array_not_full = \ + cpu_##period##_array_index < cpu_##period##_array_length; \ + if (cpu_##period##_array_not_full) { \ + CALAULATE_AVERAGE(cpu_##period##_array_index, period) \ + } else { \ + CALAULATE_AVERAGE(cpu_##period##_array_length, period) \ + } + // init cpu now double cpu_now = 0.0; // init cpu 15/30/60 -#define V(period) \ - static double *cpu_##period = new double[period]; \ - static int cpu_##period##_array_index = 0; \ - static int cpu_##period##_array_length = period; -V(15) -V(30) -V(60) -#undef V +INIT_CPU_PERIOD(15) +INIT_CPU_PERIOD(30) +INIT_CPU_PERIOD(60) void SetNowCpuUsage() { double cpu_now_ = GetNowCpuUsage(); @@ -29,36 +48,17 @@ void SetNowCpuUsage() { } cpu_now = cpu_now_; -#define V(period) \ - bool cpu_##period##_array_not_full = \ - cpu_##period##_array_index < cpu_##period##_array_length; \ - if (cpu_##period##_array_not_full) { \ - cpu_##period[cpu_##period##_array_index++] = cpu_now; \ - } else { \ - cpu_##period##_array_index = 0; \ - cpu_##period[cpu_##period##_array_index++] = cpu_now; \ - } - V(15) - V(30) - V(60) -#undef V + SET_CPU_USAGE(15) + SET_CPU_USAGE(30) + SET_CPU_USAGE(60) } void WriteCpuUsageInPeriod(bool log_format_alinode) { double cpu_15_average = 0.0, cpu_30_average = 0.0, cpu_60_average = 0.0; -#define V(period) \ - bool cpu_##period##_array_not_full = \ - cpu_##period##_array_index < cpu_##period##_array_length; \ - if (cpu_##period##_array_not_full) { \ - CALAULATE_AVERAGE(cpu_##period##_array_index, period) \ - } else { \ - CALAULATE_AVERAGE(cpu_##period##_array_length, period) \ - } - V(15) - V(30) - V(60) -#undef V + CALAULATE_CPU_USAGE_IN_PERIOD(15) + CALAULATE_CPU_USAGE_IN_PERIOD(30) + CALAULATE_CPU_USAGE_IN_PERIOD(60) if (log_format_alinode) Info( diff --git a/src/logbypass/heap.cc b/src/logbypass/heap.cc index fb1e208..ee74af6 100644 --- a/src/logbypass/heap.cc +++ b/src/logbypass/heap.cc @@ -37,33 +37,15 @@ void SetHeapSpaceStatistics() { size_t number_of_heap_spaces = isolate->NumberOfHeapSpaces(); for (size_t i = 0; i < number_of_heap_spaces; i++) { isolate->GetHeapSpaceStatistics(&s, i); -#define V(name) \ - if (strcmp(s.space_name(), #name) == 0) { \ - heap_space_statistics->name##_size = s.space_size(); \ - heap_space_statistics->name##_used = s.space_used_size(); \ - heap_space_statistics->name##_available = s.space_available_size(); \ - heap_space_statistics->name##_committed = s.physical_space_size(); \ - } - // new space - V(new_space) - // old space - V(old_space) - // code space - V(code_space) - // map space - V(map_space) - // large object space - V(large_object_space) - // read only space - // needs v8 version >= 6.8 - V(read_only_space) - // new large object space - // needs v8 version >= 6.9 - V(new_large_object_space) - // code large object space - // needs v8 version >= 7.3 - V(code_large_object_space) -#undef V + + SET_SPACE_INFO(new_space) + SET_SPACE_INFO(old_space) + SET_SPACE_INFO(code_space) + SET_SPACE_INFO(map_space) + SET_SPACE_INFO(large_object_space) + SET_SPACE_INFO(read_only_space) // needs v8 version >= 6. + SET_SPACE_INFO(new_large_object_space) // needs v8 version >= 6.9 + SET_SPACE_INFO(code_large_object_space) // needs v8 version >= 7.3 } } @@ -86,11 +68,6 @@ void UnrefMemoryAsyncHandle() { void GetMemoryInfo() { uv_async_send(&memory_statistics_trigger); } void WriteMemoryInfoToLog(bool log_format_alinode) { -#define V(name) \ - heap_space_statistics->name##_space_size, \ - heap_space_statistics->name##_space_used, \ - heap_space_statistics->name##_space_available, \ - heap_space_statistics->name##_space_committed if (log_format_alinode) { Info("heap", "rss: %zu, " @@ -143,22 +120,11 @@ void WriteMemoryInfoToLog(bool log_format_alinode) { heap_statistics->total_heap_size_executable(), heap_statistics->total_physical_size(), heap_statistics->malloced_memory(), heap_statistics->external_memory(), - // new space - V(new), - // old space - V(old), - // code space - V(code), - // map space - V(map), - // large object space - V(large_object), - // read only space - V(read_only), - // new large object space - V(new_large_object), - // code large object space - V(code_large_object)); + // space statistics + LOG_SPACE_INFO(new), LOG_SPACE_INFO(old), LOG_SPACE_INFO(code), + LOG_SPACE_INFO(map), LOG_SPACE_INFO(large_object), + LOG_SPACE_INFO(read_only), LOG_SPACE_INFO(new_large_object), + LOG_SPACE_INFO(code_large_object)); } else { Info("memory", "memory_usage(byte) " @@ -212,23 +178,11 @@ void WriteMemoryInfoToLog(bool log_format_alinode) { heap_statistics->total_heap_size_executable(), heap_statistics->total_physical_size(), heap_statistics->malloced_memory(), heap_statistics->external_memory(), - // new space - V(new), - // old space - V(old), - // code space - V(code), - // map space - V(map), - // large object space - V(large_object), - // read only space - V(read_only), - // new large object space - V(new_large_object), - // code large object space - V(code_large_object)); + // space statistics + LOG_SPACE_INFO(new), LOG_SPACE_INFO(old), LOG_SPACE_INFO(code), + LOG_SPACE_INFO(map), LOG_SPACE_INFO(large_object), + LOG_SPACE_INFO(read_only), LOG_SPACE_INFO(new_large_object), + LOG_SPACE_INFO(code_large_object)); } -#undef V } } // namespace xprofiler diff --git a/src/logbypass/heap.h b/src/logbypass/heap.h index 1666061..2df4966 100644 --- a/src/logbypass/heap.h +++ b/src/logbypass/heap.h @@ -7,6 +7,26 @@ namespace xprofiler { using v8::HeapStatistics; +#define INIT_SPACE_INFO(name) \ + size_t name##_space_size = 0; \ + size_t name##_space_used = 0; \ + size_t name##_space_available = 0; \ + size_t name##_space_committed = 0; + +#define SET_SPACE_INFO(name) \ + if (strcmp(s.space_name(), #name) == 0) { \ + heap_space_statistics->name##_size = s.space_size(); \ + heap_space_statistics->name##_used = s.space_used_size(); \ + heap_space_statistics->name##_available = s.space_available_size(); \ + heap_space_statistics->name##_committed = s.physical_space_size(); \ + } + +#define LOG_SPACE_INFO(name) \ + heap_space_statistics->name##_space_size, \ + heap_space_statistics->name##_space_used, \ + heap_space_statistics->name##_space_available, \ + heap_space_statistics->name##_space_committed + // heap statistics struct typedef struct { public: @@ -40,31 +60,14 @@ typedef struct { // heap space statistics struct typedef struct { -#define V(name) \ - size_t name##_space_size = 0; \ - size_t name##_space_used = 0; \ - size_t name##_space_available = 0; \ - size_t name##_space_committed = 0; - // new space - V(new) - // old space - V(old) - // code space - V(code) - // map space - V(map) - // large object space - V(large_object) - // read only space - // needs v8 version >= 6.8 - V(read_only) - // new large object space - // needs v8 version >= 6.9 - V(new_large_object) - // code large object space - // needs v8 version >= 7.3 - V(code_large_object) -#undef V + INIT_SPACE_INFO(new) + INIT_SPACE_INFO(old) + INIT_SPACE_INFO(code) + INIT_SPACE_INFO(map) + INIT_SPACE_INFO(large_object) + INIT_SPACE_INFO(read_only) // needs v8 version >= 6.8 + INIT_SPACE_INFO(new_large_object) // needs v8 version >= 6.9 + INIT_SPACE_INFO(code_large_object) // needs v8 version >= 7.3 } heap_space_statistics_t; int InitMemoryAsyncCallback(); diff --git a/src/logbypass/libuv.h b/src/logbypass/libuv.h index 627fe0e..7dfc637 100644 --- a/src/logbypass/libuv.h +++ b/src/logbypass/libuv.h @@ -5,26 +5,26 @@ namespace xprofiler { #define HANDLE_DEFAULT_VALUE 0 -typedef struct { -#define V(name) \ +#define INIT_UV_HANDLE(name) \ int active_##name##_handles = HANDLE_DEFAULT_VALUE; \ int active_and_ref_##name##_handles = HANDLE_DEFAULT_VALUE; - V(file) - V(tcp) - V(udp) - V(timer) -#undef V - // reset record - void reset() { -#define V(name) \ +#define RESET_UV_HANDLE(name) \ active_##name##_handles = HANDLE_DEFAULT_VALUE; \ active_and_ref_##name##_handles = HANDLE_DEFAULT_VALUE; - V(file) - V(tcp) - V(udp) - V(timer) -#undef V + +typedef struct { + INIT_UV_HANDLE(file) + INIT_UV_HANDLE(tcp) + INIT_UV_HANDLE(udp) + INIT_UV_HANDLE(timer) + + // reset record + void reset() { + RESET_UV_HANDLE(file) + RESET_UV_HANDLE(tcp) + RESET_UV_HANDLE(udp) + RESET_UV_HANDLE(timer) } } uv_handle_statistics_t; diff --git a/src/logger.cc b/src/logger.cc index a3be73f..9308040 100644 --- a/src/logger.cc +++ b/src/logger.cc @@ -21,6 +21,32 @@ using std::to_string; using v8::Local; using v8::String; +#define WRITET_TO_FILE(type) \ + uv_mutex_lock(&logger_mutex); \ + type##_stream.open(filepath, std::ios::app); \ + type##_stream << log; \ + type##_stream.flush(); \ + type##_stream.close(); \ + uv_mutex_unlock(&logger_mutex); + +#define LOG_WITH_LEVEL(level) \ + va_list args; \ + va_start(args, format); \ + Log(LOG_LEVEL::level, log_type, format, args); \ + va_end(args); + +#define JS_LOG_WITH_LEVEL(level) \ + if (!info[0]->IsString() || !info[1]->IsString()) { \ + ThrowTypeError( \ + New("log type and content must be string!").ToLocalChecked()); \ + return; \ + } \ + Local log_type_string = To(info[0]).ToLocalChecked(); \ + Utf8String log_type(log_type_string); \ + Local log_content_string = To(info[1]).ToLocalChecked(); \ + Utf8String log_content(log_content_string); \ + Log(LOG_LEVEL::level, *log_type, *log_content); + static const int kMaxMessageLength = 2048; static const int kMaxFormatLength = 2048; @@ -31,14 +57,6 @@ static std::ofstream info_stream; static std::ofstream error_stream; static std::ofstream debug_stream; -#define WRITET_TO_FILE(type) \ - uv_mutex_lock(&logger_mutex); \ - type##_stream.open(filepath, std::ios::app); \ - type##_stream << log; \ - type##_stream.flush(); \ - type##_stream.close(); \ - uv_mutex_unlock(&logger_mutex); - static void WriteToFile(const LOG_LEVEL output_level, char *log) { // get time of date char time_string_day[32]; @@ -154,30 +172,29 @@ int InitLogger() { return rc; } -#define V(level) \ - va_list args; \ - va_start(args, format); \ - Log(LOG_LEVEL::level, log_type, format, args); \ - va_end(args); -void Info(const char *log_type, const char *format, ...) { V(LOG_INFO) } -void Error(const char *log_type, const char *format, ...) { V(LOG_ERROR) } -void Debug(const char *log_type, const char *format, ...) { V(LOG_DEBUG) } -#undef V +/* native logger */ +void Info(const char *log_type, const char *format, ...) { + LOG_WITH_LEVEL(LOG_INFO) +} -#define V(level) \ - if (!info[0]->IsString() || !info[1]->IsString()) { \ - ThrowTypeError( \ - New("log type and content must be string!").ToLocalChecked()); \ - return; \ - } \ - Local log_type_string = To(info[0]).ToLocalChecked(); \ - Utf8String log_type(log_type_string); \ - Local log_content_string = To(info[1]).ToLocalChecked(); \ - Utf8String log_content(log_content_string); \ - Log(LOG_LEVEL::level, *log_type, *log_content); -void JsInfo(const FunctionCallbackInfo &info) { V(LOG_INFO) } -void JsError(const FunctionCallbackInfo &info) { V(LOG_ERROR) } -void JsDebug(const FunctionCallbackInfo &info) { V(LOG_DEBUG) } -#undef V +void Error(const char *log_type, const char *format, ...) { + LOG_WITH_LEVEL(LOG_ERROR) +} +void Debug(const char *log_type, const char *format, ...) { + LOG_WITH_LEVEL(LOG_DEBUG) +} + +/* js binding logger */ +void JsInfo(const FunctionCallbackInfo &info) { + JS_LOG_WITH_LEVEL(LOG_INFO) +} + +void JsError(const FunctionCallbackInfo &info) { + JS_LOG_WITH_LEVEL(LOG_ERROR) +} + +void JsDebug(const FunctionCallbackInfo &info) { + JS_LOG_WITH_LEVEL(LOG_DEBUG) +} }; // namespace xprofiler diff --git a/src/xprofiler.cc b/src/xprofiler.cc index 8f8fbb9..4c96ae5 100644 --- a/src/xprofiler.cc +++ b/src/xprofiler.cc @@ -13,6 +13,10 @@ using Nan::Set; using v8::FunctionTemplate; using v8::String; +#define CREATE_JS_BINDING(js_func, native_func) \ + Set(target, New(#js_func).ToLocalChecked(), \ + GetFunction(New(native_func)).ToLocalChecked()); + NAN_MODULE_INIT(Initialize) { // init global variables InitGlobalVariables(); @@ -21,28 +25,23 @@ NAN_MODULE_INIT(Initialize) { int rc = InitLogger(); if (rc != 0) return; -#define V(js_func, native_func) \ - Set(target, New(#js_func).ToLocalChecked(), \ - GetFunction(New(native_func)).ToLocalChecked()); // config - V(configure, Configure) - V(getConfig, GetConfig) + CREATE_JS_BINDING(configure, Configure) + CREATE_JS_BINDING(getConfig, GetConfig) // js logger - V(info, JsInfo) - V(error, JsError) - V(debug, JsDebug) + CREATE_JS_BINDING(info, JsInfo) + CREATE_JS_BINDING(error, JsError) + CREATE_JS_BINDING(debug, JsDebug) // performance log - V(runLogBypass, RunLogBypass) + CREATE_JS_BINDING(runLogBypass, RunLogBypass) // commands listener - V(runCommandsListener, RunCommandsListener) + CREATE_JS_BINDING(runCommandsListener, RunCommandsListener) // set hooks - V(setHooks, SetHooks) - -#undef V + CREATE_JS_BINDING(setHooks, SetHooks) } NODE_MODULE(xprofiler, Initialize) diff --git a/test/config.test.js b/test/config.test.js index 8cdc385..42a3b68 100644 --- a/test/config.test.js +++ b/test/config.test.js @@ -51,7 +51,7 @@ describe('xprofiler config', function () { describe('xprofiler config keys', function () { const configKeys = Object.keys(defaultConfig); it(`should have these keys: [${configKeys.join(', ')}]`, function () { - expect(testKeys.join(', ')).to.be(configKeys.join(', ')); + expect(utils.arrayEqual(testKeys, configKeys)).to.be.ok(); }); }); diff --git a/test/fixtures/utils.js b/test/fixtures/utils.js index 3d13fd6..0f7f432 100644 --- a/test/fixtures/utils.js +++ b/test/fixtures/utils.js @@ -44,4 +44,8 @@ exports.getNestingValue = function (origin, key) { origin = origin[k]; } return origin; +}; + +exports.arrayEqual = function arrayEqual(arr1, arr2) { + return arr1.every(a1 => arr2.includes(a1)) && arr2.every(a2 => arr1.includes(a2)); }; \ No newline at end of file