Skip to content

Commit

Permalink
feat: support generate core by xprofctl
Browse files Browse the repository at this point in the history
PR-URL: #171
  • Loading branch information
hyj1991 committed May 1, 2022
1 parent b5c4b58 commit 0ddefbf
Show file tree
Hide file tree
Showing 38 changed files with 7,190 additions and 61 deletions.
11 changes: 10 additions & 1 deletion bin/xprofctl
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,23 @@ const args = yargs
.command('stop_gc_profiling', '生成 gcprofile', normalYargs)
.command('heapdump', '生成 heapsnapshot', normalYargs)
.command('diag_report', '生成诊断报告', normalYargs)
.command('generate_cored', '生成 coredump', normalYargs)
.command('check_version', '获取 xprofiler 版本号', normalYargs)
.command('get_config', '获取 xprofiler 配置', normalYargs)
.command('set_config', '设置 xprofiler 配置',
yargs => yargs
.group(['enable_log_uv_handles', 'disable_log_uv_handles', 'log_level',
'log_type'], '配置项:')
'log_type', 'enable_fatal_error_report', 'enable_fatal_error_coredump'], '配置项:')
.describe('enable_log_uv_handles', '开启 libuv 句柄详情采集')
.describe('disable_log_uv_handles', '关闭 libuv 句柄详情采集')
.describe('log_level', '日志级别: info, error, debug')
.describe('log_type', '日志输出未知: 文件, 控制台')
.describe('enable_fatal_error_report', 'Fatal Error 发生时自动生成 Report 报告')
.describe('enable_fatal_error_coredump', 'Fatal Error 发生时自动生成 Coredump 文件')
.boolean('enable_log_uv_handles')
.boolean('disable_log_uv_handles')
.boolean('enable_fatal_error_report')
.boolean('enable_fatal_error_coredump')
.choices('log_level', [0, 1, 2])
.choices('log_type', [0, 1])
.hide('v')
Expand Down Expand Up @@ -145,6 +150,10 @@ xctl(pid, thread_id, action, options.data)
console.log(`诊断报告文件路径: ${data.filepath}`);
console.log(`生成诊断报告可能需要数秒至数十秒.`);
break;
case 'generate_coredump':
console.log(`Coredump 文件路径: ${data.filepath}`);
console.log(`生成 Coredump 可能需要数秒至数十秒.`);
break;
default:
console.error(`未知操作 ${action}: ${JSON.stringify(data)}`);
}
Expand Down
15 changes: 14 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"src/commands/report/heap_statistics.cc",
"src/commands/report/uv_statistics.cc",
"src/commands/report/system_statistics.cc",
"src/commands/coredumper/coredumper.cc",
"src/hooks/set_hooks.cc",
"src/hooks/fatal_error.cc",
"src/util.cc",
Expand All @@ -53,7 +54,12 @@
"cflags_cc!": ["-fno-exceptions"],
"conditions": [
["OS == 'linux'", {
"cflags": ["-O2", "-std=c++14"],
"cflags": [
"-O2",
"-std=c++14",
"-Wno-sign-compare",
"-Wno-cast-function-type",
],
"defines": [
'XPROFILER_IPC_PATH="<!(node -p \"require(\'./package.json\').xctlIpcPath.unix\")"',
],
Expand All @@ -62,6 +68,11 @@
"src/platform/unix/utils.cc",
"src/platform/unix/ipc.cc",
"src/platform/unix/report.cc",
"src/platform/unix/core/linux/dump.cc",
"src/platform/unix/core/linux/coredumper.cc",
"src/platform/unix/core/linux/elfcore.cc",
"src/platform/unix/core/linux/linuxthreads.cc",
"src/platform/unix/core/linux/thread_lister.cc"
]
}],
["OS == 'mac'", {
Expand All @@ -81,6 +92,7 @@
"src/platform/unix/utils.cc",
"src/platform/unix/ipc.cc",
"src/platform/unix/report.cc",
"src/platform/unix/core/darwin.cc",
]
}],
["OS == 'win'", {
Expand All @@ -101,6 +113,7 @@
"src/platform/win/utils_win.cc",
"src/platform/win/ipc_win.cc",
"src/platform/win/report_win.cc",
"src/platform/win/core_win.cc"
]
}],
],
Expand Down
4 changes: 3 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ export interface XprofilerConfig {
log_type?: 0 | 1;
log_format_alinode?: boolean;
enable_log_uv_handles?: boolean;
enable_fatal_error_hook?: boolean;
patch_http?: boolean;
patch_http_timeout?: number;
check_throw?: boolean;
enable_fatal_error_hook?: boolean;
enable_fatal_error_report?: boolean;
enable_fatal_error_coredump?: boolean;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion lib/configure.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ const defaultConfig = {
log_format_alinode: false,
log_level: 1,
log_type: 0,
enable_fatal_error_hook: true,
patch_http: true,
patch_http_timeout: 30, // seconds,
check_throw: true,
enable_fatal_error_hook: true,
enable_fatal_error_report: true,
enable_fatal_error_coredump: false,
};

function checkLogDirAccessiable(logdir) {
Expand Down
7 changes: 7 additions & 0 deletions src/commands/coredumper/coredumper.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "coredumper.h"

#include "platform/platform.h"

namespace xprofiler {
void Coredumper::WriteCoredump(std::string filename) { WriteCore(filename); }
} // namespace xprofiler
13 changes: 13 additions & 0 deletions src/commands/coredumper/coredumper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef XPROFILER_SRC_COMMANDS_COREDUMPER_H
#define XPROFILER_SRC_COMMANDS_COREDUMOER_H

#include <string>

namespace xprofiler {
class Coredumper {
public:
static void WriteCoredump(std::string filename);
};
} // namespace xprofiler

#endif /* XPROFILER_SRC_COMMANDS_COREDUMOER_H */
25 changes: 25 additions & 0 deletions src/commands/dump.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "dump.h"

#include "configure-inl.h"
#include "coredumper/coredumper.h"
#include "cpuprofiler/cpu_profiler.h"
#include "environment_data.h"
#include "gcprofiler/gc_profiler.h"
Expand Down Expand Up @@ -50,6 +51,7 @@ std::string sampling_heapprofile_filepath = "";
std::string heapsnapshot_filepath = "";
std::string gcprofile_filepath = "";
std::string node_report_filepath = "";
std::string coredump_filepath = "";

string Action2String(DumpAction action) {
string name = "";
Expand Down Expand Up @@ -78,6 +80,9 @@ string Action2String(DumpAction action) {
case NODE_REPORT:
name = "node_report";
break;
case COREDUMP:
name = "coredump";
break;
default:
name = "unknown";
break;
Expand Down Expand Up @@ -239,6 +244,12 @@ void HandleAction(v8::Isolate* isolate, void* data, string notify_type) {
action_map.erase(NODE_REPORT);
break;
}
case COREDUMP: {
Coredumper::WriteCoredump(coredump_filepath);
AfterDumpFile(coredump_filepath, notify_type, unique_key);
action_map.erase(COREDUMP);
break;
}
default:
Error(module_type, "not support dump action: %d", action);
break;
Expand Down Expand Up @@ -374,10 +385,21 @@ static json DoDumpAction(json command, DumpAction action, string prefix,
node_report_filepath = CreateFilepath(prefix, ext);
result["filepath"] = node_report_filepath;
break;
case COREDUMP:
#ifdef __linux__
coredump_filepath = CreateFilepath(prefix, ext);
result["filepath"] = coredump_filepath;
#else
err = XpfError::Failure("generate_coredump only support linux now.");
action_map.erase(COREDUMP);
#endif
break;
default:
break;
}

if (err.Fail()) return result;

// set action callback data
data->traceid = traceid;
data->thread_id = thread_id;
Expand Down Expand Up @@ -441,6 +463,9 @@ V(Heapdump, HeapdumpDumpData, HEAPDUMP, false, heapdump, heapsnapshot)
// dynamic report
V(GetNodeReport, NodeReportDumpData, NODE_REPORT, false, diagreport, diag)

// generate coredump
V(GenerateCoredump, CoreDumpData, COREDUMP, false, coredump, core)

#undef V

#undef CHECK_ERR
Expand Down
6 changes: 5 additions & 1 deletion src/commands/dump.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ enum DumpAction {
STOP_SAMPLING_HEAP_PROFILING,
START_GC_PROFILING,
STOP_GC_PROFILING,
NODE_REPORT
NODE_REPORT,
COREDUMP,
};

using ActionMap = std::unordered_map<int, bool>;
Expand Down Expand Up @@ -45,6 +46,8 @@ struct GcProfilerDumpData : BaseDumpData {};

struct NodeReportDumpData : BaseDumpData {};

struct CoreDumpData : BaseDumpData {};

COMMAND_CALLBACK(StartCpuProfiling);
COMMAND_CALLBACK(StopCpuProfiling);
COMMAND_CALLBACK(Heapdump);
Expand All @@ -53,6 +56,7 @@ COMMAND_CALLBACK(StopSamplingHeapProfiling);
COMMAND_CALLBACK(StartGcProfiling);
COMMAND_CALLBACK(StopGcProfiling);
COMMAND_CALLBACK(GetNodeReport);
COMMAND_CALLBACK(GenerateCoredump);
} // namespace xprofiler

#endif /* XPROFILER_SRC_COMMANDS_DUMP_H */
3 changes: 3 additions & 0 deletions src/commands/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ void ParseCmd(char* command) {
// node report
HANDLE_COMMANDS(diag_report, GetNodeReport)

// generator
HANDLE_COMMANDS(generate_coredump, GenerateCoredump)

// not match any commands
/* else */ {
ErrorValue(traceid, FmtMessage("not support command: %s", cmd.c_str()));
Expand Down
4 changes: 3 additions & 1 deletion src/commands/simple/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ COMMAND_CALLBACK(GetXprofilerConfig) {
data["log_format_alinode"] = GetFormatAsAlinode();
data["log_level"] = GetLogLevel();
data["log_type"] = GetLogType();
data["enable_fatal_error_hook"] = GetEnableFatalErrorHook();
data["patch_http"] = GetPatchHttp();
data["patch_http_timeout"] = GetPatchHttpTimeout();
data["check_throw"] = GetCheckThrow();
data["enable_fatal_error_hook"] = GetEnableFatalErrorHook();
data["enable_fatal_error_report"] = GetEnableFatalErrorReport();
data["enable_fatal_error_coredump"] = GetEnableFatalErrorCoredump();
success(data);
}

Expand Down
8 changes: 8 additions & 0 deletions src/configure-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ bool GetEnableFatalErrorHook() {
return per_process::config_store.enable_fatal_error_hook;
}

bool GetEnableFatalErrorReport() {
return per_process::config_store.enable_fatal_error_report;
}

bool GetEnableFatalErrorCoredump() {
return per_process::config_store.enable_fatal_error_coredump;
}

bool GetPatchHttp() { return per_process::config_store.patch_http; }

uint32_t GetPatchHttpTimeout() {
Expand Down
8 changes: 6 additions & 2 deletions src/configure.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,12 @@ void Configure(const FunctionCallbackInfo<Value>& info) {
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)
CONVERT_BOOL(patch_http)
CONVERT_UINT32(patch_http_timeout)
CONVERT_BOOL(check_throw)
CONVERT_BOOL(enable_fatal_error_hook)
CONVERT_BOOL(enable_fatal_error_report)
CONVERT_BOOL(enable_fatal_error_coredump)

info.GetReturnValue().Set(New<Boolean>(true));
}
Expand All @@ -94,10 +96,12 @@ void GetConfig(const FunctionCallbackInfo<Value>& info) {
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)
CONFIG_NATIVE_NUMBER(patch_http, Boolean)
CONFIG_NATIVE_NUMBER(patch_http_timeout, Number)
CONFIG_NATIVE_NUMBER(check_throw, Boolean)
CONFIG_NATIVE_NUMBER(enable_fatal_error_hook, Boolean)
CONFIG_NATIVE_NUMBER(enable_fatal_error_report, Boolean)
CONFIG_NATIVE_NUMBER(enable_fatal_error_coredump, Boolean)

info.GetReturnValue().Set(config);
}
Expand Down
8 changes: 6 additions & 2 deletions src/configure.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ inline LOG_LEVEL GetLogLevel();
inline LOG_TYPE GetLogType();
inline bool GetFormatAsAlinode();
inline bool GetEnableLogUvHandles();
inline bool GetEnableFatalErrorHook();
inline bool GetPatchHttp();
inline uint32_t GetPatchHttpTimeout();
inline bool GetCheckThrow();
inline bool GetEnableFatalErrorHook();
inline bool GetEnableFatalErrorReport();
inline bool GetEnableFatalErrorCoredump();

inline void SetLogLevel(LOG_LEVEL value);
inline void SetLogType(LOG_TYPE value);
Expand All @@ -36,10 +38,12 @@ class ConfigStore {
LOG_TYPE log_type = LOG_TO_FILE;
bool enable_log_uv_handles = true;
bool log_format_alinode = false;
bool enable_fatal_error_hook = true;
bool patch_http = true;
uint32_t patch_http_timeout = 30;
bool check_throw = true;
bool enable_fatal_error_hook = true;
bool enable_fatal_error_report = true;
bool enable_fatal_error_coredump = false;
};

namespace per_process {
Expand Down
29 changes: 22 additions & 7 deletions src/hooks/fatal_error.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "commands/coredumper/coredumper.h"
#include "commands/report/node_report.h"
#include "configure-inl.h"
#include "library/utils.h"
Expand All @@ -22,14 +23,28 @@ constexpr char module_type[] = "fatal_error";
}
fflush(stderr);

string filepath = GetLogDir() + GetSep() + "x-fatal-error-" +
to_string(GetPid()) + "-" + ConvertTime("%Y%m%d") + "-" +
to_string(GetNextDiagFileId()) + ".diag";

Info(module_type, "dump report to %s.", filepath.c_str());
Isolate* isolate = TryGetCurrentIsolate();
NodeReport::GetNodeReport(isolate, filepath, location, message, true);
Info(module_type, "report dumped.");

// generate report before abort
if (GetEnableFatalErrorReport()) {
string filepath = GetLogDir() + GetSep() + "x-fatal-error-" +
to_string(GetPid()) + "-" + ConvertTime("%Y%m%d") + "-" +
to_string(GetNextDiagFileId()) + ".diag";

Info(module_type, "dump report to %s.", filepath.c_str());
NodeReport::GetNodeReport(isolate, filepath, location, message, true);
Info(module_type, "report dumped.");
}

// generator core file before abort
if (GetEnableFatalErrorCoredump()) {
string filepath = GetLogDir() + GetSep() + "x-fatal-error-" +
to_string(GetPid()) + "-" + ConvertTime("%Y%m%d") + "-" +
to_string(GetNextDiagFileId()) + ".core";
Info(module_type, "dump core to %s.", filepath.c_str());
Coredumper::WriteCoredump(filepath);
Info(module_type, "core dumped.");
}

Abort();
}
Expand Down
2 changes: 1 addition & 1 deletion src/logger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static void Log(const LOG_LEVEL output_level, const char* type,

// time of day
char time_string_ms[64];
char time_string_ms_alinode[64];
char time_string_ms_alinode[128];
time_t tt = time(NULL);
struct tm* ptm = localtime(&tt);
strftime(time_string_ms, sizeof(time_string_ms), "%Y-%m-%d %H:%M:%S", ptm);
Expand Down
3 changes: 3 additions & 0 deletions src/platform/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ void PrintSystemEnv(JSONWriter* writer);
void PrintResourceLimits(JSONWriter* writer);
void PrintLoadedLibraries(JSONWriter* writer);

// coredumper
void WriteCore(std::string filename);

// js binding
void CheckSocketPath(const Nan::FunctionCallbackInfo<v8::Value>& info);
} // namespace xprofiler
Expand Down
Loading

0 comments on commit 0ddefbf

Please sign in to comment.