luat_lib_log.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. @module log
  3. @summary 日志库
  4. @version 1.0
  5. @date 2020.03.30
  6. @tag LUAT_USE_GPIO
  7. */
  8. #include "luat_base.h"
  9. #include "luat_sys.h"
  10. #include "luat_msgbus.h"
  11. #include "luat_zbuff.h"
  12. #include "ldebug.h"
  13. #include "luat_rtos.h"
  14. #define LUAT_LOG_TAG "log"
  15. #include "luat_log.h"
  16. typedef struct luat_log_conf
  17. {
  18. uint8_t style;
  19. }luat_log_conf_t;
  20. #define LOG_STYLE_NORMAL 0
  21. #define LOG_STYLE_DEBUG_INFO 1
  22. #define LOG_STYLE_FULL 2
  23. static luat_log_conf_t lconf = {
  24. .style=0
  25. };
  26. static int add_debug_info(lua_State *L, uint8_t pos, const char* LEVEL) {
  27. lua_Debug ar;
  28. // int arg;
  29. // int d = 0;
  30. // // 查找当前stack的深度
  31. // while (lua_getstack(L, d, &ar) != 0) {
  32. // d++;
  33. // }
  34. // // 防御一下, 不太可能直接d==0都失败
  35. // if (d == 0)
  36. // return 0;
  37. // 获取真正的stack位置信息
  38. if (!lua_getstack(L, 1, &ar))
  39. return 0;
  40. // S包含源码, l包含当前行号
  41. if (0 == lua_getinfo(L, "Sl", &ar))
  42. return 0;
  43. // 没有调试信息就跳过了
  44. if (ar.source == NULL)
  45. return 0;
  46. int line = ar.currentline > 64*1024 ? 0 : ar.currentline;
  47. // 推入文件名和行号, 注意: 源码路径的第一个字符是标识,需要跳过
  48. if (LEVEL)
  49. lua_pushfstring(L, "%s/%s:%d", LEVEL, ar.source + 1, line);
  50. else
  51. lua_pushfstring(L, "%s:%d", ar.source + 1, line);
  52. if (lua_gettop(L) > pos)
  53. lua_insert(L, pos);
  54. return 1;
  55. }
  56. /*
  57. 设置日志级别
  58. @api log.setLevel(level)
  59. @string level 日志级别,可用字符串或数值, 字符串为(SILENT,DEBUG,INFO,WARN,ERROR,FATAL), 数值为(0,1,2,3,4,5)
  60. @return nil 无返回值
  61. @usage
  62. -- 设置日志级别为INFO
  63. log.setLevel("INFO")
  64. */
  65. static int l_log_set_level(lua_State *L) {
  66. int LOG_LEVEL = 0;
  67. if (lua_isinteger(L, 1)) {
  68. LOG_LEVEL = lua_tointeger(L, 1);
  69. }
  70. else if (lua_isstring(L, 1)) {
  71. const char* lv = lua_tostring(L, 1);
  72. if (strcmp("SILENT", lv) == 0) {
  73. LOG_LEVEL = LUAT_LOG_CLOSE;
  74. }
  75. else if (strcmp("DEBUG", lv) == 0) {
  76. LOG_LEVEL = LUAT_LOG_DEBUG;
  77. }
  78. else if (strcmp("INFO", lv) == 0) {
  79. LOG_LEVEL = LUAT_LOG_INFO;
  80. }
  81. else if (strcmp("WARN", lv) == 0) {
  82. LOG_LEVEL = LUAT_LOG_WARN;
  83. }
  84. else if (strcmp("ERROR", lv) == 0) {
  85. LOG_LEVEL = LUAT_LOG_ERROR;
  86. }
  87. }
  88. if (LOG_LEVEL == 0) {
  89. LOG_LEVEL = LUAT_LOG_CLOSE;
  90. }
  91. luat_log_set_level(LOG_LEVEL);
  92. return 0;
  93. }
  94. /*
  95. 设置日志风格
  96. @api log.style(val)
  97. @int 日志风格,默认为0, 不传就是获取当前值
  98. @return int 当前的日志风格
  99. @usage
  100. -- 以 log.info("ABC", "DEF", 123) 为例, 假设该代码位于main.lua的12行
  101. -- 默认日志0
  102. -- I/user.ABC DEF 123
  103. -- 调试风格1, 添加额外的调试信息
  104. -- I/main.lua:12 ABC DEF 123
  105. -- 调试风格2, 添加额外的调试信息, 位置有所区别
  106. -- I/user.ABC main.lua:12 DEF 123
  107. log.style(0) -- 默认风格0
  108. log.style(1) -- 调试风格1
  109. log.style(2) -- 调试风格2
  110. */
  111. static int l_log_style(lua_State *L) {
  112. if (lua_isinteger(L, 1))
  113. lconf.style = luaL_checkinteger(L, 1);
  114. lua_pushinteger(L, lconf.style);
  115. return 1;
  116. }
  117. /*
  118. 获取日志级别
  119. @api log.getLevel()
  120. @return int 日志级别对应0,1,2,3,4,5
  121. @usage
  122. -- 得到日志级别
  123. log.getLevel()
  124. */
  125. int l_log_get_level(lua_State *L) {
  126. lua_pushinteger(L, luat_log_get_level());
  127. return 1;
  128. }
  129. static int l_log_2_log(lua_State *L, const char* LEVEL) {
  130. // 是不是什么都不传呀?
  131. int argc = lua_gettop(L);
  132. if (argc < 1) {
  133. // 最起码传1个参数
  134. return 0;
  135. }
  136. if (lconf.style == LOG_STYLE_NORMAL) {
  137. lua_pushfstring(L, "%s/user.%s", LEVEL, lua_tostring(L, 1));
  138. lua_remove(L, 1); // remove tag
  139. lua_insert(L, 1);
  140. }
  141. else if (lconf.style == LOG_STYLE_DEBUG_INFO) {
  142. add_debug_info(L, 1, LEVEL);
  143. }
  144. else if (lconf.style == LOG_STYLE_FULL) {
  145. lua_pushfstring(L, "%s/user.%s", LEVEL, lua_tostring(L, 1));
  146. lua_remove(L, 1); // remove tag
  147. lua_insert(L, 1);
  148. add_debug_info(L, 2, NULL);
  149. }
  150. lua_getglobal(L, "print");
  151. lua_insert(L, 1);
  152. lua_call(L, lua_gettop(L) - 1, 0);
  153. return 0;
  154. }
  155. /*
  156. 输出日志,级别debug
  157. @api log.debug(tag, val, val2, val3, ...)
  158. @string tag 日志标识,必须是字符串
  159. @... 需打印的参数
  160. @return nil 无返回值
  161. @usage
  162. -- 日志输出 D/onenet connect ok
  163. log.debug("onenet", "connect ok")
  164. */
  165. static int l_log_debug(lua_State *L) {
  166. if (luat_log_get_level() > LUAT_LOG_DEBUG) return 0;
  167. return l_log_2_log(L, "D");
  168. }
  169. /*
  170. 输出日志,级别info
  171. @api log.info(tag, val, val2, val3, ...)
  172. @string tag 日志标识,必须是字符串
  173. @... 需打印的参数
  174. @return nil 无返回值
  175. @usage
  176. -- 日志输出 I/onenet connect ok
  177. log.info("onenet", "connect ok")
  178. */
  179. static int l_log_info(lua_State *L) {
  180. if (luat_log_get_level() > LUAT_LOG_INFO) return 0;
  181. return l_log_2_log(L, "I");
  182. }
  183. /*
  184. 输出日志,级别warn
  185. @api log.warn(tag, val, val2, val3, ...)
  186. @string tag 日志标识,必须是字符串
  187. @... 需打印的参数
  188. @return nil 无返回值
  189. @usage
  190. -- 日志输出 W/onenet connect ok
  191. log.warn("onenet", "connect ok")
  192. */
  193. static int l_log_warn(lua_State *L) {
  194. if (luat_log_get_level() > LUAT_LOG_WARN) return 0;
  195. return l_log_2_log(L, "W");
  196. }
  197. /*
  198. 输出日志,级别error
  199. @api log.error(tag, val, val2, val3, ...)
  200. @string tag 日志标识,必须是字符串
  201. @... 需打印的参数
  202. @return nil 无返回值
  203. @usage
  204. -- 日志输出 E/onenet connect ok
  205. log.error("onenet", "connect ok")
  206. */
  207. static int l_log_error(lua_State *L) {
  208. if (luat_log_get_level() > LUAT_LOG_ERROR) return 0;
  209. return l_log_2_log(L, "E");
  210. }
  211. #include "rotable2.h"
  212. static const rotable_Reg_t reg_log[] =
  213. {
  214. { "debug" , ROREG_FUNC(l_log_debug)},
  215. { "info" , ROREG_FUNC(l_log_info)},
  216. { "warn" , ROREG_FUNC(l_log_warn)},
  217. { "error" , ROREG_FUNC(l_log_error)},
  218. { "fatal" , ROREG_FUNC(l_log_error)}, // 以error对待
  219. { "setLevel" , ROREG_FUNC(l_log_set_level)},
  220. { "getLevel" , ROREG_FUNC(l_log_get_level)},
  221. { "style", ROREG_FUNC(l_log_style)},
  222. //{ "_log" , ROREG_FUNC(l_log_2_log)},
  223. //@const LOG_SILENT number 无日志模式
  224. { "LOG_SILENT", ROREG_INT(LUAT_LOG_CLOSE)},
  225. //@const LOG_DEBUG number debug日志模式
  226. { "LOG_DEBUG", ROREG_INT(LUAT_LOG_DEBUG)},
  227. //@const LOG_INFO number info日志模式
  228. { "LOG_INFO", ROREG_INT(LUAT_LOG_INFO)},
  229. //@const LOG_WARN number warning日志模式
  230. { "LOG_WARN", ROREG_INT(LUAT_LOG_WARN)},
  231. //@const LOG_ERROR number error日志模式
  232. { "LOG_ERROR", ROREG_INT(LUAT_LOG_ERROR)},
  233. { NULL, ROREG_INT(0) }
  234. };
  235. LUAMOD_API int luaopen_log( lua_State *L ) {
  236. luat_newlib2(L, reg_log);
  237. return 1;
  238. }
  239. void luat_log_dump(const char* tag, void* ptr, size_t len) {
  240. if (ptr == NULL) {
  241. luat_log_log(LUAT_LOG_DEBUG, tag, "ptr is NULL");
  242. return;
  243. }
  244. if (len == 0) {
  245. luat_log_log(LUAT_LOG_DEBUG, tag, "ptr len is 0");
  246. return;
  247. }
  248. char buff[256] = {0};
  249. uint8_t* ptr2 = (uint8_t*)ptr;
  250. for (size_t i = 0; i < len; i++)
  251. {
  252. sprintf_(buff + strlen(buff), "%02X ", ptr2[i]);
  253. if (i % 8 == 7) {
  254. luat_log_log(LUAT_LOG_DEBUG, tag, "%s", buff);
  255. buff[0] = 0;
  256. }
  257. }
  258. if (strlen(buff)) {
  259. luat_log_log(LUAT_LOG_DEBUG, tag, "%s", buff);
  260. }
  261. }