feat: support crash report
This commit is contained in:
parent
32f570c76f
commit
dfefb68aa6
|
@ -82,6 +82,10 @@ extern bool tsEnableTelem;
|
||||||
extern int32_t tsTelemInterval;
|
extern int32_t tsTelemInterval;
|
||||||
extern char tsTelemServer[];
|
extern char tsTelemServer[];
|
||||||
extern uint16_t tsTelemPort;
|
extern uint16_t tsTelemPort;
|
||||||
|
extern bool tsEnableCrashReport;
|
||||||
|
extern char* tsTelemUri;
|
||||||
|
extern char* tsClientCrashReportUri;
|
||||||
|
extern char* tsSvrCrashReportUri;
|
||||||
|
|
||||||
// query buffer management
|
// query buffer management
|
||||||
extern int32_t tsQueryBufferSize; // maximum allowed usage buffer size in MB for each data node during query processing
|
extern int32_t tsQueryBufferSize; // maximum allowed usage buffer size in MB for each data node during query processing
|
||||||
|
|
|
@ -24,7 +24,7 @@ extern "C" {
|
||||||
|
|
||||||
typedef enum { HTTP_GZIP, HTTP_FLAT } EHttpCompFlag;
|
typedef enum { HTTP_GZIP, HTTP_FLAT } EHttpCompFlag;
|
||||||
|
|
||||||
int32_t taosSendHttpReport(const char* server, uint16_t port, char* pCont, int32_t contLen, EHttpCompFlag flag);
|
int32_t taosSendHttpReport(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen, EHttpCompFlag flag);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,26 +47,46 @@ int32_t taosGetOldTerminalMode();
|
||||||
void taosResetTerminalMode();
|
void taosResetTerminalMode();
|
||||||
|
|
||||||
#if !defined(WINDOWS)
|
#if !defined(WINDOWS)
|
||||||
#define taosPrintTrace(flags, level, dflag) \
|
#define taosLogTraceToBuf(buf, bufSize, ignoreNum) { \
|
||||||
{ \
|
void* array[100]; \
|
||||||
void* array[100]; \
|
int32_t size = backtrace(array, 100); \
|
||||||
int32_t size = backtrace(array, 100); \
|
char** strings = backtrace_symbols(array, size); \
|
||||||
char** strings = backtrace_symbols(array, size); \
|
int32_t offset = 0; \
|
||||||
if (strings != NULL) { \
|
if (strings != NULL) { \
|
||||||
taosPrintLog(flags, level, dflag, "obtained %d stack frames", size); \
|
offset = snprintf(buf, bufSize - 1, "obtained %d stack frames\n", (ignoreNum > 0) ? size - ignoreNum : size); \
|
||||||
for (int32_t i = 0; i < size; i++) { \
|
for (int32_t i = (ignoreNum > 0) ? ignoreNum : 0; i < size; i++) { \
|
||||||
taosPrintLog(flags, level, dflag, "frame:%d, %s", i, strings[i]); \
|
offset += snprintf(buf + offset, bufSize - 1 - offset, "frame:%d, %s\n", (ignoreNum > 0) ? i - ignoreNum : i, strings[i]); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
taosMemoryFree(strings); \
|
taosMemoryFree(strings); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define taosPrintTrace(flags, level, dflag, ignoreNum) \
|
||||||
|
{ \
|
||||||
|
void* array[100]; \
|
||||||
|
int32_t size = backtrace(array, 100); \
|
||||||
|
char** strings = backtrace_symbols(array, size); \
|
||||||
|
if (strings != NULL) { \
|
||||||
|
taosPrintLog(flags, level, dflag, "obtained %d stack frames", (ignoreNum > 0) ? size - ignoreNum : size); \
|
||||||
|
for (int32_t i = (ignoreNum > 0) ? ignoreNum : 0; i < size; i++) { \
|
||||||
|
taosPrintLog(flags, level, dflag, "frame:%d, %s", (ignoreNum > 0) ? i - ignoreNum : i, strings[i]); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
taosMemoryFree(strings); \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define taosPrintTrace(flags, level, dflag) \
|
#define taosLogTraceToBuf(buf, bufSize, ignoreNum) { \
|
||||||
{ \
|
snprintf(buf, bufSize - 1, \
|
||||||
taosPrintLog(flags, level, dflag, \
|
"backtrace not implemented on windows, so detailed stack information cannot be printed"); \
|
||||||
"backtrace not implemented on windows, so detailed stack information cannot be printed"); \
|
}
|
||||||
}
|
|
||||||
|
#define taosPrintTrace(flags, level, dflag, ignoreNum) \
|
||||||
|
{ \
|
||||||
|
taosPrintLog(flags, level, dflag, \
|
||||||
|
"backtrace not implemented on windows, so detailed stack information cannot be printed"); \
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -87,7 +87,10 @@ bool taosAssert(bool condition, const char *file, int32_t line, const char *form
|
||||||
#define ASSERTS(condition, ...) taosAssert(condition, __FILE__, __LINE__, __VA_ARGS__)
|
#define ASSERTS(condition, ...) taosAssert(condition, __FILE__, __LINE__, __VA_ARGS__)
|
||||||
#define ASSERT(condition) ASSERTS(condition, "assert info not provided")
|
#define ASSERT(condition) ASSERTS(condition, "assert info not provided")
|
||||||
|
|
||||||
void taosCrash(int signum, void *sigInfo, void *context);
|
void taosLogCrashInfo(char* nodeType, char* pMsg, int64_t msgLen, int signum, void *sigInfo);
|
||||||
|
void taosReadCrashInfo(char* filepath, char** pMsg, int64_t* pMsgLen, TdFilePtr* pFd);
|
||||||
|
void taosReleaseCrashLogFile(TdFilePtr pFile, bool truncateFile);
|
||||||
|
int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t startTime);
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define uFatal(...) { if (uDebugFlag & DEBUG_FATAL) { taosPrintLog("UTL FATAL", DEBUG_FATAL, tsLogEmbedded ? 255 : uDebugFlag, __VA_ARGS__); }}
|
#define uFatal(...) { if (uDebugFlag & DEBUG_FATAL) { taosPrintLog("UTL FATAL", DEBUG_FATAL, tsLogEmbedded ? 255 : uDebugFlag, __VA_ARGS__); }}
|
||||||
|
|
|
@ -43,6 +43,9 @@
|
||||||
# Switch for allowing TDengine to collect and report service usage information
|
# Switch for allowing TDengine to collect and report service usage information
|
||||||
# telemetryReporting 1
|
# telemetryReporting 1
|
||||||
|
|
||||||
|
# Switch for allowing TDengine to collect and report crash information
|
||||||
|
# crashReporting 1
|
||||||
|
|
||||||
# The maximum number of vnodes supported by this dnode
|
# The maximum number of vnodes supported by this dnode
|
||||||
# supportVnodes 0
|
# supportVnodes 0
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,8 @@ extern SAppInfo appInfo;
|
||||||
extern int32_t clientReqRefPool;
|
extern int32_t clientReqRefPool;
|
||||||
extern int32_t clientConnRefPool;
|
extern int32_t clientConnRefPool;
|
||||||
extern int32_t timestampDeltaLimit;
|
extern int32_t timestampDeltaLimit;
|
||||||
|
extern int64_t lastClusterId;
|
||||||
|
|
||||||
|
|
||||||
__async_send_cb_fn_t getMsgRspHandle(int32_t msgType);
|
__async_send_cb_fn_t getMsgRspHandle(int32_t msgType);
|
||||||
|
|
||||||
|
@ -340,6 +342,7 @@ void resetConnectDB(STscObj* pTscObj);
|
||||||
int taos_options_imp(TSDB_OPTION option, const char* str);
|
int taos_options_imp(TSDB_OPTION option, const char* str);
|
||||||
|
|
||||||
void* openTransporter(const char* user, const char* auth, int32_t numOfThreads);
|
void* openTransporter(const char* user, const char* auth, int32_t numOfThreads);
|
||||||
|
void tscStopCrashReport();
|
||||||
|
|
||||||
typedef struct AsyncArg {
|
typedef struct AsyncArg {
|
||||||
SRpcMsg msg;
|
SRpcMsg msg;
|
||||||
|
|
|
@ -28,13 +28,16 @@
|
||||||
#include "trpc.h"
|
#include "trpc.h"
|
||||||
#include "tsched.h"
|
#include "tsched.h"
|
||||||
#include "ttime.h"
|
#include "ttime.h"
|
||||||
|
#include "thttp.h"
|
||||||
|
|
||||||
#define TSC_VAR_NOT_RELEASE 1
|
#define TSC_VAR_NOT_RELEASE 1
|
||||||
#define TSC_VAR_RELEASED 0
|
#define TSC_VAR_RELEASED 0
|
||||||
|
|
||||||
SAppInfo appInfo;
|
SAppInfo appInfo;
|
||||||
|
int64_t lastClusterId = 0;
|
||||||
int32_t clientReqRefPool = -1;
|
int32_t clientReqRefPool = -1;
|
||||||
int32_t clientConnRefPool = -1;
|
int32_t clientConnRefPool = -1;
|
||||||
|
int32_t clientStop = 0;
|
||||||
|
|
||||||
int32_t timestampDeltaLimit = 900; // s
|
int32_t timestampDeltaLimit = 900; // s
|
||||||
|
|
||||||
|
@ -385,6 +388,128 @@ void destroyRequest(SRequestObj *pRequest) {
|
||||||
removeRequest(pRequest->self);
|
removeRequest(pRequest->self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void taosClientCrash(int signum, void *sigInfo, void *context) {
|
||||||
|
taosIgnSignal(SIGTERM);
|
||||||
|
taosIgnSignal(SIGHUP);
|
||||||
|
taosIgnSignal(SIGINT);
|
||||||
|
taosIgnSignal(SIGBREAK);
|
||||||
|
|
||||||
|
taosIgnSignal(SIGBUS);
|
||||||
|
taosIgnSignal(SIGABRT);
|
||||||
|
taosIgnSignal(SIGFPE);
|
||||||
|
taosIgnSignal(SIGSEGV);
|
||||||
|
|
||||||
|
char *pMsg = NULL;
|
||||||
|
const char *flags = "UTL FATAL ";
|
||||||
|
ELogLevel level = DEBUG_FATAL;
|
||||||
|
int32_t dflag = 255;
|
||||||
|
int64_t msgLen= -1;
|
||||||
|
|
||||||
|
if (tsEnableCrashReport) {
|
||||||
|
if (taosGenCrashJsonMsg(signum, &pMsg, lastClusterId, appInfo.startTime)) {
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to generate crash json msg");
|
||||||
|
goto _return;
|
||||||
|
} else {
|
||||||
|
msgLen = strlen(pMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
taosLogCrashInfo("taos", pMsg, msgLen, signum, sigInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *tscCrashReportThreadFp(void *param) {
|
||||||
|
setThreadName("client-crashReport");
|
||||||
|
char filepath[PATH_MAX] = {0};
|
||||||
|
snprintf(filepath, sizeof(filepath), "%s%s.taosCrashLog", tsLogDir, TD_DIRSEP);
|
||||||
|
char *pMsg = NULL;
|
||||||
|
int64_t msgLen = 0;
|
||||||
|
TdFilePtr pFile = NULL;
|
||||||
|
bool truncateFile = false;
|
||||||
|
int32_t sleepTime = 200;
|
||||||
|
int32_t reportPeriodNum = 3600 * 1000 / sleepTime;
|
||||||
|
int32_t loopTimes = reportPeriodNum;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (clientStop) break;
|
||||||
|
if (loopTimes++ < reportPeriodNum) {
|
||||||
|
taosMsleep(sleepTime);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosReadCrashInfo(filepath, &pMsg, &msgLen, &pFile);
|
||||||
|
if (pMsg && msgLen > 0) {
|
||||||
|
if (taosSendHttpReport(tsTelemServer, tsClientCrashReportUri, tsTelemPort, pMsg, msgLen, HTTP_FLAT) != 0) {
|
||||||
|
tscError("failed to send crash report");
|
||||||
|
if (pFile) {
|
||||||
|
taosReleaseCrashLogFile(pFile, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tscInfo("succeed to send crash report");
|
||||||
|
truncateFile = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tscDebug("no crash info");
|
||||||
|
}
|
||||||
|
|
||||||
|
taosMemoryFree(pMsg);
|
||||||
|
|
||||||
|
if (pMsg && msgLen > 0) {
|
||||||
|
pMsg = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pFile) {
|
||||||
|
taosReleaseCrashLogFile(pFile, truncateFile);
|
||||||
|
truncateFile = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosMsleep(sleepTime);
|
||||||
|
loopTimes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientStop = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tscCrashReportInit() {
|
||||||
|
if (!tsEnableCrashReport) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TdThreadAttr thAttr;
|
||||||
|
taosThreadAttrInit(&thAttr);
|
||||||
|
taosThreadAttrSetDetachState(&thAttr, PTHREAD_CREATE_JOINABLE);
|
||||||
|
TdThread crashReportThread;
|
||||||
|
if (taosThreadCreate(&crashReportThread, &thAttr, tscCrashReportThreadFp, NULL) != 0) {
|
||||||
|
tscError("failed to create crashReport thread since %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosThreadAttrDestroy(&thAttr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tscStopCrashReport() {
|
||||||
|
if (!tsEnableCrashReport) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientStop = 1;
|
||||||
|
while (atomic_load_32(&clientStop) > 0) {
|
||||||
|
taosMsleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tscSetSignalHandle() {
|
||||||
|
taosSetSignal(SIGBUS, taosClientCrash);
|
||||||
|
taosSetSignal(SIGABRT, taosClientCrash);
|
||||||
|
taosSetSignal(SIGFPE, taosClientCrash);
|
||||||
|
taosSetSignal(SIGSEGV, taosClientCrash);
|
||||||
|
}
|
||||||
|
|
||||||
void taos_init_imp(void) {
|
void taos_init_imp(void) {
|
||||||
// In the APIs of other program language, taos_cleanup is not available yet.
|
// In the APIs of other program language, taos_cleanup is not available yet.
|
||||||
// So, to make sure taos_cleanup will be invoked to clean up the allocated resource to suppress the valgrind warning.
|
// So, to make sure taos_cleanup will be invoked to clean up the allocated resource to suppress the valgrind warning.
|
||||||
|
@ -392,6 +517,10 @@ void taos_init_imp(void) {
|
||||||
errno = TSDB_CODE_SUCCESS;
|
errno = TSDB_CODE_SUCCESS;
|
||||||
taosSeedRand(taosGetTimestampSec());
|
taosSeedRand(taosGetTimestampSec());
|
||||||
|
|
||||||
|
appInfo.pid = taosGetPId();
|
||||||
|
appInfo.startTime = taosGetTimestampMs();
|
||||||
|
appInfo.pInstMap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
|
||||||
|
|
||||||
deltaToUtcInitOnce();
|
deltaToUtcInitOnce();
|
||||||
|
|
||||||
if (taosCreateLog("taoslog", 10, configDir, NULL, NULL, NULL, NULL, 1) != 0) {
|
if (taosCreateLog("taoslog", 10, configDir, NULL, NULL, NULL, NULL, 1) != 0) {
|
||||||
|
@ -404,6 +533,8 @@ void taos_init_imp(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tscSetSignalHandle();
|
||||||
|
|
||||||
initQueryModuleMsgHandle();
|
initQueryModuleMsgHandle();
|
||||||
|
|
||||||
if (taosConvInit() != 0) {
|
if (taosConvInit() != 0) {
|
||||||
|
@ -433,9 +564,8 @@ void taos_init_imp(void) {
|
||||||
taosGetAppName(appInfo.appName, NULL);
|
taosGetAppName(appInfo.appName, NULL);
|
||||||
taosThreadMutexInit(&appInfo.mutex, NULL);
|
taosThreadMutexInit(&appInfo.mutex, NULL);
|
||||||
|
|
||||||
appInfo.pid = taosGetPId();
|
tscCrashReportInit();
|
||||||
appInfo.startTime = taosGetTimestampMs();
|
|
||||||
appInfo.pInstMap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
|
|
||||||
tscDebug("client is initialized successfully");
|
tscDebug("client is initialized successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ void taos_cleanup(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tscStopCrashReport();
|
||||||
|
|
||||||
int32_t id = clientReqRefPool;
|
int32_t id = clientReqRefPool;
|
||||||
clientReqRefPool = -1;
|
clientReqRefPool = -1;
|
||||||
taosCloseRef(id);
|
taosCloseRef(id);
|
||||||
|
|
|
@ -119,6 +119,7 @@ int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) {
|
||||||
|
|
||||||
// update the appInstInfo
|
// update the appInstInfo
|
||||||
pTscObj->pAppInfo->clusterId = connectRsp.clusterId;
|
pTscObj->pAppInfo->clusterId = connectRsp.clusterId;
|
||||||
|
lastClusterId = connectRsp.clusterId;
|
||||||
|
|
||||||
pTscObj->connType = connectRsp.connType;
|
pTscObj->connType = connectRsp.connType;
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,11 @@ bool tsEnableTelem = true;
|
||||||
int32_t tsTelemInterval = 43200;
|
int32_t tsTelemInterval = 43200;
|
||||||
char tsTelemServer[TSDB_FQDN_LEN] = "telemetry.taosdata.com";
|
char tsTelemServer[TSDB_FQDN_LEN] = "telemetry.taosdata.com";
|
||||||
uint16_t tsTelemPort = 80;
|
uint16_t tsTelemPort = 80;
|
||||||
|
char* tsTelemUri = "/report";
|
||||||
|
|
||||||
|
bool tsEnableCrashReport = true;
|
||||||
|
char* tsClientCrashReportUri = "/ccrashreport";
|
||||||
|
char* tsSvrCrashReportUri = "/dcrashreport";
|
||||||
|
|
||||||
// schemaless
|
// schemaless
|
||||||
char tsSmlTagName[TSDB_COL_NAME_LEN] = "_tag_null";
|
char tsSmlTagName[TSDB_COL_NAME_LEN] = "_tag_null";
|
||||||
|
@ -314,6 +319,7 @@ static int32_t taosAddClientCfg(SConfig *pCfg) {
|
||||||
if (cfgAddInt32(pCfg, "maxMemUsedByInsert", tsMaxMemUsedByInsert, 1, INT32_MAX, true) != 0) return -1;
|
if (cfgAddInt32(pCfg, "maxMemUsedByInsert", tsMaxMemUsedByInsert, 1, INT32_MAX, true) != 0) return -1;
|
||||||
if (cfgAddInt32(pCfg, "maxRetryWaitTime", tsMaxRetryWaitTime, 0, 86400000, 0) != 0) return -1;
|
if (cfgAddInt32(pCfg, "maxRetryWaitTime", tsMaxRetryWaitTime, 0, 86400000, 0) != 0) return -1;
|
||||||
if (cfgAddBool(pCfg, "useAdapter", tsUseAdapter, true) != 0) return -1;
|
if (cfgAddBool(pCfg, "useAdapter", tsUseAdapter, true) != 0) return -1;
|
||||||
|
if (cfgAddBool(pCfg, "crashReporting", tsEnableCrashReport, true) != 0) return -1;
|
||||||
|
|
||||||
tsNumOfTaskQueueThreads = tsNumOfCores / 2;
|
tsNumOfTaskQueueThreads = tsNumOfCores / 2;
|
||||||
tsNumOfTaskQueueThreads = TMAX(tsNumOfTaskQueueThreads, 4);
|
tsNumOfTaskQueueThreads = TMAX(tsNumOfTaskQueueThreads, 4);
|
||||||
|
@ -436,6 +442,7 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
||||||
if (cfgAddInt32(pCfg, "monitorMaxLogs", tsMonitorMaxLogs, 1, 1000000, 0) != 0) return -1;
|
if (cfgAddInt32(pCfg, "monitorMaxLogs", tsMonitorMaxLogs, 1, 1000000, 0) != 0) return -1;
|
||||||
if (cfgAddBool(pCfg, "monitorComp", tsMonitorComp, 0) != 0) return -1;
|
if (cfgAddBool(pCfg, "monitorComp", tsMonitorComp, 0) != 0) return -1;
|
||||||
|
|
||||||
|
if (cfgAddBool(pCfg, "crashReporting", tsEnableCrashReport, 0) != 0) return -1;
|
||||||
if (cfgAddBool(pCfg, "telemetryReporting", tsEnableTelem, 0) != 0) return -1;
|
if (cfgAddBool(pCfg, "telemetryReporting", tsEnableTelem, 0) != 0) return -1;
|
||||||
if (cfgAddInt32(pCfg, "telemetryInterval", tsTelemInterval, 1, 200000, 0) != 0) return -1;
|
if (cfgAddInt32(pCfg, "telemetryInterval", tsTelemInterval, 1, 200000, 0) != 0) return -1;
|
||||||
if (cfgAddString(pCfg, "telemetryServer", tsTelemServer, 0) != 0) return -1;
|
if (cfgAddString(pCfg, "telemetryServer", tsTelemServer, 0) != 0) return -1;
|
||||||
|
@ -669,6 +676,7 @@ static int32_t taosSetClientCfg(SConfig *pCfg) {
|
||||||
tsQueryUseNodeAllocator = cfgGetItem(pCfg, "queryUseNodeAllocator")->bval;
|
tsQueryUseNodeAllocator = cfgGetItem(pCfg, "queryUseNodeAllocator")->bval;
|
||||||
tsKeepColumnName = cfgGetItem(pCfg, "keepColumnName")->bval;
|
tsKeepColumnName = cfgGetItem(pCfg, "keepColumnName")->bval;
|
||||||
tsUseAdapter = cfgGetItem(pCfg, "useAdapter")->bval;
|
tsUseAdapter = cfgGetItem(pCfg, "useAdapter")->bval;
|
||||||
|
tsEnableCrashReport = cfgGetItem(pCfg, "crashReporting")->bval;
|
||||||
|
|
||||||
tsMaxRetryWaitTime = cfgGetItem(pCfg, "maxRetryWaitTime")->i32;
|
tsMaxRetryWaitTime = cfgGetItem(pCfg, "maxRetryWaitTime")->i32;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -728,6 +736,7 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
|
||||||
tsQueryRspPolicy = cfgGetItem(pCfg, "queryRspPolicy")->i32;
|
tsQueryRspPolicy = cfgGetItem(pCfg, "queryRspPolicy")->i32;
|
||||||
|
|
||||||
tsEnableTelem = cfgGetItem(pCfg, "telemetryReporting")->bval;
|
tsEnableTelem = cfgGetItem(pCfg, "telemetryReporting")->bval;
|
||||||
|
tsEnableCrashReport = cfgGetItem(pCfg, "crashReporting")->bval;
|
||||||
tsTelemInterval = cfgGetItem(pCfg, "telemetryInterval")->i32;
|
tsTelemInterval = cfgGetItem(pCfg, "telemetryInterval")->i32;
|
||||||
tstrncpy(tsTelemServer, cfgGetItem(pCfg, "telemetryServer")->str, TSDB_FQDN_LEN);
|
tstrncpy(tsTelemServer, cfgGetItem(pCfg, "telemetryServer")->str, TSDB_FQDN_LEN);
|
||||||
tsTelemPort = (uint16_t)cfgGetItem(pCfg, "telemetryPort")->i32;
|
tsTelemPort = (uint16_t)cfgGetItem(pCfg, "telemetryPort")->i32;
|
||||||
|
@ -797,6 +806,8 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
|
||||||
tsCountAlwaysReturnValue = cfgGetItem(pCfg, "countAlwaysReturnValue")->i32;
|
tsCountAlwaysReturnValue = cfgGetItem(pCfg, "countAlwaysReturnValue")->i32;
|
||||||
} else if (strcasecmp("cDebugFlag", name) == 0) {
|
} else if (strcasecmp("cDebugFlag", name) == 0) {
|
||||||
cDebugFlag = cfgGetItem(pCfg, "cDebugFlag")->i32;
|
cDebugFlag = cfgGetItem(pCfg, "cDebugFlag")->i32;
|
||||||
|
} else if (strcasecmp("crashReporting", name) == 0) {
|
||||||
|
tsEnableCrashReport = cfgGetItem(pCfg, "crashReporting")->bval;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ static struct {
|
||||||
char apolloUrl[PATH_MAX];
|
char apolloUrl[PATH_MAX];
|
||||||
const char **envCmd;
|
const char **envCmd;
|
||||||
SArray *pArgs; // SConfigPair
|
SArray *pArgs; // SConfigPair
|
||||||
|
int64_t startTime;
|
||||||
} global = {0};
|
} global = {0};
|
||||||
|
|
||||||
static void dmSetDebugFlag(int32_t signum, void *sigInfo, void *context) { taosSetAllDebugFlag(143, true); }
|
static void dmSetDebugFlag(int32_t signum, void *sigInfo, void *context) { taosSetAllDebugFlag(143, true); }
|
||||||
|
@ -67,6 +68,37 @@ static void dmStopDnode(int signum, void *sigInfo, void *context) {
|
||||||
dmStop();
|
dmStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dmLogCrash(int signum, void *sigInfo, void *context) {
|
||||||
|
taosIgnSignal(SIGTERM);
|
||||||
|
taosIgnSignal(SIGHUP);
|
||||||
|
taosIgnSignal(SIGINT);
|
||||||
|
taosIgnSignal(SIGBREAK);
|
||||||
|
|
||||||
|
taosIgnSignal(SIGBUS);
|
||||||
|
taosIgnSignal(SIGABRT);
|
||||||
|
taosIgnSignal(SIGFPE);
|
||||||
|
taosIgnSignal(SIGSEGV);
|
||||||
|
|
||||||
|
char *pMsg = NULL;
|
||||||
|
const char *flags = "UTL FATAL ";
|
||||||
|
ELogLevel level = DEBUG_FATAL;
|
||||||
|
int32_t dflag = 255;
|
||||||
|
int64_t msgLen= -1;
|
||||||
|
|
||||||
|
if (tsEnableCrashReport) {
|
||||||
|
if (taosGenCrashJsonMsg(signum, &pMsg, dmGetClusterId(), global.startTime)) {
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to generate crash json msg");
|
||||||
|
goto _return;
|
||||||
|
} else {
|
||||||
|
msgLen = strlen(pMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
taosLogCrashInfo("taosd", pMsg, msgLen, signum, sigInfo);
|
||||||
|
}
|
||||||
|
|
||||||
static void dmSetSignalHandle() {
|
static void dmSetSignalHandle() {
|
||||||
taosSetSignal(SIGUSR1, dmSetDebugFlag);
|
taosSetSignal(SIGUSR1, dmSetDebugFlag);
|
||||||
taosSetSignal(SIGUSR2, dmSetAssert);
|
taosSetSignal(SIGUSR2, dmSetAssert);
|
||||||
|
@ -79,15 +111,18 @@ static void dmSetSignalHandle() {
|
||||||
taosSetSignal(SIGQUIT, dmStopDnode);
|
taosSetSignal(SIGQUIT, dmStopDnode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
taosSetSignal(SIGBUS, taosCrash);
|
taosSetSignal(SIGBUS, dmLogCrash);
|
||||||
taosSetSignal(SIGABRT, taosCrash);
|
taosSetSignal(SIGABRT, dmLogCrash);
|
||||||
taosSetSignal(SIGFPE, taosCrash);
|
taosSetSignal(SIGFPE, dmLogCrash);
|
||||||
taosSetSignal(SIGSEGV, taosCrash);
|
taosSetSignal(SIGSEGV, dmLogCrash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t dmParseArgs(int32_t argc, char const *argv[]) {
|
static int32_t dmParseArgs(int32_t argc, char const *argv[]) {
|
||||||
|
global.startTime = taosGetTimestampMs();
|
||||||
|
|
||||||
int32_t cmdEnvIndex = 0;
|
int32_t cmdEnvIndex = 0;
|
||||||
if (argc < 2) return 0;
|
if (argc < 2) return 0;
|
||||||
|
|
||||||
global.envCmd = taosMemoryMalloc((argc - 1) * sizeof(char *));
|
global.envCmd = taosMemoryMalloc((argc - 1) * sizeof(char *));
|
||||||
memset(global.envCmd, 0, (argc - 1) * sizeof(char *));
|
memset(global.envCmd, 0, (argc - 1) * sizeof(char *));
|
||||||
for (int32_t i = 1; i < argc; ++i) {
|
for (int32_t i = 1; i < argc; ++i) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ typedef struct SDnodeMgmt {
|
||||||
const char *name;
|
const char *name;
|
||||||
TdThread statusThread;
|
TdThread statusThread;
|
||||||
TdThread monitorThread;
|
TdThread monitorThread;
|
||||||
|
TdThread crashReportThread;
|
||||||
SSingleWorker mgmtWorker;
|
SSingleWorker mgmtWorker;
|
||||||
ProcessCreateNodeFp processCreateNodeFp;
|
ProcessCreateNodeFp processCreateNodeFp;
|
||||||
ProcessDropNodeFp processDropNodeFp;
|
ProcessDropNodeFp processDropNodeFp;
|
||||||
|
@ -55,6 +56,8 @@ int32_t dmStartStatusThread(SDnodeMgmt *pMgmt);
|
||||||
void dmStopStatusThread(SDnodeMgmt *pMgmt);
|
void dmStopStatusThread(SDnodeMgmt *pMgmt);
|
||||||
int32_t dmStartMonitorThread(SDnodeMgmt *pMgmt);
|
int32_t dmStartMonitorThread(SDnodeMgmt *pMgmt);
|
||||||
void dmStopMonitorThread(SDnodeMgmt *pMgmt);
|
void dmStopMonitorThread(SDnodeMgmt *pMgmt);
|
||||||
|
int32_t dmStartCrashReportThread(SDnodeMgmt *pMgmt);
|
||||||
|
void dmStopCrashReportThread(SDnodeMgmt *pMgmt);
|
||||||
int32_t dmStartWorker(SDnodeMgmt *pMgmt);
|
int32_t dmStartWorker(SDnodeMgmt *pMgmt);
|
||||||
void dmStopWorker(SDnodeMgmt *pMgmt);
|
void dmStopWorker(SDnodeMgmt *pMgmt);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@ static int32_t dmStartMgmt(SDnodeMgmt *pMgmt) {
|
||||||
if (dmStartMonitorThread(pMgmt) != 0) {
|
if (dmStartMonitorThread(pMgmt) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (dmStartCrashReportThread(pMgmt) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +33,7 @@ static void dmStopMgmt(SDnodeMgmt *pMgmt) {
|
||||||
pMgmt->pData->stopped = true;
|
pMgmt->pData->stopped = true;
|
||||||
dmStopMonitorThread(pMgmt);
|
dmStopMonitorThread(pMgmt);
|
||||||
dmStopStatusThread(pMgmt);
|
dmStopStatusThread(pMgmt);
|
||||||
|
dmStopCrashReportThread(pMgmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t dmOpenMgmt(SMgmtInputOpt *pInput, SMgmtOutputOpt *pOutput) {
|
static int32_t dmOpenMgmt(SMgmtInputOpt *pInput, SMgmtOutputOpt *pOutput) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#define _DEFAULT_SOURCE
|
#define _DEFAULT_SOURCE
|
||||||
#include "dmInt.h"
|
#include "dmInt.h"
|
||||||
|
#include "thttp.h"
|
||||||
|
|
||||||
static void *dmStatusThreadFp(void *param) {
|
static void *dmStatusThreadFp(void *param) {
|
||||||
SDnodeMgmt *pMgmt = param;
|
SDnodeMgmt *pMgmt = param;
|
||||||
|
@ -63,6 +64,63 @@ static void *dmMonitorThreadFp(void *param) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *dmCrashReportThreadFp(void *param) {
|
||||||
|
SDnodeMgmt *pMgmt = param;
|
||||||
|
int64_t lastTime = taosGetTimestampMs();
|
||||||
|
setThreadName("dnode-crashReport");
|
||||||
|
char filepath[PATH_MAX] = {0};
|
||||||
|
snprintf(filepath, sizeof(filepath), "%s%s.taosdCrashLog", tsLogDir, TD_DIRSEP);
|
||||||
|
char *pMsg = NULL;
|
||||||
|
int64_t msgLen = 0;
|
||||||
|
TdFilePtr pFile = NULL;
|
||||||
|
bool truncateFile = false;
|
||||||
|
int32_t sleepTime = 200;
|
||||||
|
int32_t reportPeriodNum = 3600 * 1000 / sleepTime;;
|
||||||
|
int32_t loopTimes = reportPeriodNum;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (pMgmt->pData->dropped || pMgmt->pData->stopped) break;
|
||||||
|
if (loopTimes++ < reportPeriodNum) {
|
||||||
|
taosMsleep(sleepTime);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosReadCrashInfo(filepath, &pMsg, &msgLen, &pFile);
|
||||||
|
if (pMsg && msgLen > 0) {
|
||||||
|
if (taosSendHttpReport(tsTelemServer, tsSvrCrashReportUri, tsTelemPort, pMsg, msgLen, HTTP_FLAT) != 0) {
|
||||||
|
dError("failed to send crash report");
|
||||||
|
if (pFile) {
|
||||||
|
taosReleaseCrashLogFile(pFile, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dInfo("succeed to send crash report");
|
||||||
|
truncateFile = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dDebug("no crash info");
|
||||||
|
}
|
||||||
|
|
||||||
|
taosMemoryFree(pMsg);
|
||||||
|
|
||||||
|
if (pMsg && msgLen > 0) {
|
||||||
|
pMsg = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pFile) {
|
||||||
|
taosReleaseCrashLogFile(pFile, truncateFile);
|
||||||
|
truncateFile = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosMsleep(sleepTime);
|
||||||
|
loopTimes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int32_t dmStartStatusThread(SDnodeMgmt *pMgmt) {
|
int32_t dmStartStatusThread(SDnodeMgmt *pMgmt) {
|
||||||
TdThreadAttr thAttr;
|
TdThreadAttr thAttr;
|
||||||
taosThreadAttrInit(&thAttr);
|
taosThreadAttrInit(&thAttr);
|
||||||
|
@ -105,6 +163,36 @@ void dmStopMonitorThread(SDnodeMgmt *pMgmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t dmStartCrashReportThread(SDnodeMgmt *pMgmt) {
|
||||||
|
if (!tsEnableCrashReport) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TdThreadAttr thAttr;
|
||||||
|
taosThreadAttrInit(&thAttr);
|
||||||
|
taosThreadAttrSetDetachState(&thAttr, PTHREAD_CREATE_JOINABLE);
|
||||||
|
if (taosThreadCreate(&pMgmt->crashReportThread, &thAttr, dmCrashReportThreadFp, pMgmt) != 0) {
|
||||||
|
dError("failed to create crashReport thread since %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosThreadAttrDestroy(&thAttr);
|
||||||
|
tmsgReportStartup("dnode-crashReport", "initialized");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dmStopCrashReportThread(SDnodeMgmt *pMgmt) {
|
||||||
|
if (!tsEnableCrashReport) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taosCheckPthreadValid(pMgmt->crashReportThread)) {
|
||||||
|
taosThreadJoin(pMgmt->crashReportThread, NULL);
|
||||||
|
taosThreadClear(&pMgmt->crashReportThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
static void dmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) {
|
||||||
SDnodeMgmt *pMgmt = pInfo->ahandle;
|
SDnodeMgmt *pMgmt = pInfo->ahandle;
|
||||||
int32_t code = -1;
|
int32_t code = -1;
|
||||||
|
|
|
@ -85,6 +85,7 @@ typedef struct SDnode {
|
||||||
// dmEnv.c
|
// dmEnv.c
|
||||||
SDnode *dmInstance();
|
SDnode *dmInstance();
|
||||||
void dmReportStartup(const char *pName, const char *pDesc);
|
void dmReportStartup(const char *pName, const char *pDesc);
|
||||||
|
int64_t dmGetClusterId();
|
||||||
|
|
||||||
// dmMgmt.c
|
// dmMgmt.c
|
||||||
int32_t dmInitDnode(SDnode *pDnode);
|
int32_t dmInitDnode(SDnode *pDnode);
|
||||||
|
|
|
@ -268,3 +268,8 @@ void dmReportStartup(const char *pName, const char *pDesc) {
|
||||||
tstrncpy(pStartup->desc, pDesc, TSDB_STEP_DESC_LEN);
|
tstrncpy(pStartup->desc, pDesc, TSDB_STEP_DESC_LEN);
|
||||||
dDebug("step:%s, %s", pStartup->name, pStartup->desc);
|
dDebug("step:%s, %s", pStartup->name, pStartup->desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t dmGetClusterId() {
|
||||||
|
return global.data.clusterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,7 @@ static int32_t dmStartNodes(SDnode *pDnode) {
|
||||||
|
|
||||||
dInfo("TDengine initialized successfully");
|
dInfo("TDengine initialized successfully");
|
||||||
dmReportStartup("TDengine", "initialized successfully");
|
dmReportStartup("TDengine", "initialized successfully");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ static int32_t mndProcessTelemTimer(SRpcMsg* pReq) {
|
||||||
taosThreadMutexUnlock(&pMgmt->lock);
|
taosThreadMutexUnlock(&pMgmt->lock);
|
||||||
|
|
||||||
if (pCont != NULL) {
|
if (pCont != NULL) {
|
||||||
if (taosSendHttpReport(tsTelemServer, tsTelemPort, pCont, strlen(pCont), HTTP_FLAT) != 0) {
|
if (taosSendHttpReport(tsTelemServer, tsTelemUri, tsTelemPort, pCont, strlen(pCont), HTTP_FLAT) != 0) {
|
||||||
mError("failed to send telemetry report");
|
mError("failed to send telemetry report");
|
||||||
} else {
|
} else {
|
||||||
mInfo("succeed to send telemetry report");
|
mInfo("succeed to send telemetry report");
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "ttime.h"
|
#include "ttime.h"
|
||||||
|
|
||||||
static SMonitor tsMonitor = {0};
|
static SMonitor tsMonitor = {0};
|
||||||
|
static char* tsMonUri = "/report";
|
||||||
|
|
||||||
void monRecordLog(int64_t ts, ELogLevel level, const char *content) {
|
void monRecordLog(int64_t ts, ELogLevel level, const char *content) {
|
||||||
taosThreadMutexLock(&tsMonitor.lock);
|
taosThreadMutexLock(&tsMonitor.lock);
|
||||||
|
@ -550,7 +551,7 @@ void monSendReport() {
|
||||||
// uDebugL("report cont:%s\n", pCont);
|
// uDebugL("report cont:%s\n", pCont);
|
||||||
if (pCont != NULL) {
|
if (pCont != NULL) {
|
||||||
EHttpCompFlag flag = tsMonitor.cfg.comp ? HTTP_GZIP : HTTP_FLAT;
|
EHttpCompFlag flag = tsMonitor.cfg.comp ? HTTP_GZIP : HTTP_FLAT;
|
||||||
if (taosSendHttpReport(tsMonitor.cfg.server, tsMonitor.cfg.port, pCont, strlen(pCont), flag) != 0) {
|
if (taosSendHttpReport(tsMonitor.cfg.server, tsMonUri, tsMonitor.cfg.port, pCont, strlen(pCont), flag) != 0) {
|
||||||
uError("failed to send monitor msg");
|
uError("failed to send monitor msg");
|
||||||
}
|
}
|
||||||
taosMemoryFree(pCont);
|
taosMemoryFree(pCont);
|
||||||
|
|
|
@ -35,6 +35,7 @@ typedef struct SHttpModule {
|
||||||
typedef struct SHttpMsg {
|
typedef struct SHttpMsg {
|
||||||
queue q;
|
queue q;
|
||||||
char* server;
|
char* server;
|
||||||
|
char* uri;
|
||||||
int32_t port;
|
int32_t port;
|
||||||
char* cont;
|
char* cont;
|
||||||
int32_t len;
|
int32_t len;
|
||||||
|
@ -63,26 +64,26 @@ static void httpHandleReq(SHttpMsg* msg);
|
||||||
static void httpHandleQuit(SHttpMsg* msg);
|
static void httpHandleQuit(SHttpMsg* msg);
|
||||||
static int32_t httpSendQuit();
|
static int32_t httpSendQuit();
|
||||||
|
|
||||||
static int32_t taosSendHttpReportImpl(const char* server, uint16_t port, char* pCont, int32_t contLen,
|
static int32_t taosSendHttpReportImpl(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen,
|
||||||
EHttpCompFlag flag);
|
EHttpCompFlag flag);
|
||||||
|
|
||||||
static int32_t taosBuildHttpHeader(const char* server, int32_t contLen, char* pHead, int32_t headLen,
|
static int32_t taosBuildHttpHeader(const char* server, const char* uri, int32_t contLen, char* pHead, int32_t headLen,
|
||||||
EHttpCompFlag flag) {
|
EHttpCompFlag flag) {
|
||||||
if (flag == HTTP_FLAT) {
|
if (flag == HTTP_FLAT) {
|
||||||
return snprintf(pHead, headLen,
|
return snprintf(pHead, headLen,
|
||||||
"POST /report HTTP/1.1\n"
|
"POST %s HTTP/1.1\n"
|
||||||
"Host: %s\n"
|
"Host: %s\n"
|
||||||
"Content-Type: application/json\n"
|
"Content-Type: application/json\n"
|
||||||
"Content-Length: %d\n\n",
|
"Content-Length: %d\n\n",
|
||||||
server, contLen);
|
uri, server, contLen);
|
||||||
} else if (flag == HTTP_GZIP) {
|
} else if (flag == HTTP_GZIP) {
|
||||||
return snprintf(pHead, headLen,
|
return snprintf(pHead, headLen,
|
||||||
"POST /report HTTP/1.1\n"
|
"POST %s HTTP/1.1\n"
|
||||||
"Host: %s\n"
|
"Host: %s\n"
|
||||||
"Content-Type: application/json\n"
|
"Content-Type: application/json\n"
|
||||||
"Content-Encoding: gzip\n"
|
"Content-Encoding: gzip\n"
|
||||||
"Content-Length: %d\n\n",
|
"Content-Length: %d\n\n",
|
||||||
server, contLen);
|
uri, server, contLen);
|
||||||
} else {
|
} else {
|
||||||
terrno = TSDB_CODE_INVALID_CFG;
|
terrno = TSDB_CODE_INVALID_CFG;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -181,6 +182,7 @@ static void httpDestroyMsg(SHttpMsg* msg) {
|
||||||
if (msg == NULL) return;
|
if (msg == NULL) return;
|
||||||
|
|
||||||
taosMemoryFree(msg->server);
|
taosMemoryFree(msg->server);
|
||||||
|
taosMemoryFree(msg->uri);
|
||||||
taosMemoryFree(msg->cont);
|
taosMemoryFree(msg->cont);
|
||||||
taosMemoryFree(msg);
|
taosMemoryFree(msg);
|
||||||
}
|
}
|
||||||
|
@ -293,10 +295,11 @@ int32_t httpSendQuit() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t taosSendHttpReportImpl(const char* server, uint16_t port, char* pCont, int32_t contLen,
|
static int32_t taosSendHttpReportImpl(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen,
|
||||||
EHttpCompFlag flag) {
|
EHttpCompFlag flag) {
|
||||||
SHttpMsg* msg = taosMemoryMalloc(sizeof(SHttpMsg));
|
SHttpMsg* msg = taosMemoryMalloc(sizeof(SHttpMsg));
|
||||||
msg->server = strdup(server);
|
msg->server = strdup(server);
|
||||||
|
msg->uri = strdup(uri);
|
||||||
msg->port = port;
|
msg->port = port;
|
||||||
msg->cont = taosMemoryMalloc(contLen);
|
msg->cont = taosMemoryMalloc(contLen);
|
||||||
memcpy(msg->cont, pCont, contLen);
|
memcpy(msg->cont, pCont, contLen);
|
||||||
|
@ -309,12 +312,10 @@ static int32_t taosSendHttpReportImpl(const char* server, uint16_t port, char* p
|
||||||
httpDestroyMsg(msg);
|
httpDestroyMsg(msg);
|
||||||
tError("http-report already released");
|
tError("http-report already released");
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
|
||||||
msg->http = load;
|
|
||||||
transAsyncSend(load->asyncPool, &(msg->q));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
msg->http = load;
|
||||||
|
return transAsyncSend(load->asyncPool, &(msg->q));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void httpDestroyClientCb(uv_handle_t* handle) {
|
static void httpDestroyClientCb(uv_handle_t* handle) {
|
||||||
|
@ -360,7 +361,7 @@ static void httpHandleReq(SHttpMsg* msg) {
|
||||||
|
|
||||||
int32_t len = 2048;
|
int32_t len = 2048;
|
||||||
char* header = taosMemoryCalloc(1, len);
|
char* header = taosMemoryCalloc(1, len);
|
||||||
int32_t headLen = taosBuildHttpHeader(msg->server, msg->len, header, len, msg->flag);
|
int32_t headLen = taosBuildHttpHeader(msg->server, msg->uri, msg->len, header, len, msg->flag);
|
||||||
if (headLen < 0) {
|
if (headLen < 0) {
|
||||||
taosMemoryFree(header);
|
taosMemoryFree(header);
|
||||||
goto END;
|
goto END;
|
||||||
|
@ -380,6 +381,7 @@ static void httpHandleReq(SHttpMsg* msg) {
|
||||||
cli->port = msg->port;
|
cli->port = msg->port;
|
||||||
cli->dest = dest;
|
cli->dest = dest;
|
||||||
|
|
||||||
|
taosMemoryFree(msg->uri);
|
||||||
taosMemoryFree(msg);
|
taosMemoryFree(msg);
|
||||||
|
|
||||||
uv_tcp_init(http->loop, &cli->tcp);
|
uv_tcp_init(http->loop, &cli->tcp);
|
||||||
|
@ -406,9 +408,9 @@ END:
|
||||||
httpDestroyMsg(msg);
|
httpDestroyMsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t taosSendHttpReport(const char* server, uint16_t port, char* pCont, int32_t contLen, EHttpCompFlag flag) {
|
int32_t taosSendHttpReport(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen, EHttpCompFlag flag) {
|
||||||
taosThreadOnce(&transHttpInit, transHttpEnvInit);
|
taosThreadOnce(&transHttpInit, transHttpEnvInit);
|
||||||
return taosSendHttpReportImpl(server, port, pCont, contLen, flag);
|
return taosSendHttpReportImpl(server, uri, port, pCont, contLen, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void transHttpEnvInit() {
|
static void transHttpEnvInit() {
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "tconfig.h"
|
#include "tconfig.h"
|
||||||
#include "tutil.h"
|
#include "tutil.h"
|
||||||
|
#include "tjson.h"
|
||||||
|
#include "tglobal.h"
|
||||||
|
|
||||||
#define LOG_MAX_LINE_SIZE (1024)
|
#define LOG_MAX_LINE_SIZE (1024)
|
||||||
#define LOG_MAX_LINE_BUFFER_SIZE (LOG_MAX_LINE_SIZE + 3)
|
#define LOG_MAX_LINE_BUFFER_SIZE (LOG_MAX_LINE_SIZE + 3)
|
||||||
|
@ -808,7 +810,7 @@ bool taosAssert(bool condition, const char *file, int32_t line, const char *form
|
||||||
taosPrintLogImp(1, 255, buffer, len);
|
taosPrintLogImp(1, 255, buffer, len);
|
||||||
|
|
||||||
taosPrintLog(flags, level, dflag, "tAssert at file %s:%d exit:%d", file, line, tsAssert);
|
taosPrintLog(flags, level, dflag, "tAssert at file %s:%d exit:%d", file, line, tsAssert);
|
||||||
taosPrintTrace(flags, level, dflag);
|
taosPrintTrace(flags, level, dflag, -1);
|
||||||
|
|
||||||
if (tsAssert) {
|
if (tsAssert) {
|
||||||
// taosCloseLog();
|
// taosCloseLog();
|
||||||
|
@ -824,21 +826,100 @@ bool taosAssert(bool condition, const char *file, int32_t line, const char *form
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void taosCrash(int signum, void *sigInfo, void *context) {
|
int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t startTime) {
|
||||||
taosIgnSignal(SIGTERM);
|
SJson* pJson = tjsonCreateObject();
|
||||||
taosIgnSignal(SIGHUP);
|
if (pJson == NULL) return -1;
|
||||||
taosIgnSignal(SIGINT);
|
char tmp[4096] = {0};
|
||||||
taosIgnSignal(SIGBREAK);
|
|
||||||
|
|
||||||
taosIgnSignal(SIGBUS);
|
tjsonAddDoubleToObject(pJson, "reportVersion", 1);
|
||||||
taosIgnSignal(SIGABRT);
|
|
||||||
taosIgnSignal(SIGFPE);
|
|
||||||
taosIgnSignal(SIGSEGV);
|
|
||||||
|
|
||||||
|
tjsonAddIntegerToObject(pJson, "clusterId", clusterId);
|
||||||
|
tjsonAddIntegerToObject(pJson, "startTime", startTime);
|
||||||
|
|
||||||
|
taosGetFqdn(tmp);
|
||||||
|
tjsonAddStringToObject(pJson, "fqdn", tmp);
|
||||||
|
|
||||||
|
tjsonAddIntegerToObject(pJson, "pid", taosGetPId());
|
||||||
|
|
||||||
|
taosGetAppName(tmp, NULL);
|
||||||
|
tjsonAddStringToObject(pJson, "appName", tmp);
|
||||||
|
|
||||||
|
if (taosGetOsReleaseName(tmp, sizeof(tmp)) == 0) {
|
||||||
|
tjsonAddStringToObject(pJson, "os", tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
float numOfCores = 0;
|
||||||
|
if (taosGetCpuInfo(tmp, sizeof(tmp), &numOfCores) == 0) {
|
||||||
|
tjsonAddStringToObject(pJson, "cpuModel", tmp);
|
||||||
|
tjsonAddDoubleToObject(pJson, "numOfCpu", numOfCores);
|
||||||
|
} else {
|
||||||
|
tjsonAddDoubleToObject(pJson, "numOfCpu", tsNumOfCores);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(tmp, sizeof(tmp), "%" PRId64 " kB", tsTotalMemoryKB);
|
||||||
|
tjsonAddStringToObject(pJson, "memory", tmp);
|
||||||
|
|
||||||
|
tjsonAddStringToObject(pJson, "version", version);
|
||||||
|
tjsonAddStringToObject(pJson, "buildInfo", buildinfo);
|
||||||
|
tjsonAddStringToObject(pJson, "gitInfo", gitinfo);
|
||||||
|
|
||||||
|
tjsonAddIntegerToObject(pJson, "crashSig", signum);
|
||||||
|
tjsonAddIntegerToObject(pJson, "crashTs", taosGetTimestampUs());
|
||||||
|
|
||||||
|
taosLogTraceToBuf(tmp, sizeof(tmp), 3);
|
||||||
|
tjsonAddStringToObject(pJson, "stackInfo", tmp);
|
||||||
|
|
||||||
|
char* pCont = tjsonToString(pJson);
|
||||||
|
tjsonDelete(pJson);
|
||||||
|
|
||||||
|
*pMsg = pCont;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void taosLogCrashInfo(char* nodeType, char* pMsg, int64_t msgLen, int signum, void *sigInfo) {
|
||||||
const char *flags = "UTL FATAL ";
|
const char *flags = "UTL FATAL ";
|
||||||
ELogLevel level = DEBUG_FATAL;
|
ELogLevel level = DEBUG_FATAL;
|
||||||
int32_t dflag = 255;
|
int32_t dflag = 255;
|
||||||
|
char filepath[PATH_MAX] = {0};
|
||||||
|
TdFilePtr pFile = NULL;
|
||||||
|
|
||||||
|
if (pMsg && msgLen > 0) {
|
||||||
|
snprintf(filepath, sizeof(filepath), "%s%s.%sCrashLog", tsLogDir, TD_DIRSEP, nodeType);
|
||||||
|
|
||||||
|
pFile = taosOpenFile(filepath, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
|
||||||
|
if (pFile == NULL) {
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to open file:%s since %s", filepath, terrstr());
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosLockFile(pFile);
|
||||||
|
|
||||||
|
int64_t writeSize = taosWriteFile(pFile, &msgLen, sizeof(msgLen));
|
||||||
|
if (sizeof(msgLen) != writeSize) {
|
||||||
|
taosUnLockFile(pFile);
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to write len to file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s",
|
||||||
|
filepath, pFile, writeSize, sizeof(msgLen), terrstr());
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSize = taosWriteFile(pFile, pMsg, msgLen);
|
||||||
|
if (msgLen != writeSize) {
|
||||||
|
taosUnLockFile(pFile);
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to write file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s",
|
||||||
|
filepath, pFile, writeSize, msgLen, terrstr());
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosUnLockFile(pFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
if (pFile) taosCloseFile(&pFile);
|
||||||
|
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
taosPrintLog(flags, level, dflag, "crash signal is %d", signum);
|
taosPrintLog(flags, level, dflag, "crash signal is %d", signum);
|
||||||
|
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
|
@ -846,8 +927,102 @@ void taosCrash(int signum, void *sigInfo, void *context) {
|
||||||
taosGetCmdlineByPID(((siginfo_t *)sigInfo)->si_pid));
|
taosGetCmdlineByPID(((siginfo_t *)sigInfo)->si_pid));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
taosPrintTrace(flags, level, dflag, 3);
|
||||||
|
|
||||||
taosPrintTrace(flags, level, dflag);
|
taosMemoryFree(pMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void taosReadCrashInfo(char* filepath, char** pMsg, int64_t* pMsgLen, TdFilePtr* pFd) {
|
||||||
|
const char *flags = "UTL FATAL ";
|
||||||
|
ELogLevel level = DEBUG_FATAL;
|
||||||
|
int32_t dflag = 255;
|
||||||
|
TdFilePtr pFile = NULL;
|
||||||
|
bool truncateFile = false;
|
||||||
|
char* buf = NULL;
|
||||||
|
|
||||||
|
if (NULL == *pFd) {
|
||||||
|
int64_t filesize = 0;
|
||||||
|
if (taosStatFile(filepath, &filesize, NULL) < 0) {
|
||||||
|
if (ENOENT == errno) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to stat file:%s since %s", filepath, terrstr());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filesize <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pFile = taosOpenFile(filepath, TD_FILE_READ|TD_FILE_WRITE);
|
||||||
|
if (pFile == NULL) {
|
||||||
|
if (ENOENT == errno) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to open file:%s since %s", filepath, terrstr());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
taosLockFile(pFile);
|
||||||
|
} else {
|
||||||
|
pFile = *pFd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t msgLen = 0;
|
||||||
|
int64_t readSize = taosReadFile(pFile, &msgLen, sizeof(msgLen));
|
||||||
|
if (sizeof(msgLen) != readSize) {
|
||||||
|
truncateFile = true;
|
||||||
|
if (readSize < 0) {
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to read len from file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s",
|
||||||
|
filepath, pFile, readSize, sizeof(msgLen), terrstr());
|
||||||
|
}
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = taosMemoryMalloc(msgLen);
|
||||||
|
if (NULL == buf) {
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to malloc buf, size:%" PRId64, msgLen);
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
readSize = taosReadFile(pFile, buf, msgLen);
|
||||||
|
if (msgLen != readSize) {
|
||||||
|
truncateFile = true;
|
||||||
|
taosPrintLog(flags, level, dflag, "failed to read file:%s,%p wlen:%" PRId64 " tlen:%" PRId64 " since %s",
|
||||||
|
filepath, pFile, readSize, msgLen, terrstr());
|
||||||
|
goto _return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pMsg = buf;
|
||||||
|
*pMsgLen = msgLen;
|
||||||
|
*pFd = pFile;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
_return:
|
||||||
|
|
||||||
|
if (truncateFile) {
|
||||||
|
taosFtruncateFile(pFile, 0);
|
||||||
|
}
|
||||||
|
taosUnLockFile(pFile);
|
||||||
|
taosCloseFile(&pFile);
|
||||||
|
taosMemoryFree(buf);
|
||||||
|
|
||||||
|
*pMsg = NULL;
|
||||||
|
*pMsgLen = 0;
|
||||||
|
*pFd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void taosReleaseCrashLogFile(TdFilePtr pFile, bool truncateFile) {
|
||||||
|
if (truncateFile) {
|
||||||
|
taosFtruncateFile(pFile, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
taosUnLockFile(pFile);
|
||||||
|
taosCloseFile(&pFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue