summaryrefslogtreecommitdiff
path: root/toxcore/logger.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/logger.c')
-rw-r--r--toxcore/logger.c263
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
45static struct logger_config { 44
45typedef 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;
50logger = { 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
60logger* global = NULL;
61
62const 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
56void __attribute__((destructor)) terminate_logger() 70char* 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
68unsigned logger_get_pid()
69{
70 return
71#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
72 GetCurrentProcessId();
73#else
74 getpid();
75#endif
76}
77
78const 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
91int logger_init(const char *file_name, LoggerLevel level) 83/**
84 * Public Functions
85 */
86logger* 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
134ERROR:
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 146void logger_kill(logger* log)
116void 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
133char *logger_timestr(char *dest, size_t max_size) 168void 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; */ 173void logger_set_global(logger* log)
174{
175 #ifndef LOGGING /* Disabled */
176 return;
177 #endif
178
179 global = log;
149} 180}
150 181
151char *logger_posstr (char *dest, size_t max_size, const char *file, int line) 182logger* 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 */ 191void 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