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