log.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. #include "precompile.h"
  2. #include "SpBase.h"
  3. #include "log.h"
  4. #include "app.h"
  5. #include "sp_log.h"
  6. #include "sp_svc.h"
  7. #include "sp_iom.h"
  8. #include "sp_cfg.h"
  9. #include "sp_env.h"
  10. #include "fileutil.h"
  11. #include "strutil.h"
  12. #include "dbgutil.h"
  13. #include <winpr/file.h>
  14. #ifdef _WIN32
  15. #include "SpShellConsole.h"
  16. #endif //_WIN32
  17. #define MAX_LOGFILE_SIZE (1<<20)
  18. typedef struct log_t {
  19. SYSTEMTIME tm_start;
  20. FILE *fp;
  21. int file_seq;// non-zero when file is already exist
  22. int last_error;
  23. sp_log_daemon_t *log_daemon;
  24. }log_t;
  25. static const char *str_types[] = {
  26. "Nil",
  27. "Evt",
  28. "Wrn",
  29. "Err",
  30. "Dbg",
  31. };
  32. static const char *str_severity[] = {
  33. "Nil",
  34. "low",
  35. "mid",
  36. "hgh",
  37. };
  38. static BOOL __log_need_change(log_t *log, LPSYSTEMTIME now)
  39. {
  40. TOOLKIT_ASSERT(now);
  41. /* if error occurs, may be Hard Disk broken or space is run out. so no need to change file */
  42. if (log->last_error)
  43. return FALSE;
  44. /* fp currently is null, when system start */
  45. if (!log->fp)
  46. return TRUE;
  47. /* a new day come */
  48. if (log->tm_start.wYear != now->wYear ||
  49. log->tm_start.wMonth != now->wMonth ||
  50. log->tm_start.wDay != now->wDay)
  51. return TRUE;
  52. /* file size has exceed MAX_LOGFILE_SIZE */
  53. if (ftell(log->fp) > MAX_LOGFILE_SIZE) {
  54. return TRUE;
  55. }
  56. /* 10 minutes pass */
  57. {
  58. int diff = (now->wHour - log->tm_start.wHour) * 3600;
  59. diff += (now->wMinute - log->tm_start.wMinute) * 60;
  60. diff += (now->wSecond - log->tm_start.wSecond);
  61. if (diff >= 600) {
  62. return TRUE;
  63. }
  64. }
  65. return FALSE;
  66. }
  67. static const char *get_temp_path(char *buf, LPSYSTEMTIME now, int seq)
  68. {
  69. sp_env_t *env = sp_get_env();
  70. sp_cfg_t *cfg = env->cfg;
  71. sp_cfg_root_ini_t *root_cfg = cfg->root_ini;
  72. const char *dir = root_cfg->ref_syslog_path;
  73. if (dir != NULL && strlen(dir) > 0) {
  74. if (seq) {
  75. sprintf(buf, "%s" SPLIT_SLASH_STR "%08X_%02d-%02d-%02d_%02d-%02d-%02d(%03d)", dir,
  76. cfg->install_ini->current_startup_time,
  77. now->wYear, now->wMonth, now->wDay,
  78. now->wHour, now->wMinute, now->wSecond, seq % 1000);
  79. } else {
  80. sprintf(buf, "%s" SPLIT_SLASH_STR "%08X_%02d-%02d-%02d_%02d-%02d-%02d", dir,
  81. cfg->install_ini->current_startup_time,
  82. now->wYear, now->wMonth, now->wDay,
  83. now->wHour, now->wMinute, now->wSecond);
  84. }
  85. }
  86. return buf;
  87. }
  88. static const char *new_tmp_path(char *buf, LPSYSTEMTIME now, int *file_seq)
  89. {
  90. int seq = 0;
  91. int i;
  92. const int max_tries = 1000;
  93. for (i = 0; i < max_tries; ++i) {
  94. get_temp_path(buf, now, seq);
  95. strcat(buf, ".xml");
  96. if (ExistsFileA(buf)) {
  97. seq++;
  98. } else {
  99. break;
  100. }
  101. }
  102. if (i == max_tries) {
  103. return NULL;
  104. }
  105. //buf[strlen(buf) - 4] = 0;
  106. *file_seq = seq;
  107. return buf;
  108. }
  109. static BOOL rename_file1(LPSYSTEMTIME tm_start, int file_seq)
  110. {
  111. char x[MAX_PATH];
  112. char y[MAX_PATH];
  113. get_temp_path(x, tm_start, file_seq);
  114. strcpy(y, x);
  115. strcat(y, ".xml");
  116. return MoveFileExA(x, y, MOVEFILE_REPLACE_EXISTING);
  117. }
  118. static void __log_change_file(log_t *log, LPSYSTEMTIME now)
  119. {
  120. char tmp[MAX_PATH];
  121. if (log->fp) {
  122. fflush(log->fp);
  123. fclose(log->fp);
  124. log->fp = NULL;
  125. }
  126. if (!new_tmp_path(tmp, now, &log->file_seq)) {
  127. log->last_error = -1;
  128. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("cannot create log tmp file");
  129. return;
  130. }
  131. log->fp = fopen(tmp, "wb");
  132. if (!log->fp) {
  133. log->last_error = -1;
  134. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("cannot fopen log tmp file %s", tmp);
  135. return;
  136. } else {
  137. memcpy(&log->tm_start, now, sizeof(SYSTEMTIME));
  138. }
  139. }
  140. static void __log_write_record(log_t *log,
  141. u__int64_t log_id,
  142. LPSYSTEMTIME tm,
  143. int log_type,
  144. u__int64_t prev_rsn,
  145. u__int64_t curr_rsn,
  146. int original_rsn_type,
  147. int rsn_depth,
  148. int log_severity,
  149. int log_sys_error,
  150. int log_usr_error,
  151. const char *module,
  152. const char *entity,
  153. const char *msg)
  154. {
  155. int n;
  156. n = fprintf(log->fp,
  157. //"<Log SN=\"0x%llX\" Time=\"%02d:%02d:%02d\" LogType=\"%d\" CRS=\"0x%llX\" LRS=\"0x%llX\" ORS=\"0x%X\" RunCount=\"%d\" SeverityLevel=\"%d\" SysCode=\"0x%X\" UserCode=\"0x%X\" SpName=\"%s\" Entity=\"%s\">%s</Log>\r\n",
  158. "<Log SN=\"0x%llX\" Time=\"%02d:%02d:%02d\" LogType=\"%d\" SeverityLevel=\"%d\" SysCode=\"0x%X\" UserCode=\"0x%X\" SpName=\"%s\" Entity=\"%s\">%s</Log>\r\n",
  159. log_id,
  160. tm->wHour, tm->wMinute, tm->wSecond,
  161. log_type,
  162. /*curr_rsn,
  163. prev_rsn,
  164. original_rsn_type,
  165. rsn_depth, */
  166. log_severity,
  167. log_sys_error,
  168. log_usr_error,
  169. module,
  170. entity,
  171. msg);
  172. if (n < 0) {
  173. log->last_error = -1;
  174. fclose(log->fp);
  175. log->fp = NULL;
  176. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("write log record failed!");
  177. }
  178. }
  179. static void on_log(void *inst,
  180. int nsub,
  181. u__int64_t *sub,
  182. int client_id,
  183. int log_epid,
  184. int client_instance_id,
  185. u__int64_t log_id,
  186. u__int64_t prev_rsn,
  187. u__int64_t curr_rsn,
  188. int original_rsn_type,
  189. int rsn_depth,
  190. unsigned int log_time,
  191. int log_type,
  192. int log_severity,
  193. int log_sys_error,
  194. int log_usr_error,
  195. int param_cnt,
  196. int *params,
  197. const char *msg,
  198. void *user_data,
  199. const char* bussId, const char* traceId, const char* spanId, const char* parentSpanId)
  200. {
  201. sp_env_t *env = sp_get_env();
  202. sp_cfg_t *cfg = env->cfg;
  203. sp_cfg_shell_entity_t *ent = sp_cfg_get_entity_by_idx(cfg, client_id);
  204. sp_cfg_shell_module_t *mod = ent ? ent->mod : sp_cfg_get_module_by_idx(cfg, log_epid);
  205. log_t *log = (log_t*)user_data;
  206. app_t *app = get_app_instance();
  207. if (cfg == NULL || ent == NULL || mod == NULL || log == NULL || app == NULL)
  208. return;
  209. #ifdef RVC_OS_WIN
  210. // 在调试控制台显示已订阅实体日志
  211. if (app->pConsole != NULL && app->pConsole->HasSubLogCnn()) {
  212. app->pConsole->OutputLog(client_id, ent->name, msg);
  213. }
  214. #endif //RVC_OS_WIN
  215. if(app->bsc_gui != NULL) {
  216. CSimpleStringA msgContent(true);
  217. int notifyType = 0;
  218. const bool needTosendNormal = (ent->debug_level > 0);
  219. if (log_type == 1 && needTosendNormal) { // Log_Event
  220. notifyType = GUI_DISPLAY_ELEM_LOG_EVENT;
  221. msgContent = CSimpleStringA::Format("[%s] I:{%s}(uc:0x%X)", ent->name, msg, log_usr_error);
  222. }
  223. else if (log_type == 2 && (needTosendNormal || log_severity == 3 /*Severity_High*/)) { //Log_Warning
  224. notifyType = GUI_DISPLAY_ELEM_LOG_WARN;
  225. msgContent = CSimpleString::Format("[%s] W:{%s}(sc:0x%X, uc:0x%X)", ent->name, msg, log_sys_error, log_usr_error);
  226. }
  227. else if (log_type == 3) {// Log_Error
  228. notifyType = GUI_DISPLAY_ELEM_LOG_ERROR;
  229. msgContent = CSimpleString::Format("[%s] E:{%s}(sc:0x%X, uc:0x%X)", ent->name, msg, log_sys_error, log_usr_error);
  230. }
  231. else if ((log_type == 4 || log_type == 0) && needTosendNormal) {// Log_Debug
  232. notifyType = GUI_DISPLAY_ELEM_LOG_DEBUG;
  233. msgContent = CSimpleString::Format("[%s] D:{%s}", ent->name, msg);
  234. }
  235. else if (log_type == 5) {// Log_Fatal
  236. notifyType = GUI_DISPLAY_ELEM_LOG_FATAL;
  237. msgContent = CSimpleString::Format("[%s] F:{%s}(sc:0x%X, uc:0x%X)", ent->name, msg, log_sys_error, log_usr_error);
  238. }
  239. if (notifyType != 0) {
  240. #if defined(_MSC_VER)
  241. sp_gui_show_running_info(app->bsc_gui, msgContent, notifyType);
  242. #else
  243. app->bsc_gui->show_running_info(app->bsc_gui->gui_inst, msgContent, notifyType);
  244. #endif //_MSC_VER
  245. }
  246. }
  247. /** 不打印SystemLog [Gifur@2022516]*/
  248. //SYSTEMTIME st;
  249. //y2k_to_localtime(log_time, &st);
  250. //if (__log_need_change(log, &st)) {
  251. // __log_change_file(log, &st);
  252. //}
  253. //if (!log->last_error && log->fp) {
  254. // LARGE_INTEGER t;
  255. // char *escape = str_xml_escape(msg);
  256. // t.QuadPart = log_id;
  257. // __log_write_record(log,
  258. // log_id, &st, log_type,
  259. // prev_rsn, curr_rsn, original_rsn_type, rsn_depth,
  260. // log_severity, log_sys_error, log_usr_error,
  261. // mod->name, ent ? ent->name : "$Anonymous$", escape);
  262. // FREE(escape);
  263. //}
  264. }
  265. // user send flush command
  266. static void on_flush(void *inst,
  267. int client_id,
  268. LPSYSTEMTIME lst,
  269. void *user_data)
  270. {
  271. log_t *log = (log_t*)user_data;
  272. if (log->fp) {
  273. fflush(log->fp);
  274. /*fclose(log->fp);
  275. log->fp = NULL;*/
  276. }
  277. }
  278. static void on_timeout_interval(void *inst, LPSYSTEMTIME lst, void *user_data)
  279. {
  280. /** 不打印SystemLog [Gifur@2022516]*/
  281. //log_t *log = (log_t*)user_data;
  282. //if (log->fp) {
  283. // if (__log_need_change(log, lst)) {
  284. // fclose(log->fp);
  285. // log->fp = NULL;
  286. // } else {
  287. // fflush(log->fp);
  288. // }
  289. //}
  290. }
  291. int log_create(sp_svc_t *svc, log_t **p_log)
  292. {
  293. log_t *log = ZALLOC_T(log_t);
  294. sp_env_t *env = sp_get_env();
  295. sp_cfg_t *cfg = env->cfg;
  296. sp_cfg_root_ini_t *root_cfg = cfg->root_ini;
  297. //const char *dir = root_cfg->ref_syslog_path;
  298. int rc;
  299. rc = sp_log_daemon_create(&on_log, &on_flush, &on_timeout_interval, log, svc, &log->log_daemon);
  300. if (rc == 0) {
  301. *p_log = log;
  302. } else {
  303. free(log);
  304. }
  305. return rc;
  306. }
  307. int log_destroy(log_t *log)
  308. {
  309. int rc;
  310. rc = sp_log_daemon_destroy(log->log_daemon);
  311. if (rc == 0) {
  312. if (log->fp) {
  313. fflush(log->fp);
  314. fclose(log->fp);
  315. log->fp = NULL;
  316. }
  317. free(log);
  318. }
  319. return 0;
  320. }