1 /*
2  * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3  */
4 
5 #include "ulog/ulog.h"
6 #include "ulog_api.h"
7 
8 #include <string.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include "aos/kernel.h"
13 #if ULOG_POP_CLOUD_ENABLE
14 #include "uagent_type.h"
15 #endif
16 bool aos_ulog_init = false;
17 
18 extern void (*aos_cust_output_func)(const char *fmt, ...);
19 #if AOS_COMP_CLI
20 
21 #include "aos/cli.h"
22 
update_net_cli(const char cmd,const char * param)23 __attribute__((weak)) void update_net_cli(const char cmd, const char *param)
24 {
25     /* Will be overwrite in session_udp, as this implement take effect only the UDP feature support,
26        I don't like so many compile switcher in the code which result reader is not so comfortable,
27        so weak attribute used here.
28     */
29 }
30 
fs_control_cli(const char cmd,const char * param)31 __attribute__((weak)) void fs_control_cli(const char cmd, const char *param)
32 {
33     /* Will be overwrite in session_fs */
34 }
35 
on_show_ulog_file()36 __attribute__((weak)) void on_show_ulog_file()
37 {
38     /* Will be overwrite in session_fs */
39 }
40 
41 #if ULOG_CONFIG_ASYNC
cmd_cli_ulog(char * pwbuf,int blen,int argc,char * argv[])42 static void cmd_cli_ulog(char *pwbuf, int blen, int argc, char *argv[])
43 {
44     bool exit_loop = false;
45     uint8_t session = 0xFF;
46     uint8_t level = 0xFF;
47     uint8_t i;
48 
49     if (argc == 2) {
50         const char* option = argv[1];
51         switch (option[0]) {
52         case 'f':
53             on_show_ulog_file();
54             break;
55         case 'x': {
56 #if ULOG_CONFIG_POP_FS
57             char *buf = (char*)aos_malloc(512);
58             if (NULL != buf) {
59                 aos_cli_printf("get ulog list %d\n", aos_get_ulog_list(buf, 512));
60                 puts(buf);
61                 aos_free(buf);
62             }
63 #else
64             aos_cli_printf("pop log to fs is off");
65 #endif /* ULOG_CONFIG_POP_FS */
66         }
67         break;
68         default:
69             break;
70         }
71     }
72     for (i = 1; i < argc && !exit_loop; i += 2) {
73         const char* option = argv[i];
74         const char* param = argv[i + 1];
75         if (option != NULL && param != NULL && strlen(option) == 1) {
76             switch (option[0]) {
77             case 's':/* session */
78                 session = strtoul(param, NULL, 10);
79                 break;
80             case 'l':/* level */
81                 level = strtoul(param, NULL, 10);
82                 break;
83             case 'a':/* syslog watcher address */
84                 update_net_cli(option[0], param);
85                 break;
86             case 'p': /* syslog wacher port*/
87                 update_net_cli(option[0], param);
88                 break;
89             case 'n':  /*tcpip on/off*/
90                 update_net_cli(option[0], param);
91                 break;
92             case 't':/* terminate record on fs */
93                 fs_control_cli(option[0], param);
94                 break;
95             default: /* unknown option */
96                 exit_loop = true;
97                 break;
98             }
99         } else {/* unknown format */
100             break;
101         }
102     }
103 
104     if ((session < ulog_session_size) && (level <= LOG_NONE)) {
105         on_filter_level_changes((ulog_session_type_t)session, level);
106     }
107 }
108 #endif
109 
110 extern int aos_cli_printf(const char *fmt, ...);
sync_log_cmd(char * buf,int len,int argc,char ** argv)111 static void sync_log_cmd(char *buf, int len, int argc, char **argv)
112 {
113     if (argc < 2) {
114         aos_cli_printf("log level : %s\r\n", get_sync_stop_level());
115         return;
116     } else if (argc == 2) {
117         const char* option = argv[1];
118         switch (option[0]) {
119         case 'A':
120         case 'F':
121         case 'E':
122         case 'W':
123         case 'I':
124         case 'D':
125         case 'N':
126             on_sync_filter_level_change(ulog_session_std, option[0]);
127             break;
128 
129         default:
130             aos_cli_printf("unknown option %c, only support[AFEWID]\r\n", option[0]);
131             break;
132         }
133     }
134 
135 }
136 
137 static struct cli_command ulog_cli_cmd[] = {
138     { "loglevel","set sync log level", sync_log_cmd },
139 #if ULOG_CONFIG_ASYNC
140     { "ulog", "ulog [option param]",   cmd_cli_ulog },
141 #endif
142 };
143 
144 #endif /* AOS_COMP_CLI */
145 
146 #if (ULOG_POP_CLOUD_ENABLE || ULOG_UPLOAD_LOG_FILE)
147 #include "cJSON.h"
148 
on_ulog_handler(void * p,const unsigned short len,void * cmd)149 static int on_ulog_handler(void *p, const unsigned short len, void *cmd)
150 {
151     int rc = -1;
152     cJSON *root = NULL;
153     root = cJSON_Parse(cmd);
154     if (NULL != root) {
155         cJSON *ulog_cmd = NULL;
156 #if ULOG_POP_CLOUD_ENABLE
157         ulog_cmd = cJSON_GetObjectItem(root, "ulog level");
158         if (ulog_cmd != NULL && cJSON_IsNumber(ulog_cmd)) {
159             if(ULOG_POLICY_RQST == ulog_cmd->valueint) {
160                 char buf[64];
161                 snprintf(buf, sizeof(buf), ULOG_LEVEL_RSP, ulog_stop_filter_level(ulog_session_cloud));
162                 rc = uagent_send(UAGENT_MOD_ULOG, ULOG_POLICY,
163                                  strlen(buf), buf, send_policy_object);
164 
165             }
166 
167             if (ulog_cmd->valueint <= LOG_NONE) {
168                 on_filter_change(ulog_session_cloud, ulog_cmd->valueint);
169                 rc = 0;
170             }
171         }
172 #endif
173 
174 #if ULOG_UPLOAD_LOG_FILE
175         /* log list requset */
176         ulog_cmd = cJSON_GetObjectItem(root, "ulog list");
177 
178         if (ulog_cmd != NULL && cJSON_IsString(ulog_cmd)) {
179             if (0 == strlen(ulog_cmd->valuestring)) {
180                 char *buf = (char*)aos_malloc(1024);
181                 memset(buf, 0, 1024);
182                 if (NULL != buf) {
183                     if (0 == aos_get_ulog_list(buf, 1024)) {
184                         rc = uagent_send(UAGENT_MOD_ULOG, ULOG_LOG_LIST,
185                                          strlen(buf), buf, send_policy_object);
186                     }
187                     aos_free(buf);
188                 }
189             }
190         }
191         /*  request upload ulog file */
192         ulog_cmd = cJSON_GetObjectItem(root, "url");
193         if (NULL != ulog_cmd && cJSON_IsString(ulog_cmd)) {
194             cJSON *ulog_idx = cJSON_GetObjectItem(root, "idx");
195             if (NULL != ulog_idx && cJSON_IsNumber(ulog_idx)) {
196                 rc = http_start(ulog_cmd->valuestring, ulog_idx->valueint);
197             }
198         }
199 #endif
200         cJSON_Delete(root);
201     }
202     return rc;
203 }
204 
205 #ifndef MOD_VER
206 #define MOD_VER "1.0.0"
207 #endif
208 static uagent_func_node_t ulog_uagent_funclist[] = {
209     {ULOG_LEVEL_CHANGE, "uloglevel",  on_ulog_handler,  NULL,  &ulog_uagent_funclist[1]},
210     {ULOG_POLICY,       "ulogpolicy", NULL,             NULL,  &ulog_uagent_funclist[2]},
211 #if ULOG_POP_CLOUD_ENABLE
212 #if ULOG_UPLOAD_LOG_FILE
213     {ULOG_SHOW,         "ulogshow",   NULL,             NULL,  &ulog_uagent_funclist[3]},
214 #else /* !ULOG_UPLOAD_LOG_FILE */
215     {ULOG_SHOW,         "ulogshow",   NULL,             NULL,  NULL},
216 #endif
217 #endif /* ULOG_POP_CLOUD_ENABLE */
218 
219 #if ULOG_UPLOAD_LOG_FILE
220     {ULOG_LOG_LIST,     "loglist",    NULL,             NULL,  NULL}
221 #endif
222 };
223 
224 static mod_func_t ulog_uagent_func = {
225     { UAGENT_MOD_ULOG, sizeof(ulog_uagent_funclist) / sizeof(ulog_uagent_funclist[0]), "uLOG", MOD_VER },
226     ulog_uagent_funclist
227 };
228 
229 #endif
230 
ulog_init(void)231 void ulog_init(void)
232 {
233     if (!aos_ulog_init) {
234         log_init_mutex();
235         on_filter_level_changes(ulog_session_size, LOG_NONE);
236 #if ULOG_CONFIG_ASYNC
237         ulog_async_init();
238 #endif
239 
240 #if AOS_COMP_CLI
241         aos_cli_register_commands(&ulog_cli_cmd[0], sizeof(ulog_cli_cmd) / sizeof(struct cli_command));
242 #endif
243         /*set default log output*/
244         if (aos_cust_output_func == NULL) {
245             aos_set_log_output(printf);
246         }
247 
248         aos_ulog_init = true;
249 #if (ULOG_POP_CLOUD_ENABLE || ULOG_UPLOAD_LOG_FILE)
250 
251         uagent_func_node_t * p = ulog_uagent_func.header;
252         if (NULL != p) {
253             while (NULL != p) {
254                 if (0 != uagent_register(UAGENT_MOD_ULOG, "uLog", MOD_VER, p->func, p->func_name, p->service, p->argu)) {
255                     LOGE("ULOG", "register into uagent fail");
256                 }
257                 p = p->next;
258             }
259         } else {
260             LOGE("ULOG", "register into uagent fail, table is null");
261         }
262 #endif
263     }
264 }
265 
266