blob: 33f227f3c13564524da24506d68d9b50b7c19e00 [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001#include <stdio.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <sys/socket.h>
5#include <netinet/in.h>
6#include <netdb.h>
7#include <arpa/inet.h>
8#include <fcntl.h>
9#include <time.h>
10#include <unistd.h>
11#include <errno.h>
12#include "log_config.h"
13
14#define ALOG_DEV "/dev/log_radio"
15
16typedef enum android_LogPriority {
17 ANDROID_LOG_UNKNOWN = 0,
18 ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
19 ANDROID_LOG_VERBOSE,
20 ANDROID_LOG_DEBUG,
21 ANDROID_LOG_INFO,
22 ANDROID_LOG_WARN,
23 ANDROID_LOG_ERROR,
24 ANDROID_LOG_FATAL,
25 ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
26} android_LogPriority;
27
28typedef struct AndroidLogEntry_t {
29 time_t tv_sec;
30 long tv_nsec;
31 android_LogPriority priority;
32 int32_t pid;
33 int32_t tid;
34 const char * tag;
35 size_t messageLen;
36 const char * message;
37} AndroidLogEntry;
38
39static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostname;
40static int log_size = 1 * 1024 * 1024;
41
42static log_config_entry *config = NULL;
43static char tmp_log[48] = {0};
44
45void hex_print(char* buf, int len)
46{
47 int i;
48
49 for (i = 0; i < len; i++) {
50 printf("%x ", buf[i]);
51 }
52}
53
54static char filterPriToChar(android_LogPriority pri)
55{
56 switch (pri) {
57 case ANDROID_LOG_VERBOSE:
58 return 'V';
59 case ANDROID_LOG_DEBUG:
60 return 'D';
61 case ANDROID_LOG_INFO:
62 return 'I';
63 case ANDROID_LOG_WARN:
64 return 'W';
65 case ANDROID_LOG_ERROR:
66 return 'E';
67 case ANDROID_LOG_FATAL:
68 return 'F';
69 case ANDROID_LOG_SILENT:
70 return 'S';
71
72 case ANDROID_LOG_DEFAULT:
73 case ANDROID_LOG_UNKNOWN:
74 default:
75 return '?';
76 }
77}
78
79static android_LogPriority filterCharToPri(char c)
80{
81 switch (c) {
82 case 'v':
83 return ANDROID_LOG_VERBOSE;
84 case 'd':
85 return ANDROID_LOG_DEBUG;
86 case 'i':
87 return ANDROID_LOG_INFO;
88 case 'w':
89 return ANDROID_LOG_WARN;
90 case 'e':
91 return ANDROID_LOG_ERROR;
92 case 'f':
93 return ANDROID_LOG_FATAL;
94 case 's':
95 return ANDROID_LOG_SILENT;
96 case '*':
97 default:
98 return ANDROID_LOG_VERBOSE;
99 }
100}
101
102int fileter_log(int pri, char *tag, struct filter_list_t *filter)
103{
104 struct filter_list_t *_filter = filter;
105
106 while(_filter)
107 {
108 int p = filterCharToPri(_filter->priority);
109 if(_filter->tag)
110 {
111 int len = strlen(_filter->tag);
112 // tag and priority
113 if(0 == memcmp(_filter->tag, tag, len) && ((pri > p) || (pri == p)))
114 return 0;
115 }else{ // have no tag
116 if(pri < p)
117 return -1;
118 else
119 return 0;
120 }
121 _filter = _filter->next;
122 }
123
124 return -1;
125}
126
127int alog_process(char* data, int len, AndroidLogEntry *entry)
128{
129 int i, n = 0;
130 int tmp_len;
131
132 for (i = 0; i < len;) {
133 if (data[i] == '\0') {
134 i += 1;
135 } else {
136 switch (n) {
137 case 0: {
138 // printf("%d - %d: %x\n", i, tmp_len, data[i]);
139 i++;
140 break;
141 }
142 case 1: {
143 int* pid = (int*)&data[i];
144 entry->pid = *pid;
145 // printf("%d pid: %d\n", i, entry->pid);
146 i += 4;
147 break;
148 }
149 case 2: {
150 int* tid = (int*)&data[i];
151 entry->tid = *tid;
152 // printf("%d tid: %d\n", i, entry->tid);
153 i += 4;
154 break;
155 }
156 case 3: {
157 // printf("%d - %d: %x %x %x %x\n", i, tmp_len, data[i], data[i + 1], data[i + 2], data[i + 3]);
158 time_t* _t = (time_t*)&data[i];
159 entry->tv_sec = *_t;
160 i += 8;
161 break;
162 }
163 case 4: {
164 entry->priority = data[i];
165 entry->tag = &data[i + 1];
166 i += strlen(&data[i]);
167 break;
168 }
169 //* format: <priority:1><tag:N>\0<message:N>\0
170 case 5: {
171 entry->message = &data[i];
172 entry->messageLen = strlen(&data[i]);
173 i += entry->messageLen;
174 break;
175 }
176 default:
177 printf("process error \n");
178 break;
179 }
180 n++;
181 }
182 }
183 return 0;
184}
185
186int android_log_printLogLine(
187 int fd,
188 struct file_list_t *_file_list,
189 const AndroidLogEntry *entry)
190{
191 char priChar;
192 char timeBuf[32];
193 char defaultBuffer[512];
194 size_t totalLen;
195 int fd_new = fd;
196 struct stat s;
197 char * ret = NULL;
198
199 if (log_size && (!stat(tmp_log, &s)) && (s.st_size > log_size)) {
200 fd_new = get_rotate_file(fd_new, log_file, _file_list);
201 if (fd_new < 0) {
202 fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
203 exit(-1);
204 }
205 }
206
207 if(fileter_log(entry->priority, entry->tag, config->filter_list))
208 {
209 // printf("%s %d: fileter pri:%d tag:%s!\n", __FUNCTION__, __LINE__, entry->priority, entry->tag);
210 return -1;
211 }
212
213 priChar = filterPriToChar(entry->priority);
214 struct tm* ptm = localtime(&entry->tv_sec);
215 strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
216
217 totalLen = snprintf(defaultBuffer, sizeof(defaultBuffer),
218 "%s %c/%s (%d): %s\n", timeBuf, priChar, entry->tag, entry->pid, entry->message);
219
220 ret = write(fd_new, defaultBuffer, totalLen);
221
222 return ret;
223}
224
225void* alog_thread(void* argv)
226{
227 int dev_fd, ret;
228 int log_fd;
229 AndroidLogEntry entry;
230 char buf[512] = {0};
231 static struct file_list_t file_list;
232 config = (log_config_entry *)argv;
233
234 pthread_detach(pthread_self());
235 if (NULL == argv)
236 return NULL;
237
238 dev_fd = open(ALOG_DEV, O_RDONLY, 0600);
239 if (dev_fd < 0) {
240 fprintf(stderr, "failed to open %s: %s\n", ALOG_DEV, strerror(errno));
241 exit(-1);
242 }
243
244 memset(&file_list, 0, sizeof(struct file_list_t));
245 file_list.total = config->rotate_file_count;
246 log_file = config->out_path;
247
248 if (config->ip && config->port) {
249 int port = atoi(config->port);
250 printf("%s %d : %s:%s\n", __FUNCTION__, __LINE__, config->ip, config->port);
251 log_fd = tcp_connect(config->ip, port);
252 } else if (log_file) {
253 sprintf(tmp_log, "/tmp/log%s", strstr_tail(log_file, "/"));
254 // 先将文件保存到 /tmp/log/ 目录下,后面到达 rotate_file_size 后,转移到out_path
255 log_fd = open(tmp_log, O_CREAT | O_WRONLY| O_APPEND, 0600);
256 if (log_fd < 0) {
257 fprintf(stderr, "failed to open %s: %s\n", tmp_log, strerror(errno));
258 exit(-1);
259 }
260 } else {
261 log_fd = STDOUT_FILENO;
262 }
263 if(config->rotate_file_size)
264 log_size = config->rotate_file_size;
265
266 printf("android log start...\n");
267 while (1) {
268 ret = read(dev_fd, buf, sizeof(buf));
269 if (ret < 0) {
270 printf("read error\n");
271 break;
272 }
273 alog_process(buf, ret, &entry);
274 android_log_printLogLine(log_fd, &file_list, &entry);
275 memset(buf, 0, sizeof(buf));
276 }
277 close(dev_fd);
278 close(log_fd);
279
280 printf("%s exit \n", __FUNCTION__);
281 pthread_exit(NULL);
282 return NULL;
283}