diff options
Diffstat (limited to 'toxcore/logger.c')
-rw-r--r-- | toxcore/logger.c | 263 |
1 files changed, 169 insertions, 94 deletions
diff --git a/toxcore/logger.c b/toxcore/logger.c index 674d72e9..21ff81c6 100644 --- a/toxcore/logger.c +++ b/toxcore/logger.c | |||
@@ -1,7 +1,5 @@ | |||
1 | /* logger.c | 1 | /* logger.c |
2 | * | 2 | * |
3 | * Wrapping logger functions in nice macros | ||
4 | * | ||
5 | * Copyright (C) 2013 Tox project All Rights Reserved. | 3 | * Copyright (C) 2013 Tox project All Rights Reserved. |
6 | * | 4 | * |
7 | * This file is part of Tox. | 5 | * This file is part of Tox. |
@@ -26,10 +24,7 @@ | |||
26 | #endif /* HAVE_CONFIG_H */ | 24 | #endif /* HAVE_CONFIG_H */ |
27 | 25 | ||
28 | #include "logger.h" | 26 | #include "logger.h" |
29 | 27 | #include "crypto_core.h" /* for random_int() */ | |
30 | #ifdef LOGGING | ||
31 | |||
32 | #include "network.h" /* for time */ | ||
33 | 28 | ||
34 | #include <stdio.h> | 29 | #include <stdio.h> |
35 | #include <errno.h> | 30 | #include <errno.h> |
@@ -37,121 +32,201 @@ | |||
37 | #include <stdarg.h> | 32 | #include <stdarg.h> |
38 | #include <inttypes.h> | 33 | #include <inttypes.h> |
39 | #include <time.h> | 34 | #include <time.h> |
35 | #include <pthread.h> | ||
40 | 36 | ||
41 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | 37 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) |
42 | #define strerror_r(errno,buf,len) strerror_s(buf,len,errno) | 38 | # define getpid() ((unsigned) GetCurrentProcessId()) |
39 | # define SFILE(FILE__M) (strrchr(FILE__M, '\\') ? strrchr(FILE__M, '\\') + 1 : FILE__M) | ||
40 | #else | ||
41 | # define SFILE(FILE__M) (strrchr(FILE__M, '/') ? strrchr(FILE__M, '/') + 1 : FILE__M) | ||
43 | #endif | 42 | #endif |
44 | 43 | ||
45 | static struct logger_config { | 44 | |
45 | typedef struct logger { | ||
46 | FILE *log_file; | 46 | FILE *log_file; |
47 | LoggerLevel level; | 47 | LOG_LEVEL level; |
48 | uint64_t start_time; /* Time when lib loaded */ | 48 | uint64_t start_time; /* Time when lib loaded */ |
49 | } | 49 | char* id; |
50 | logger = { | 50 | |
51 | NULL, | 51 | /* Allocate these once */ |
52 | DEBUG, | 52 | char* tstr; |
53 | 0 | 53 | char* posstr; |
54 | char* msg; | ||
55 | |||
56 | /* For thread synchronisation */ | ||
57 | pthread_mutex_t mutex[1]; | ||
58 | } logger; | ||
59 | |||
60 | logger* global = NULL; | ||
61 | |||
62 | const char* LOG_LEVEL_STR [] = { | ||
63 | [LOG_TRACE] = "TRACE", | ||
64 | [LOG_DEBUG] = "DEBUG", | ||
65 | [LOG_INFO] = "INFO" , | ||
66 | [LOG_WARNING] = "WARN" , | ||
67 | [LOG_ERROR] = "ERROR", | ||
54 | }; | 68 | }; |
55 | 69 | ||
56 | void __attribute__((destructor)) terminate_logger() | 70 | char* strtime(char* dest, size_t max_len) |
57 | { | ||
58 | if ( !logger.log_file ) return; | ||
59 | |||
60 | time_t tim = time(NULL); | ||
61 | |||
62 | logger_write(ERROR, "\n============== Closing logger [%u] ==============\n" | ||
63 | "Time: %s", logger_get_pid(), asctime(localtime(&tim))); | ||
64 | |||
65 | fclose(logger.log_file); | ||
66 | } | ||
67 | |||
68 | unsigned logger_get_pid() | ||
69 | { | ||
70 | return | ||
71 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
72 | GetCurrentProcessId(); | ||
73 | #else | ||
74 | getpid(); | ||
75 | #endif | ||
76 | } | ||
77 | |||
78 | const char *logger_stringify_level(LoggerLevel level) | ||
79 | { | 71 | { |
80 | static const char *strings [] = { | 72 | time_t timer; |
81 | "INFO", | 73 | struct tm *tm_info; |
82 | "DEBUG", | 74 | |
83 | "WARN", | 75 | time(&timer); |
84 | "ERROR" | 76 | tm_info = localtime(&timer); |
85 | }; | 77 | |
86 | 78 | strftime(dest, max_len, "%m:%d %H:%M:%S", tm_info); | |
87 | return strings[level]; | 79 | return dest; |
88 | } | 80 | } |
89 | 81 | ||
90 | 82 | ||
91 | int logger_init(const char *file_name, LoggerLevel level) | 83 | /** |
84 | * Public Functions | ||
85 | */ | ||
86 | logger* logger_new (const char *file_name, LOG_LEVEL level, const char* id) | ||
92 | { | 87 | { |
93 | if (logger.log_file) { | 88 | #ifndef LOGGING /* Disabled */ |
94 | fprintf(stderr, "Error opening logger name: %s with level %d: file already opened!\n", | 89 | return NULL; |
95 | file_name, level); | 90 | #endif |
96 | return -1; | 91 | |
92 | logger* retu = calloc(1, sizeof(logger)); | ||
93 | |||
94 | if (!retu) | ||
95 | return NULL; | ||
96 | |||
97 | if ( pthread_mutex_init(retu->mutex, NULL) != 0 ) { | ||
98 | free(retu); | ||
99 | return NULL; | ||
97 | } | 100 | } |
98 | 101 | ||
99 | logger.log_file = fopen(file_name, "ab"); | 102 | if (!(retu->log_file = fopen(file_name, "ab"))) { |
100 | |||
101 | if (logger.log_file == NULL) { | ||
102 | fprintf(stderr, "Error opening logger file: %s; info: %s\n", file_name, strerror(errno)); | 103 | fprintf(stderr, "Error opening logger file: %s; info: %s\n", file_name, strerror(errno)); |
103 | return -1; | 104 | free(retu); |
105 | pthread_mutex_destroy(retu->mutex); | ||
106 | return NULL; | ||
104 | } | 107 | } |
105 | 108 | ||
106 | logger.level = level; | 109 | if (!(retu->tstr = calloc(16, sizeof (char))) || |
107 | logger.start_time = current_time_monotonic(); | 110 | !(retu->posstr = calloc(300, sizeof (char))) || |
108 | 111 | !(retu->msg = calloc(4096, sizeof (char))) ) | |
109 | time_t tim = time(NULL); | 112 | goto ERROR; |
110 | logger_write(ERROR, "\n============== Starting logger [%u] ==============\n" | 113 | |
111 | "Time: %s", logger_get_pid(), asctime(localtime(&tim))); | 114 | if (id) { |
112 | return 0; | 115 | if (!(retu->id = calloc(strlen(id) + 1, 1))) |
116 | goto ERROR; | ||
117 | |||
118 | strcpy(retu->id, id); | ||
119 | } else { | ||
120 | if (!(retu->id = malloc(8))) | ||
121 | goto ERROR; | ||
122 | |||
123 | snprintf(retu->id, 8, "%u", random_int()); | ||
124 | } | ||
125 | |||
126 | retu->level = level; | ||
127 | retu->start_time = current_time_monotonic(); | ||
128 | |||
129 | fprintf(retu->log_file, "Successfully created and running logger id: %s; time: %s\n", | ||
130 | retu->id, strtime(retu->tstr, 16)); | ||
131 | |||
132 | return retu; | ||
133 | |||
134 | ERROR: | ||
135 | fprintf(stderr, "Failed to create logger!\n"); | ||
136 | pthread_mutex_destroy(retu->mutex); | ||
137 | fclose(retu->log_file); | ||
138 | free(retu->tstr); | ||
139 | free(retu->posstr); | ||
140 | free(retu->msg); | ||
141 | free(retu->id); | ||
142 | free(retu); | ||
143 | return NULL; | ||
113 | } | 144 | } |
114 | 145 | ||
115 | 146 | void logger_kill(logger* log) | |
116 | void logger_write (LoggerLevel level, const char *format, ...) | ||
117 | { | 147 | { |
118 | if (logger.log_file == NULL) { | 148 | #ifndef LOGGING /* Disabled */ |
119 | /*fprintf(stderr, "Logger file is NULL!\n");*/ | 149 | return; |
150 | #endif | ||
151 | |||
152 | if (!log) | ||
120 | return; | 153 | return; |
121 | } | 154 | |
122 | 155 | pthread_mutex_lock(log->mutex); | |
123 | if (logger.level > level) return; /* Don't print some levels xuh */ | 156 | free(log->id); |
124 | 157 | free(log->tstr); | |
125 | va_list _arg; | 158 | free(log->posstr); |
126 | va_start (_arg, format); | 159 | free(log->msg); |
127 | vfprintf (logger.log_file, format, _arg); | 160 | if (fclose(log->log_file) != 0 ) |
128 | va_end (_arg); | 161 | perror("Could not close log file"); |
129 | 162 | pthread_mutex_unlock(log->mutex); | |
130 | fflush(logger.log_file); | 163 | pthread_mutex_destroy(log->mutex); |
164 | |||
165 | free(log); | ||
131 | } | 166 | } |
132 | 167 | ||
133 | char *logger_timestr(char *dest, size_t max_size) | 168 | void logger_kill_global(void) |
134 | { | 169 | { |
135 | time_t timer; | 170 | logger_kill(global); |
136 | struct tm *tm_info; | 171 | } |
137 | |||
138 | time(&timer); | ||
139 | tm_info = localtime(&timer); | ||
140 | |||
141 | strftime(dest, max_size, "%m:%d %H:%M:%S", tm_info); | ||
142 | |||
143 | return dest; | ||
144 | |||
145 | /*uint64_t diff = (current_time_monotonic() - logger.start_time); /* ms * / | ||
146 | snprintf(dest, max_size, "%"PRIu64"", diff); | ||
147 | 172 | ||
148 | return dest; */ | 173 | void logger_set_global(logger* log) |
174 | { | ||
175 | #ifndef LOGGING /* Disabled */ | ||
176 | return; | ||
177 | #endif | ||
178 | |||
179 | global = log; | ||
149 | } | 180 | } |
150 | 181 | ||
151 | char *logger_posstr (char *dest, size_t max_size, const char *file, int line) | 182 | logger* logger_get_global(void) |
152 | { | 183 | { |
153 | snprintf(dest, max_size, "%s:%d", file, line); | 184 | #ifndef LOGGING /* Disabled */ |
154 | return dest; | 185 | return NULL; |
186 | #endif | ||
187 | |||
188 | return global; | ||
155 | } | 189 | } |
156 | 190 | ||
157 | #endif /* LOGGING */ | 191 | void logger_write (logger* log, LOG_LEVEL level, const char* file, int line, const char *format, ...) |
192 | { | ||
193 | #ifndef LOGGING /* Disabled */ | ||
194 | return; | ||
195 | #endif | ||
196 | |||
197 | static const char* logger_format = | ||
198 | "%s " /* Logger id string */ | ||
199 | "%-16s" /* Time string of format: %m:%d %H:%M:%S */ | ||
200 | "%u " /* Thread id */ | ||
201 | "%-5s " /* Logger lever string */ | ||
202 | "%-20s " /* File:line string */ | ||
203 | "- %s" /* Output message */ | ||
204 | "\n"; /* Every new print new line */ | ||
205 | |||
206 | |||
207 | logger* this_log = log ? log: global; | ||
208 | |||
209 | if (!this_log) | ||
210 | return; | ||
211 | |||
212 | /* Don't print levels lesser than set one */ | ||
213 | if (this_log->level > level) | ||
214 | return; | ||
215 | |||
216 | pthread_mutex_lock(this_log->mutex); | ||
217 | |||
218 | /* Set position str */ | ||
219 | snprintf(this_log->posstr, 300, "%s:%d", SFILE(file), line); | ||
220 | |||
221 | /* Set message */ | ||
222 | va_list args; | ||
223 | va_start (args, format); | ||
224 | vsnprintf(this_log->msg, 4096, format, args); | ||
225 | va_end (args); | ||
226 | |||
227 | fprintf(this_log->log_file, logger_format, this_log->id, strtime(this_log->tstr, 16), pthread_self(), | ||
228 | LOG_LEVEL_STR[level], this_log->posstr, this_log->msg); | ||
229 | fflush(this_log->log_file); | ||
230 | |||
231 | pthread_mutex_unlock(this_log->mutex); | ||
232 | } \ No newline at end of file | ||