replace value to macro for HTTP OK
[apps/native/tizen-things-daemon.git] / daemon / src / ttd-log.c
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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
17 #include <glib.h>
18 #include <sys/syscall.h>
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <time.h>
24 #include <dlog.h>
25 #include <tzplatform_config.h>
26 #include "ttd-log.h"
27 #include "common-util.h"
28
29 /*
30  * ttd log format
31  * [time][log_level][pid-tid] message([func : line] log)
32  */
33
34 static FILE *log_fp = NULL;
35 static GMutex log_mutex;
36 static ttd_log_type_e ltype = TTD_LOG_TYPE_DLOG;
37
38 static const char log_prio_name[][TTD_LOG_LEVEL_MAX] = {
39         "U", /**< Unknown - DO NOT use */
40         "V", /**< Verbose */
41         "D", /**< Debug */
42         "I", /**< Info */
43         "W", /**< Warning */
44         "E", /**< Error */
45 };
46
47 static inline long int __get_tid(void)
48 {
49         return (long int)syscall(__NR_gettid);
50 }
51
52 static log_priority __level_to_dlog_prio(ttd_log_level_e level)
53 {
54         log_priority prio = DLOG_UNKNOWN;
55         switch (level) {
56         case TTD_LOG_DEBUG:
57                 prio = DLOG_DEBUG;
58                 break;
59         case TTD_LOG_ERROR:
60                 prio = DLOG_ERROR;
61                 break;
62         case TTD_LOG_WARNING:
63                 prio = DLOG_WARN;
64                 break;
65         case TTD_LOG_VERBOSE:
66                 prio = DLOG_VERBOSE;
67                 break;
68         case TTD_LOG_INFO:
69                 prio = DLOG_INFO;
70                 break;
71         case TTD_LOG_UNKNOWN:
72         case TTD_LOG_LEVEL_MAX:
73         default:
74                 prio = DLOG_UNKNOWN;
75         }
76         return prio;
77 }
78
79 static const char* getFormattedTime(void)
80 {
81         struct timespec time_s;
82         struct tm *ptm;
83         static char res_time[40] = {0, };
84
85         time_s.tv_sec = 0;
86         time_s.tv_nsec = 0;
87
88         if (0 == common_get_epoch_coarse_timespec(&time_s)) {
89                 ptm = localtime((const time_t *)&time_s.tv_sec);
90
91                 // format : YY-MM-DD hh:mm:ss:uuuuuu
92                 g_snprintf(res_time, sizeof(res_time),
93                         "%04d-%02d-%02d %02d:%02d:%02d:%06ld"
94                         , ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday
95                         , ptm->tm_hour, ptm->tm_min, ptm->tm_sec
96                         , (long int)(time_s.tv_nsec / 1000));
97         } /* if failed, return last time */
98
99         return res_time;
100 }
101
102 static int __open_log_file(void)
103 {
104         const char *log_file = tzplatform_mkpath(TZ_SYS_VAR, "log/ttd.log");
105         dlog_print(DLOG_DEBUG, LOG_TAG, "log file - %s\n", log_file);
106
107         /* TODO : splits log file, if log file size is exceeded specified max size */
108         g_mutex_lock(&log_mutex);
109         log_fp = fopen(log_file, "a");
110         if (!log_fp) {
111                 g_mutex_unlock(&log_mutex);
112                 dlog_print(DLOG_ERROR,
113                         LOG_TAG, "error[%s] to use log file, so use dlog as log system\n",
114                         strerror(errno));
115
116                 ltype = TTD_LOG_TYPE_DLOG;
117                 return -1;
118         }
119         setvbuf(log_fp, (char *)NULL, _IOLBF, 0);
120         g_mutex_unlock(&log_mutex);
121         return 0;
122 }
123
124 static void __close_log_file(void)
125 {
126         g_mutex_lock(&log_mutex);
127         if (log_fp) {
128                 fclose(log_fp);
129                 log_fp = NULL;
130         }
131         g_mutex_unlock(&log_mutex);
132
133         dlog_print(DLOG_DEBUG, LOG_TAG, "close log file\n");
134 }
135
136 static void
137 __write_log_to_file(const char *msg, ttd_log_level_e level, const char *tag)
138 {
139         /* TODO : we need to logging tag ??? */
140
141         char *log_msg = NULL;
142
143         if (!msg)
144                 return;
145
146         log_msg = g_strdup_printf("[%s][%s][%ld-%ld] %s",
147                         getFormattedTime(),
148                         log_prio_name[level],
149                         (long int)getpid(), __get_tid(),
150                         msg);
151
152         if (!log_msg) {
153                 dlog_print(DLOG_ERROR, LOG_TAG, "failed to create log msg\n");
154                 dlog_print(DLOG_ERROR, LOG_TAG, "%s", msg);
155         }
156
157         g_mutex_lock(&log_mutex);
158         if (log_fp)
159                 fprintf(log_fp, "%s", log_msg);
160         g_mutex_unlock(&log_mutex);
161         g_free(log_msg);
162 }
163
164 int ttd_log_init(ttd_log_type_e type)
165 {
166         ltype = type;
167         g_mutex_init(&log_mutex);
168         dlog_print(DLOG_DEBUG, LOG_TAG, "initializing log type : [%d]\n", type);
169         switch (type) {
170         case TTD_LOG_TYPE_FILE:
171         case TTD_LOG_TYPE_ALL:
172                 __open_log_file();
173                 break;
174         case TTD_LOG_TYPE_DLOG: /* nothing to do */
175         default:
176                 ltype = TTD_LOG_TYPE_DLOG;
177                 break;
178         }
179         return 0;
180 }
181
182 void ttd_log_fini(void)
183 {
184         __close_log_file();
185         g_mutex_clear(&log_mutex);
186         ltype = TTD_LOG_TYPE_DLOG;
187
188         return;
189 }
190
191 int ttd_log_print(ttd_log_level_e level, const char *tag, const char *fmt, ...)
192 {
193         va_list ap;
194
195         switch (ltype) {
196         case TTD_LOG_TYPE_FILE:
197         {
198                 char *msg = NULL;
199
200                 va_start(ap, fmt);
201                 msg = g_strdup_vprintf(fmt, ap);
202                 va_end(ap);
203
204                 __write_log_to_file(msg, level, tag);
205                 g_free(msg);
206         }
207                 break;
208         case TTD_LOG_TYPE_ALL:
209         {
210                 char *msg = NULL;
211
212                 va_start(ap, fmt);
213                 msg = g_strdup_vprintf(fmt, ap);
214                 va_end(ap);
215
216                 dlog_print(__level_to_dlog_prio(level), tag, "%s", msg);
217                 __write_log_to_file(msg, level, tag);
218                 g_free(msg);
219         }
220                 break;
221         case TTD_LOG_TYPE_DLOG:
222         default:
223                 va_start(ap, fmt);
224                 dlog_vprint(__level_to_dlog_prio(level), tag, fmt, ap);
225                 va_end(ap);
226                 break;
227         }
228         return 0;
229 }