luat_lib_errdump.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. /*
  2. @module errDump
  3. @summary 错误上报
  4. @version 1.0
  5. @date 2022.12.15
  6. @demo errDump
  7. @tag LUAT_USE_ERRDUMP
  8. @usage
  9. -- 基本用法, 10分钟上报一次,如果有的话
  10. if errDump then
  11. errDump.config(true, 600)
  12. end
  13. -- 附开源服务器端: https://gitee.com/openLuat/luatos-devlog
  14. */
  15. #include "luat_base.h"
  16. #include "luat_sys.h"
  17. #include "luat_msgbus.h"
  18. #include "luat_zbuff.h"
  19. #include "ldebug.h"
  20. #include "luat_rtos.h"
  21. #ifdef LUAT_USE_MOBILE
  22. #include "luat_mobile.h"
  23. #endif
  24. #include "luat_mcu.h"
  25. #include "luat_fs.h"
  26. #include "luat_pm.h"
  27. #include "luat_mem.h"
  28. #ifdef LUAT_USE_NETWORK
  29. #include "luat_network_adapter.h"
  30. #define LUAT_ERRDUMP_TAG "log"
  31. #include "luat_errdump.h"
  32. #define LUAT_LOG_TAG "errDump"
  33. #include "luat_log.h"
  34. #define ERR_DUMP_LEN_MAX (4096)
  35. #define LUAT_ERRDUMP_PORT (12425)
  36. const char luat_errdump_domain[] = "dev_msg1.openluat.com";
  37. enum
  38. {
  39. LUAT_ERRDUMP_RECORD_TYPE_SYS,
  40. LUAT_ERRDUMP_RECORD_TYPE_USR,
  41. LUAT_ERRDUMP_RECORD_TYPE_NONE,
  42. LUAT_ERRDUMP_CONNECT = 0,
  43. LUAT_ERRDUMP_TX,
  44. LUAT_ERRDUMP_RX,
  45. LUAT_ERRDUMP_CLOSE,
  46. };
  47. static const char sys_error_log_file_path[] = {'/',0xaa,'s','e','r','r',0};
  48. static const char user_error_log_file_path[] = {'/',0xaa,'u','e','r','r',0};
  49. typedef struct luat_errdump_conf
  50. {
  51. Buffer_Struct tx_buf;
  52. network_ctrl_t *netc;
  53. char *user_string;
  54. uint32_t upload_period;
  55. uint32_t sys_error_r_cnt;
  56. uint32_t sys_error_w_cnt;
  57. uint32_t user_error_r_cnt;
  58. uint32_t user_error_w_cnt;
  59. luat_rtos_timer_t upload_timer;
  60. luat_rtos_timer_t network_timer;
  61. uint8_t is_uploading;
  62. uint8_t error_dump_enable;
  63. uint8_t upload_poweron_reason_done;
  64. char custom_id[49];
  65. char custom_domain_host[49];
  66. uint16_t custom_domain_port;
  67. }luat_errdump_conf_t;
  68. static luat_errdump_conf_t econf;
  69. static void luat_errdump_load(const char *path, Buffer_Struct *buffer);
  70. static void luat_errdump_clear(const char *path);
  71. static int32_t l_errdump_callback(lua_State *L, void* ptr);
  72. static LUAT_RT_RET_TYPE luat_errdump_timer_callback(LUAT_RT_CB_PARAM);
  73. static LUAT_RT_RET_TYPE luat_errdump_rx_timer_callback(LUAT_RT_CB_PARAM);
  74. static int luat_errdump_network_callback(void *data, void *param)
  75. {
  76. OS_EVENT *event = (OS_EVENT *)data;
  77. // int ret = 0;
  78. rtos_msg_t msg = {0};
  79. (void)param;
  80. if (event->Param1)
  81. {
  82. LLOGE("errdump fail, after %d second retry", econf.upload_period);
  83. econf.is_uploading = 0;
  84. msg.handler = l_errdump_callback,
  85. msg.arg1 = LUAT_ERRDUMP_CLOSE,
  86. luat_msgbus_put(&msg, 0);
  87. luat_rtos_timer_start(econf.upload_timer, econf.upload_period * 1000, 0, luat_errdump_timer_callback, NULL);
  88. OS_DeInitBuffer(&econf.tx_buf);
  89. return 0;
  90. }
  91. switch(event->ID)
  92. {
  93. case EV_NW_RESULT_CONNECT:
  94. msg.handler = l_errdump_callback,
  95. msg.arg1 = LUAT_ERRDUMP_TX,
  96. luat_msgbus_put(&msg, 0);
  97. break;
  98. case EV_NW_RESULT_EVENT:
  99. msg.handler = l_errdump_callback,
  100. msg.arg1 = LUAT_ERRDUMP_RX,
  101. luat_msgbus_put(&msg, 0);
  102. network_wait_event(econf.netc, NULL, 0, 0);
  103. break;
  104. case EV_NW_RESULT_CLOSE:
  105. break;
  106. }
  107. return 0;
  108. }
  109. static void luat_errdump_make_data(lua_State *L)
  110. {
  111. const char *project = "unkonw";
  112. const char *version = "";
  113. #ifdef LUAT_USE_MOBILE
  114. char imei[16] = {0};
  115. #endif
  116. char *selfid = econf.custom_id;
  117. const char *sn = version;
  118. FILE* fd = NULL;
  119. size_t len = 0;
  120. if (econf.custom_id[0] == 0) {
  121. #ifdef LUAT_USE_MOBILE
  122. luat_mobile_get_imei(0, imei, 15);
  123. selfid = imei;
  124. #else
  125. const char* id = luat_mcu_unique_id(&len);
  126. if (id != NULL && len > 0 && len < 24) {
  127. for (size_t i = 0; i < len; i++)
  128. {
  129. sprintf_(econf.custom_id + i*2, "%02X", econf.custom_id[i]);
  130. }
  131. }
  132. #endif
  133. }
  134. lua_getglobal(L, "PROJECT");
  135. size_t version_len, project_len;
  136. if (LUA_TSTRING == lua_type(L, -1))
  137. {
  138. project = luaL_tolstring(L, -1, &project_len);
  139. }
  140. lua_getglobal(L, "VERSION");
  141. if (LUA_TSTRING == lua_type(L, -1))
  142. {
  143. version = luaL_tolstring(L, -1, &version_len);
  144. }
  145. int32_t file_len[LUAT_ERRDUMP_RECORD_TYPE_NONE];
  146. econf.sys_error_r_cnt = econf.sys_error_w_cnt;
  147. file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS] = luat_fs_fsize(sys_error_log_file_path);
  148. econf.user_error_r_cnt = econf.user_error_w_cnt;
  149. file_len[LUAT_ERRDUMP_RECORD_TYPE_USR] = luat_fs_fsize(user_error_log_file_path);
  150. if (file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS] < 0)
  151. {
  152. file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS] = 0;
  153. }
  154. if (file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS] > (ERR_DUMP_LEN_MAX * 2))
  155. {
  156. LLOGE("sys record file len %d too much, drop", file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS]);
  157. luat_fs_remove(sys_error_log_file_path);
  158. file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS] = 0;
  159. }
  160. if (file_len[LUAT_ERRDUMP_RECORD_TYPE_USR] < 0)
  161. {
  162. file_len[LUAT_ERRDUMP_RECORD_TYPE_USR] = 0;
  163. }
  164. if (file_len[LUAT_ERRDUMP_RECORD_TYPE_USR] > (ERR_DUMP_LEN_MAX * 2))
  165. {
  166. LLOGE("user record file len %d too much, drop", file_len[LUAT_ERRDUMP_RECORD_TYPE_USR]);
  167. luat_fs_remove(user_error_log_file_path);
  168. file_len[LUAT_ERRDUMP_RECORD_TYPE_USR] = 0;
  169. }
  170. if (econf.user_string)
  171. {
  172. sn = econf.user_string;
  173. }
  174. OS_ReInitBuffer(&econf.tx_buf, file_len[LUAT_ERRDUMP_RECORD_TYPE_USR] + file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS] + 128);
  175. econf.tx_buf.Pos = sprintf_((char*)econf.tx_buf.Data, "%s_LuatOS-SoC_%s_%s,%s,%s,%s,\r\n", project, luat_version_str(), luat_os_bsp(), version, selfid, sn);
  176. if (!econf.upload_poweron_reason_done)
  177. {
  178. econf.tx_buf.Pos += sprintf_((char*)(econf.tx_buf.Data + econf.tx_buf.Pos), "poweron reason:%d\r\n", luat_pm_get_poweron_reason());
  179. }
  180. if (file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS] > 0)
  181. {
  182. fd = luat_fs_fopen(sys_error_log_file_path, "r");
  183. len = luat_fs_fread((char*)(econf.tx_buf.Data + econf.tx_buf.Pos), file_len[LUAT_ERRDUMP_RECORD_TYPE_SYS], 1, fd);
  184. if (len > 0)
  185. {
  186. econf.tx_buf.Pos += len;
  187. econf.tx_buf.Data[econf.tx_buf.Pos] = '\r';
  188. econf.tx_buf.Data[econf.tx_buf.Pos + 1] = '\n';
  189. econf.tx_buf.Pos += 2;
  190. }
  191. luat_fs_fclose(fd);
  192. }
  193. if (file_len[LUAT_ERRDUMP_RECORD_TYPE_USR] > 0)
  194. {
  195. fd = luat_fs_fopen(user_error_log_file_path, "r");
  196. len = luat_fs_fread(econf.tx_buf.Data + econf.tx_buf.Pos, file_len[LUAT_ERRDUMP_RECORD_TYPE_USR], 1, fd);
  197. if (len > 0)
  198. {
  199. econf.tx_buf.Pos += len;
  200. econf.tx_buf.Data[econf.tx_buf.Pos] = '\r';
  201. econf.tx_buf.Data[econf.tx_buf.Pos + 1] = '\n';
  202. econf.tx_buf.Pos += 2;
  203. }
  204. luat_fs_fclose(fd);
  205. }
  206. }
  207. static int32_t l_errdump_callback(lua_State *L, void* ptr)
  208. {
  209. (void)ptr;
  210. uint8_t response[16];
  211. luat_ip_addr_t remote_ip;
  212. uint16_t remote_port;
  213. uint32_t dummy_len;
  214. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  215. const char *ok_result = "{\"r\": 1}";
  216. switch(msg->arg1)
  217. {
  218. case LUAT_ERRDUMP_CONNECT:
  219. econf.netc = network_alloc_ctrl(network_get_last_register_adapter());
  220. if (!econf.netc)
  221. {
  222. LLOGE("no socket, errdump fail, after %d second retry", econf.upload_period);
  223. econf.is_uploading = 0;
  224. luat_rtos_timer_start(econf.upload_timer, econf.upload_period * 1000, 0, luat_errdump_timer_callback, NULL);
  225. OS_DeInitBuffer(&econf.tx_buf);
  226. }
  227. else
  228. {
  229. network_init_ctrl(econf.netc, NULL, luat_errdump_network_callback, NULL);
  230. network_set_base_mode(econf.netc, 0, 0, 0, 0, 0, 0);
  231. luat_rtos_timer_start(econf.network_timer, 30000, 0, luat_errdump_rx_timer_callback, NULL);
  232. if (econf.custom_domain_host[0]) {
  233. if (econf.custom_domain_port < 1) {
  234. econf.custom_domain_port = LUAT_ERRDUMP_PORT;
  235. }
  236. // LLOGD("上行到自定义服务器 %s %d", econf.custom_domain_host, econf.custom_domain_port);
  237. network_connect(econf.netc, econf.custom_domain_host, strlen(econf.custom_domain_host), NULL, econf.custom_domain_port, 0);
  238. }
  239. else {
  240. network_connect(econf.netc, luat_errdump_domain, sizeof(luat_errdump_domain), NULL, LUAT_ERRDUMP_PORT, 0);
  241. }
  242. }
  243. break;
  244. case LUAT_ERRDUMP_TX:
  245. if (!econf.tx_buf.Data)
  246. {
  247. luat_errdump_make_data(L);
  248. }
  249. else
  250. {
  251. if (econf.sys_error_r_cnt != econf.sys_error_w_cnt || econf.user_error_r_cnt != econf.user_error_w_cnt)
  252. {
  253. msg->arg2 = 0;
  254. luat_errdump_make_data(L);
  255. }
  256. }
  257. if (network_tx(econf.netc, econf.tx_buf.Data, econf.tx_buf.Pos, 0, NULL, 0, &dummy_len, 0) < 0)
  258. {
  259. LLOGE("socket tx error, errdump fail, after %d second retry", econf.upload_period);
  260. luat_rtos_timer_start(econf.upload_timer, econf.upload_period * 1000, 0, luat_errdump_timer_callback, NULL);
  261. goto SOCKET_CLOSE;
  262. }
  263. network_wait_event(econf.netc, NULL, 0, 0);
  264. luat_rtos_timer_start(econf.network_timer, 10000, 0, luat_errdump_rx_timer_callback, (void *)(msg->arg2 + 1));
  265. break;
  266. case LUAT_ERRDUMP_RX:
  267. if (network_rx(econf.netc, response, 16, 0, &remote_ip, &remote_port, &dummy_len))
  268. {
  269. LLOGE("socket rx error, errdump fail, after %d second retry", econf.upload_period);
  270. luat_rtos_timer_start(econf.upload_timer, econf.upload_period * 1000, 0, luat_errdump_timer_callback, NULL);
  271. goto SOCKET_CLOSE;
  272. }
  273. if (8 == dummy_len)
  274. {
  275. if (memcmp(response, ok_result, 8))
  276. {
  277. LLOGD("errdump response error %.*s", dummy_len, response);
  278. break;
  279. }
  280. }
  281. else if (2 == dummy_len)
  282. {
  283. if (memcmp(response, "OK", 2))
  284. {
  285. LLOGD("errdump response error %.*s", dummy_len, response);
  286. break;
  287. }
  288. }
  289. else
  290. {
  291. LLOGD("errdump response maybe new %.*s", dummy_len, response);
  292. }
  293. if (econf.sys_error_r_cnt != econf.sys_error_w_cnt || econf.user_error_r_cnt != econf.user_error_w_cnt)
  294. {
  295. LLOGD("errdump need retry!");
  296. luat_errdump_make_data(L);
  297. if (network_tx(econf.netc, econf.tx_buf.Data, econf.tx_buf.Pos, 0, NULL, 0, &dummy_len, 0))
  298. {
  299. LLOGE("socket tx error, errdump fail, after %d second retry", econf.upload_period);
  300. luat_rtos_timer_start(econf.upload_timer, econf.upload_period * 1000, 0, luat_errdump_timer_callback, NULL);
  301. goto SOCKET_CLOSE;
  302. }
  303. network_wait_event(econf.netc, NULL, 0, 0);
  304. luat_rtos_timer_start(econf.network_timer, 10000, 0, luat_errdump_rx_timer_callback, (void *)1);
  305. }
  306. else
  307. {
  308. LLOGD("errdump ok!");
  309. luat_errdump_clear(sys_error_log_file_path);
  310. luat_errdump_clear(user_error_log_file_path);
  311. econf.upload_poweron_reason_done = 1;
  312. goto SOCKET_CLOSE;
  313. }
  314. break;
  315. case LUAT_ERRDUMP_CLOSE:
  316. goto SOCKET_CLOSE;
  317. break;
  318. }
  319. return 0;
  320. SOCKET_CLOSE:
  321. luat_rtos_timer_stop(econf.network_timer);
  322. econf.is_uploading = 0;
  323. if (econf.netc)
  324. {
  325. network_close(econf.netc, 0);
  326. network_release_ctrl(econf.netc);
  327. OS_DeInitBuffer(&econf.tx_buf);
  328. econf.netc = NULL;
  329. }
  330. return 0;
  331. }
  332. static LUAT_RT_RET_TYPE luat_errdump_rx_timer_callback(LUAT_RT_CB_PARAM)
  333. {
  334. if (param)
  335. {
  336. uint32_t retry = (uint32_t)param;
  337. if (retry < 3)
  338. {
  339. LLOGE("errdump tx fail %d cnt, retry", retry);
  340. rtos_msg_t msg = {
  341. .handler = l_errdump_callback,
  342. .ptr = NULL,
  343. .arg1 = LUAT_ERRDUMP_TX,
  344. .arg2 = retry,
  345. };
  346. luat_msgbus_put(&msg, 0);
  347. }
  348. }
  349. else
  350. {
  351. LLOGE("errdump server connect fail, after %d second retry", econf.upload_period);
  352. rtos_msg_t msg = {
  353. .handler = l_errdump_callback,
  354. .ptr = NULL,
  355. .arg1 = LUAT_ERRDUMP_CLOSE,
  356. .arg2 = 0,
  357. };
  358. luat_msgbus_put(&msg, 0);
  359. econf.is_uploading = 0;
  360. luat_rtos_timer_start(econf.upload_timer, econf.upload_period * 1000, 0, luat_errdump_timer_callback, NULL);
  361. }
  362. }
  363. static LUAT_RT_RET_TYPE luat_errdump_timer_callback(LUAT_RT_CB_PARAM)
  364. {
  365. (void)param;
  366. if (!econf.upload_poweron_reason_done || luat_fs_fsize(sys_error_log_file_path) > 0 || luat_fs_fsize(user_error_log_file_path) > 0)
  367. {
  368. econf.is_uploading = 1;
  369. rtos_msg_t msg = {
  370. .handler = l_errdump_callback,
  371. .ptr = NULL,
  372. .arg1 = LUAT_ERRDUMP_CONNECT,
  373. .arg2 = 0,
  374. };
  375. luat_msgbus_put(&msg, 0);
  376. }
  377. else
  378. {
  379. LLOGD("no info errdump stop");
  380. }
  381. }
  382. static void luat_errdump_save(const char *path, const uint8_t *data, uint32_t len)
  383. {
  384. if (!econf.error_dump_enable) return;
  385. size_t now_len = luat_fs_fsize(path);
  386. FILE* fd = NULL;
  387. // 分情况处理
  388. if (len >= ERR_DUMP_LEN_MAX) {
  389. // 新数据直接超过了最大长度, 那老数据没意义了
  390. // 而且新数据必须截断
  391. data += (len - ERR_DUMP_LEN_MAX);
  392. len = ERR_DUMP_LEN_MAX;
  393. fd = luat_fs_fopen(path, "w+"); // 这里会截断
  394. }
  395. else if (now_len + len > ERR_DUMP_LEN_MAX) {
  396. // 新数据小于ERR_DUMP_LEN_MAX, 但新数据+老数据<ERR_DUMP_LEN_MAX
  397. size_t keep_len = ERR_DUMP_LEN_MAX - len;// 老数据保留措施
  398. uint8_t *buffer = luat_heap_malloc(keep_len);
  399. if (buffer) {
  400. // 打开原文件,读取现有的数据
  401. fd = luat_fs_fopen(path, "r");
  402. if (fd) {
  403. luat_fs_fseek(fd, now_len - keep_len, SEEK_SET);
  404. luat_fs_fread(buffer, keep_len, 1, fd);
  405. luat_fs_fclose(fd);
  406. // 再次打开文件,进行写入
  407. fd = luat_fs_fopen(path, "w+");
  408. if (fd) {
  409. luat_fs_fwrite(buffer, keep_len, 1, fd);
  410. } // 老数据读不到就无视吧
  411. } // 老数据读不到就无视吧
  412. luat_heap_free(buffer);
  413. }
  414. }
  415. else {
  416. // 数据直接追加就可以了
  417. fd = luat_fs_fopen(path, "a+");
  418. }
  419. if (fd == NULL) {
  420. // 最后的尝试
  421. luat_fs_remove(path);
  422. fd = luat_fs_fopen(path, "w+");
  423. }
  424. // 最后的最后, 写入新数据
  425. if (fd) {
  426. luat_fs_fwrite(data, len, 1, fd);
  427. luat_fs_fclose(fd);
  428. }
  429. else {
  430. // TODO 这里要return吗?
  431. }
  432. if (!econf.is_uploading && econf.upload_period)
  433. {
  434. luat_rtos_timer_start(econf.upload_timer, 2000, 0, luat_errdump_timer_callback, NULL);
  435. }
  436. }
  437. static void luat_errdump_clear(const char *path)
  438. {
  439. if (luat_fs_fexist(path)) luat_fs_remove(path);
  440. }
  441. static void luat_errdump_load(const char *path, Buffer_Struct *buffer)
  442. {
  443. if (!econf.error_dump_enable) return;
  444. size_t len = luat_fs_fsize(path);
  445. if (!len)
  446. {
  447. return;
  448. }
  449. FILE* fd = luat_fs_fopen(path, "rb");
  450. if (buffer->MaxLen < len)
  451. {
  452. OS_ReInitBuffer(buffer, len);
  453. }
  454. len = luat_fs_fread(buffer->Data, len, 1, fd);
  455. if (len > 0)
  456. {
  457. buffer->Pos = len;
  458. }
  459. luat_fs_fclose(fd);
  460. }
  461. void luat_errdump_save_file(const uint8_t *data, uint32_t len)
  462. {
  463. econf.sys_error_w_cnt++;
  464. luat_errdump_save(sys_error_log_file_path, data, len);
  465. econf.sys_error_w_cnt++;
  466. }
  467. void luat_errdump_record_init(uint8_t enable, uint32_t upload_period)
  468. {
  469. econf.error_dump_enable = enable;
  470. if (econf.error_dump_enable)
  471. {
  472. if (upload_period)
  473. {
  474. if (!econf.upload_timer)
  475. {
  476. luat_rtos_timer_create(&econf.upload_timer);
  477. }
  478. if (!econf.network_timer)
  479. {
  480. luat_rtos_timer_create(&econf.network_timer);
  481. }
  482. econf.upload_period = upload_period;
  483. luat_rtos_timer_start(econf.upload_timer, 2000, 0, luat_errdump_timer_callback, NULL);
  484. luat_rtos_timer_stop(econf.network_timer);
  485. }
  486. else
  487. {
  488. econf.upload_period = 0;
  489. luat_rtos_timer_delete(econf.upload_timer);
  490. luat_rtos_timer_delete(econf.network_timer);
  491. }
  492. }
  493. else
  494. {
  495. luat_errdump_clear(sys_error_log_file_path);
  496. luat_errdump_clear(user_error_log_file_path);
  497. luat_rtos_timer_delete(econf.upload_timer);
  498. luat_rtos_timer_delete(econf.network_timer);
  499. if (econf.user_string)
  500. {
  501. luat_heap_free(econf.user_string);
  502. econf.user_string = NULL;
  503. }
  504. }
  505. }
  506. /*
  507. 手动读取异常日志,主要用于用户将日志发送给自己的服务器而不是IOT平台,如果在errDump.config配置了周期上传,则不能使用本函数
  508. @api errDump.dump(zbuff, type, isDelete)
  509. @zbuff 日志信息缓存,如果为nil就不会读出,一般当
  510. @int 日志类型,目前只有errDump.TYPE_SYS和errDump.TYPE_USR
  511. @boolean 是否删除日志
  512. @return boolean true表示本次读取前并没有写入数据,false反之,在删除日志前,最好再读一下确保没有新的数据写入了
  513. @usage
  514. local result = errDump.dump(buff, errDump.TYPE_SYS, false) --读出系统记录的异常日志
  515. local result = errDump.dump(nil, errDump.TYPE_SYS, true) --清除系统记录的异常日志
  516. */
  517. static int l_errdump_dump(lua_State *L) {
  518. int is_delete = 0;
  519. if (LUA_TBOOLEAN == lua_type(L, 3))
  520. {
  521. is_delete = lua_toboolean(L, 3);
  522. }
  523. luat_zbuff_t *buff = NULL;
  524. if (lua_touserdata(L, 1))
  525. {
  526. buff = tozbuff(L);
  527. }
  528. int result = 0;
  529. const char *path = NULL;
  530. int type = luaL_optinteger(L, 2, LUAT_ERRDUMP_RECORD_TYPE_USR);
  531. if (type >= LUAT_ERRDUMP_RECORD_TYPE_NONE)
  532. {
  533. lua_pushboolean(L, 1);
  534. return 1;
  535. }
  536. switch(type)
  537. {
  538. case LUAT_ERRDUMP_RECORD_TYPE_SYS:
  539. result = (econf.sys_error_r_cnt != econf.sys_error_w_cnt);
  540. path = sys_error_log_file_path;
  541. break;
  542. case LUAT_ERRDUMP_RECORD_TYPE_USR:
  543. result = (econf.user_error_r_cnt != econf.user_error_w_cnt);
  544. path = user_error_log_file_path;
  545. break;
  546. }
  547. if (buff)
  548. {
  549. Buffer_Struct buffer;
  550. buffer.Data = buff->addr;
  551. buffer.MaxLen = buff->len;
  552. buffer.Pos = 0;
  553. switch(type)
  554. {
  555. case LUAT_ERRDUMP_RECORD_TYPE_SYS:
  556. econf.sys_error_r_cnt = econf.sys_error_w_cnt;
  557. break;
  558. case LUAT_ERRDUMP_RECORD_TYPE_USR:
  559. econf.user_error_r_cnt = econf.user_error_w_cnt;
  560. break;
  561. }
  562. luat_errdump_load(path, &buffer);
  563. buff->addr = buffer.Data;
  564. buff->len = buffer.MaxLen;
  565. buff->used = buffer.Pos;
  566. }
  567. lua_pushboolean(L, result);
  568. if (is_delete)
  569. {
  570. luat_errdump_clear(path);
  571. }
  572. return 1;
  573. }
  574. /*
  575. 写入用户的异常日志,注意最大只有4KB,超过部分新的覆盖旧的,开启自动上传后会上传到合宙IOT平台
  576. @api errDump.record(string)
  577. @string 日志
  578. @return nil 无返回值
  579. @usage
  580. errDump.record("socket long time no connect") --记录下"socket long time no connect"
  581. */
  582. static int l_errdump_record(lua_State *L) {
  583. if (LUA_TSTRING == lua_type(L, 1))
  584. {
  585. size_t len = 0;
  586. const char *str = luaL_tolstring(L, 1, &len);
  587. if (len)
  588. {
  589. econf.user_error_w_cnt++;
  590. luat_errdump_save(user_error_log_file_path, (const uint8_t *)str, len);
  591. econf.user_error_w_cnt++;
  592. }
  593. }
  594. return 0;
  595. }
  596. /*
  597. 配置关键日志上传IOT平台,这里的日志包括引起luavm异常退出的日志和用户通过record写入的日志,类似于air的errDump
  598. @api errDump.config(enable, period, user_flag, custom_id, host, port)
  599. @boolean 是否启用记录功能,false的话将不会记录任何日志
  600. @int 定时上传周期,单位秒,默认600秒,这个是自动上传时候后的重试时间时间,在开机后或者有record操作后会很快尝试上传到合宙IOT平台一次,如果为0,则不会上传,由用户dump后自己上传自己的平台
  601. @string 用户的特殊标识,可以为空
  602. @string 设备识别号, 4G设备默认是imei,其他设备默认是mcu.unique_id
  603. @string 服务器域名,默认dev_msg1.openluat.com
  604. @int 服务器端口,默认
  605. @return nil 无返回值
  606. @usage
  607. errDump.config(true, 3600, "12345678") --一个小时尝试上次一次,上传时会在imei后附加上12345678
  608. errDump.config(false) --关闭记录功能,不再上传
  609. errDump.config(true, 0) --记录,但是不会主动上传,由用户实现上传功能
  610. -- 2023.09.22新增custom_id参数
  611. errDump.config(true, 3600, nil, "ABC") --一个小时尝试上次一次,上传时使用自定义的设备识别号ABC
  612. -- 2023.12.8 新增host和port参数
  613. errDump.config(true, 3600, nil, nil, "dev_msg1.openluat.com", 12425)
  614. */
  615. static int l_errdump_upload_config(lua_State *L) {
  616. if (LUA_TBOOLEAN == lua_type(L, 1))
  617. {
  618. luat_errdump_record_init(lua_toboolean(L, 1), luaL_optinteger(L, 2, 600));
  619. }
  620. if (econf.error_dump_enable)
  621. {
  622. size_t len = 0;
  623. const char *str;
  624. if (LUA_TSTRING == lua_type(L, 3))
  625. {
  626. str = luaL_checklstring(L, 3, &len);
  627. if (econf.user_string)
  628. {
  629. luat_heap_free(econf.user_string);
  630. econf.user_string = NULL;
  631. }
  632. econf.user_string = luat_heap_malloc(len + 1);
  633. memcpy(econf.user_string, str, len + 1);
  634. }
  635. if (LUA_TSTRING == lua_type(L, 4)) {
  636. str = luaL_checklstring(L, 4, &len);
  637. if (len < 48)
  638. memcpy(econf.custom_id, str, len + 1);
  639. }
  640. if (LUA_TSTRING == lua_type(L, 5)) {
  641. str = luaL_checklstring(L, 5, &len);
  642. if (len < 48)
  643. memcpy(econf.custom_domain_host, str, len + 1);
  644. if (lua_isinteger(L, 6)) {
  645. econf.custom_domain_port = lua_tointeger(L, 6);
  646. }
  647. if (econf.custom_domain_port < 1) {
  648. econf.custom_domain_port = LUAT_ERRDUMP_PORT;
  649. }
  650. LLOGD("自定义服务器 %s %d", econf.custom_domain_host, econf.custom_domain_port);
  651. }
  652. }
  653. return 0;
  654. }
  655. #include "rotable2.h"
  656. static const rotable_Reg_t reg_errdump[] =
  657. {
  658. { "dump", ROREG_FUNC(l_errdump_dump)},
  659. { "record", ROREG_FUNC(l_errdump_record)},
  660. { "config", ROREG_FUNC(l_errdump_upload_config)},
  661. { "TYPE_SYS", ROREG_INT(LUAT_ERRDUMP_RECORD_TYPE_SYS)},
  662. { "TYPE_USR", ROREG_INT(LUAT_ERRDUMP_RECORD_TYPE_USR)},
  663. { NULL, ROREG_INT(0) }
  664. };
  665. LUAMOD_API int luaopen_errdump( lua_State *L ) {
  666. luat_newlib2(L, reg_errdump);
  667. return 1;
  668. }
  669. #endif