da_log.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. * Copyright [2021] JD.com, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <sys/socket.h>
  17. #include <arpa/inet.h>
  18. #include "da_log.h"
  19. #include "da_time.h"
  20. #include "da_string.h"
  21. #define LOGSIZE 4096
  22. #define MSGSIZE 4096
  23. #define REMOTELOG_ERR_TYPE 14
  24. #define AGENT_CLIENT_TYPE 1
  25. #define O_LARGEFILE __O_LARGEFILE
  26. int __log_level__ = 6;
  27. int __log_switch__ = 1;
  28. int __business_id__ = 0;
  29. char __own_addr__[32] = "";
  30. int __own_port__ = 0;
  31. static int logfd = -1;
  32. static char appname[32] = "";
  33. static char log_dir[128] = "./log";
  34. static int logday = 0;
  35. static int noconsole = 0;
  36. //remote log area
  37. static struct sockaddr_in remote_log_addr;
  38. static int sockaddr_length = 0;
  39. int da_gettid(void);
  40. void _set_remote_log_config_(const char *addr, int port, const char *own_addr, int own_port, int businessid, int iSwitch)
  41. {
  42. if(0 == iSwitch)
  43. return;
  44. if (NULL == addr || NULL == own_addr)
  45. {
  46. return;
  47. }
  48. if (0 == port || 0 == own_port)
  49. {
  50. return;
  51. }
  52. strncpy(__own_addr__, own_addr, 31);
  53. __own_addr__[31] = '\0';
  54. __own_port__ = own_port;
  55. __business_id__ = businessid;
  56. bzero((void*)&remote_log_addr, sizeof(remote_log_addr));
  57. remote_log_addr.sin_family = AF_INET;
  58. remote_log_addr.sin_port = htons(port);
  59. int ret = inet_pton(AF_INET, addr, &remote_log_addr.sin_addr);
  60. if (1 != ret)
  61. {
  62. return;
  63. }
  64. sockaddr_length = sizeof(remote_log_addr);
  65. return;
  66. }
  67. static inline int _build_remote_log_socket_()
  68. {
  69. int log_fd = socket(AF_INET, SOCK_DGRAM, 0);
  70. if (log_fd <= 0)
  71. {
  72. return -1;
  73. }
  74. return log_fd;
  75. }
  76. //remote log fd
  77. static __thread int remote_log_fd;
  78. int _set_remote_log_fd_()
  79. {
  80. int fd = _build_remote_log_socket_();
  81. if (fd > 0) { remote_log_fd = fd; return 0; }
  82. else { return -1; }
  83. }
  84. // clean logfd when module unloaded
  85. __attribute__((__destructor__))
  86. static void clean_logfd(void) {
  87. if(logfd >= 0) {
  88. close(logfd);
  89. logfd = -1;
  90. }
  91. }
  92. void _init_log_(const char *app, const char *dir) {
  93. ASSERT(app!=NULL);
  94. strncpy(appname, app, sizeof(appname) - 1);
  95. if (dir) {
  96. strncpy(log_dir, dir, sizeof(log_dir) - 1);
  97. }
  98. mkdir(log_dir, 0777);
  99. if (access(log_dir, W_OK | X_OK) < 0) {
  100. log_error("logdir(%s): Not writable", log_dir);
  101. }
  102. logfd = open("/dev/null", O_WRONLY);
  103. if (logfd < 0)
  104. logfd = dup(2);
  105. fcntl(logfd, F_SETFD, FD_CLOEXEC);
  106. }
  107. void _set_log_level_(int l) {
  108. ASSERT(l>0);
  109. if (l >= 0)
  110. __log_level__ = l > 4 ? l : 4;
  111. }
  112. void _set_log_switch_(int iSwitch)
  113. {
  114. //0 不开启本地日志
  115. __log_switch__ = iSwitch;
  116. }
  117. void _write_log_(int level, char *filename, const char *funcname,
  118. int lineno, const char *format, ...) {
  119. // save errno
  120. int savedErrNo = errno;
  121. int off = 0;
  122. int msgoff = 0;
  123. char buf[LOGSIZE];
  124. char logfile[256];
  125. if (appname[0] == 0)
  126. return;
  127. if (level < 0)
  128. level = 0;
  129. else if (level > 7)
  130. level = 7;
  131. struct tm tm;
  132. time_t now = time(NULL);
  133. localtime_r(&now, &tm);
  134. if (filename == NULL) {
  135. off = snprintf(buf, LOGSIZE, "<%d>[%02d:%02d:%02d] pid[%d]: ", level,
  136. tm.tm_hour, tm.tm_min, tm.tm_sec, getpid());
  137. } else {
  138. filename = basename(filename);
  139. off = snprintf(buf, LOGSIZE,
  140. "<%d>[%02d:%02d:%02d] pid[%d]: %s(%d)[%s]: ", level, tm.tm_hour,
  141. tm.tm_min, tm.tm_sec, da_gettid(), filename, lineno, funcname);
  142. }
  143. if (off >= LOGSIZE)
  144. off = LOGSIZE - 1;
  145. {
  146. int today = tm.tm_year * 1000 + tm.tm_yday;
  147. if (logfd >= 0 && today != logday) {
  148. int fd;
  149. logday = today;
  150. snprintf(logfile, sizeof(logfile), "%s/%s.%04d%02d%02d.log",
  151. log_dir, appname, tm.tm_year + 1900, tm.tm_mon + 1,
  152. tm.tm_mday);
  153. fd = open(logfile, O_CREAT | O_LARGEFILE | O_APPEND | O_WRONLY,
  154. 0644);
  155. if (fd >= 0) {
  156. dup2(fd, logfd);
  157. close(fd);
  158. fcntl(logfd, F_SETFD, FD_CLOEXEC);
  159. }
  160. }
  161. }
  162. msgoff = off;
  163. {
  164. // formatted message
  165. va_list ap;
  166. va_start(ap, format);
  167. // restore errno
  168. errno = savedErrNo;
  169. off += vsnprintf(buf + off, LOGSIZE - off, format, ap);
  170. va_end(ap);
  171. }
  172. if (off >= LOGSIZE)
  173. off = LOGSIZE - 1;
  174. if (buf[off - 1] != '\n') {
  175. buf[off++] = '\n';
  176. }
  177. int unused;
  178. if (logfd >= 0 && (0 != __log_switch__)) {
  179. unused = write(logfd, buf, off);
  180. char szRemoteFd[512] = {0};
  181. }
  182. if(level <= 3)
  183. {
  184. //error log opttype is 14
  185. remote_log(0, NULL, REMOTELOG_ERR_TYPE, 0, buf, now, 0, 0, off);
  186. }
  187. if (level <= 7 && !noconsole) {
  188. // debug send to console/stderr too.
  189. unused = fwrite(buf + 3, 1, off - 3, stderr);
  190. if (unused <= 0) {
  191. // disable console if write error
  192. noconsole = 1;
  193. }
  194. }
  195. }
  196. void write_stderr(const char *fmt, ...) {
  197. int len, size, errno_save;
  198. char buf[4 * 256];
  199. va_list args;
  200. ssize_t n;
  201. errno_save = errno;
  202. len = 0; /* length of output buffer */
  203. size = 4 * 256; /* size of output buffer */
  204. va_start(args, fmt);
  205. len += da_vscnprintf(buf, size, fmt, args);
  206. va_end(args);
  207. buf[len++] = '\n';
  208. n = da_write(STDERR_FILENO, buf, len);
  209. errno = errno_save;
  210. }
  211. struct CRemoteLog
  212. {
  213. int cmd;
  214. int magic;
  215. int len;
  216. char body[0];
  217. };
  218. void remote_log(int type, const char *key, int op_type, int op_result, char *content, long op_time, int cmd, int magic , int contentlen)
  219. {
  220. if (0 == sockaddr_length)
  221. {
  222. return;
  223. }
  224. if (REMOTELOG_ERR_TYPE == op_type)
  225. {
  226. if ( (contentlen > 0) && ( '\n' == content[contentlen-1]) )
  227. {
  228. content[contentlen-1] = 0;
  229. }
  230. }
  231. int off = 0;
  232. char msg[MSGSIZE];
  233. memset(msg, 0 , MSGSIZE);
  234. struct CRemoteLog* pRemoteLog = (struct CRemoteLog*)msg;
  235. int body_max_len = MSGSIZE-sizeof(struct CRemoteLog);
  236. off = snprintf(pRemoteLog->body, body_max_len, "{\"clienttype\":%d,\"routekey\":%d,\"tableconfig\":\"%s\",\"fieldvalues\":[{\"bid\":%d,\"ip\":\"%s\",\"port\":%d,\"ukey\":\"%s\",\"op_type\":%d,\"content\":\"%s\",\"op_time\":%ld,\"op_result\":%d}]}",
  237. AGENT_CLIENT_TYPE, __business_id__, type?"dtc_business.xml":"dtc_error.xml", __business_id__, __own_addr__, __own_port__, key==NULL?"":key, op_type, content==NULL?"":content, op_time, op_result);
  238. pRemoteLog->cmd = cmd;
  239. pRemoteLog->magic = magic;
  240. pRemoteLog->len = off;
  241. //printf("send fd is %d", remote_log_fd);
  242. if (remote_log_fd > 0)
  243. {
  244. sendto(remote_log_fd, msg, sizeof(struct CRemoteLog)+off, 0, (const struct sockaddr*)&remote_log_addr, sockaddr_length);
  245. }
  246. }