modified for systemd journal support
[framework/system/dlog.git] / log.c
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
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 <pthread.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stdarg.h>
20 #include <fcntl.h>
21 #include <sys/uio.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include <dlog.h>
25 #ifdef SD_JOURNAL_SUPPORT
26 #include <syslog.h>
27 #include <systemd/sd-journal.h>
28 #endif
29 #define LOG_BUF_SIZE    1024
30
31 #define LOG_MAIN        "log_main"
32 #define LOG_RADIO       "log_radio"
33 #define LOG_SYSTEM      "log_system"
34 #define LOG_APPS        "log_apps"
35
36 static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
37
38 static int g_logging_on = 1;
39 static int g_dlog_level = DLOG_SILENT;
40
41 static int __dlog_init(log_id_t, log_priority, const char *tag, const char *msg);
42 static int (*write_to_log)(log_id_t, log_priority, const char *tag, const char *msg) = __dlog_init;
43 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
44 static int __write_to_log_null(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
45 {
46         return -1;
47 }
48 static int __write_to_log_kernel(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
49 {
50         ssize_t ret;
51         int log_fd;
52         struct iovec vec[3];
53
54         if (log_id < LOG_ID_APPS) {
55                 if(prio < g_dlog_level) {
56                         return 0;
57                 }
58         } else if (LOG_ID_MAX <= log_id) {
59                 return 0;
60         }
61         if (log_id < LOG_ID_MAX)
62                 log_fd = log_fds[log_id];
63         else
64                 return -1; // for TC
65
66         if (!tag)
67                 tag = "";
68
69         if (!msg)
70                 return -1;
71
72         vec[0].iov_base = (unsigned char *) &prio;
73         vec[0].iov_len  = 1;
74         vec[1].iov_base = (void *) tag;
75         vec[1].iov_len  = strlen(tag) + 1;
76         vec[2].iov_base = (void *) msg;
77         vec[2].iov_len  = strlen(msg) + 1;
78
79         ret = writev(log_fd, vec, 3);
80
81         return ret;
82 }
83 static char dlog_pri_to_char (log_priority pri)
84 {
85         switch (pri) {
86                 case DLOG_VERBOSE:       return 'V';
87                 case DLOG_DEBUG:         return 'D';
88                 case DLOG_INFO:          return 'I';
89                 case DLOG_WARN:          return 'W';
90                 case DLOG_ERROR:         return 'E';
91                 case DLOG_FATAL:         return 'F';
92                 case DLOG_SILENT:        return 'S';
93
94                 case DLOG_DEFAULT:
95                 case DLOG_UNKNOWN:
96                 default:
97                                                                  return '?';
98         }
99 }
100 #ifdef SD_JOURNAL_SUPPORT
101 static int dlog_pri_to_journal_pri(log_priority prio)
102 {
103         int journal_prio = LOG_DEBUG;
104
105         switch(prio) {
106         case DLOG_UNKNOWN:
107         case DLOG_DEFAULT:
108         case DLOG_VERBOSE:
109                 journal_prio = LOG_DEBUG;
110                 break;
111         case DLOG_DEBUG:
112                 journal_prio = LOG_DEBUG;
113                 break;
114         case DLOG_INFO:
115                 journal_prio = LOG_INFO;
116                 break;
117         case DLOG_WARN:
118                 journal_prio = LOG_WARNING;
119                 break;
120         case DLOG_ERROR:
121                 journal_prio = LOG_ERR;
122                 break;
123         case DLOG_FATAL:
124                 journal_prio = LOG_CRIT;
125                 break;
126         case DLOG_SILENT:
127         default:
128                 journal_prio = -1;
129                 break;
130         }
131         return journal_prio;
132 }
133 static int __write_to_log_sd_journal_print(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
134 {
135         ssize_t ret;
136         int log_fd;
137
138         if (log_id < LOG_ID_APPS) {
139                 if(prio < g_dlog_level) {
140                         return 0;
141                 }
142         } else if (LOG_ID_MAX <= log_id) {
143                 return 0;
144         }
145         if (log_id < LOG_ID_MAX)
146                 log_fd = log_fds[log_id];
147         else
148                 return -1;
149         return sd_journal_print(dlog_pri_to_journal_pri(prio), "%c %s: %s",dlog_pri_to_char(prio), tag, msg);
150 }
151 #endif
152 void init_dlog_level(void)
153 {
154         char *dlog_level_env;
155         char *logging_mode_env;
156         if (g_logging_on) {
157                 logging_mode_env = getenv("TIZEN_PLATFORMLOGGING_MODE");
158                 if (!logging_mode_env)
159                                 g_logging_on = 0;
160                         else
161                                 g_logging_on = atoi(logging_mode_env);
162         }
163         if (g_logging_on) {
164                 dlog_level_env = getenv("TIZEN_DLOG_LEVEL");
165                 if (!dlog_level_env) {
166                         g_dlog_level = 8;
167                 } else {
168                         g_dlog_level = atoi(dlog_level_env);
169                 }
170         } else
171                 g_dlog_level = 8;
172 }
173 static int __dlog_init(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
174 {
175         pthread_mutex_lock(&log_init_lock);
176         // get filtering info
177         // open device
178         if (write_to_log == __dlog_init) {
179                 init_dlog_level();
180
181                 log_fds[LOG_ID_MAIN] = open("/dev/"LOG_MAIN, O_WRONLY);
182                 log_fds[LOG_ID_RADIO] = open("/dev/"LOG_RADIO, O_WRONLY);
183                 log_fds[LOG_ID_SYSTEM] = open("/dev/"LOG_SYSTEM, O_WRONLY);
184                 log_fds[LOG_ID_APPS] = open("/dev/"LOG_APPS, O_WRONLY);
185
186                 if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0) {
187                         fprintf(stderr, "open log dev is failed\n");
188                         write_to_log = __write_to_log_null;
189                 } else {
190 #ifdef SD_JOURNAL_SUPPORT
191                         write_to_log = __write_to_log_sd_journal_print;
192 #else
193                         write_to_log = __write_to_log_kernel;
194 #endif
195                 }
196
197                 if (log_fds[LOG_ID_SYSTEM] < 0)
198                         log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
199
200                 if (log_fds[LOG_ID_APPS] < 0)
201                         log_fds[LOG_ID_APPS] = log_fds[LOG_ID_MAIN];
202         }
203         pthread_mutex_unlock(&log_init_lock);
204         return write_to_log(log_id, prio, tag, msg);
205 }
206
207 int __dlog_vprint(log_id_t log_id, int prio, const char *tag, const char *fmt, va_list ap)
208 {
209         char buf[LOG_BUF_SIZE];
210
211         vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
212
213         return write_to_log(log_id, prio, tag, buf);
214 }
215
216 int __dlog_print(log_id_t log_id, int prio, const char *tag, const char *fmt, ...)
217 {
218         va_list ap;
219         char buf[LOG_BUF_SIZE];
220
221         va_start(ap, fmt);
222         vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
223         va_end(ap);
224
225         return write_to_log(log_id, prio, tag, buf);
226 }
227 int _get_logging_on(void)
228 {
229         return g_logging_on;
230 }