Mercurial > hg > fxanalyse
comparison logging.c @ 251:307fd62f376d
Implement log file rotation
author | Daniele Nicolodi <daniele@grinta.net> |
---|---|
date | Thu, 28 May 2015 16:12:18 +0200 |
parents | eaac96094640 |
children | d948e3ced2b9 |
comparison
equal
deleted
inserted
replaced
250:9b35a2b2c759 | 251:307fd62f376d |
---|---|
10 extern double utc; | 10 extern double utc; |
11 /* main panel id */ | 11 /* main panel id */ |
12 extern unsigned int MainPanel; | 12 extern unsigned int MainPanel; |
13 | 13 |
14 | 14 |
15 struct logger { | |
16 unsigned int panel; | |
17 char *dirpath; | |
18 char *filepath; | |
19 int fd; | |
20 int level; | |
21 int yday; | |
22 void(*onerror)(int, const char *); | |
23 }; | |
24 | |
25 | |
26 static inline int strtolevel(const char *str) | |
27 { | |
28 for (int i = 0; i < 4; i++) { | |
29 if (streq(levels[i], str)) | |
30 return i; | |
31 } | |
32 return DEBUG; | |
33 } | |
34 | |
35 | |
36 static int rotate(struct logger *l, struct tm *t) | |
37 { | |
38 int rv; | |
39 char id[7]; | |
40 | |
41 if (! l->dirpath) | |
42 return; | |
43 | |
44 if (l->yday == t.rm_yday) | |
45 return 0; | |
46 | |
47 /* close old file descriptor */ | |
48 close(l->fd); | |
49 l->fd = -1; | |
50 | |
51 /* construct new file name */ | |
52 strftime(id, sizeof(id), "%y%m%d", t); | |
53 rv = asprintf(&l->filepath, "%s\\%s-Log.txt", l->dirpath, id); | |
54 if (rv < 0) | |
55 return rv; | |
56 | |
57 /* open new log file */ | |
58 rv = open(filename, O_CREAT|O_WRONLY|O_APPEND, 00744); | |
59 if (rv < 0) | |
60 return rv; | |
61 | |
62 /* update status */ | |
63 l->fd = rv; | |
64 l->yday = t.rm_yday; | |
65 | |
66 return 1; | |
67 } | |
68 | |
69 | |
15 int __logger_init(struct logger *l, void(*onerror)(int, const char *)) | 70 int __logger_init(struct logger *l, void(*onerror)(int, const char *)) |
16 { | 71 { |
17 int rv, panel; | 72 int rv, panel; |
18 char path[MAX_PATHNAME_LEN], *filename; | 73 char path[MAX_PATHNAME_LEN], *filename; |
74 | |
75 l = malloc(sizeof(struct logger)); | |
76 memset(l, 0, sizeof(*l)); | |
19 | 77 |
20 l->onerror = onerror; | 78 l->onerror = onerror; |
21 l->fd = -1; | 79 l->fd = -1; |
80 l->level = DEBUG; | |
22 | 81 |
23 panel = LoadPanel(0, "FXAnalyse.uir", LOGGING); | 82 panel = LoadPanel(0, "FXAnalyse.uir", LOGGING); |
24 if (panel < 0) | 83 if (panel < 0) |
25 return -1; | 84 return -1; |
26 l->panel = panel; | 85 l->panel = panel; |
30 | 89 |
31 /* load configuration file */ | 90 /* load configuration file */ |
32 IniText configuration = Ini_New(TRUE); | 91 IniText configuration = Ini_New(TRUE); |
33 Ini_ReadFromFile(configuration, path); | 92 Ini_ReadFromFile(configuration, path); |
34 | 93 |
35 /* logging file name */ | 94 /* logging folder path */ |
36 rv = Ini_GetStringCopy(configuration, "logging", "filename", &filename); | 95 rv = Ini_GetStringCopy(configuration, "logging", "folder", &l->dirname); |
96 | |
97 /* logging level */ | |
98 rv = Ini_GetStringCopy(configuration, "logging", "level", &str); | |
37 if (rv > 0) { | 99 if (rv > 0) { |
38 __logmessage(l, INFO, "logging to '%s'", filename); | 100 l->level = strtolevel(str); |
39 l->fd = open(filename, O_CREAT|O_WRONLY|O_APPEND, 00744); | 101 free(str); |
40 if (l->fd < 0) | |
41 __logmessage(l, ERROR, "open log file %s: %s", filename, strerror(errno)); | |
42 } | 102 } |
43 | 103 |
44 free(filename); | |
45 Ini_Dispose(configuration); | 104 Ini_Dispose(configuration); |
46 | 105 |
47 return 0; | 106 return 0; |
48 } | 107 } |
49 | 108 |
60 char msg[1024]; | 119 char msg[1024]; |
61 int len = 0; | 120 int len = 0; |
62 | 121 |
63 /* timestamp */ | 122 /* timestamp */ |
64 len += sprintf(msg, "%014.3f ", utc); | 123 len += sprintf(msg, "%014.3f ", utc); |
65 time_t now = time(NULL); | 124 time_t now = (time_t)utc; |
125 if (now == 0) | |
126 now = time(NULL); | |
66 struct tm *t = localtime(&now); | 127 struct tm *t = localtime(&now); |
67 len += strftime(msg + len, sizeof(msg) - len, "%d-%m-%Y %H:%M:%S ", t); | 128 len += strftime(msg + len, sizeof(msg) - len, "%d-%m-%Y %H:%M:%S ", t); |
68 | 129 |
69 /* level */ | 130 /* level */ |
70 len += snprintf(msg + len, sizeof(msg) - len, "%s: ", levels[level]); | 131 len += snprintf(msg + len, sizeof(msg) - len, "%s: ", levels[level]); |
88 | 149 |
89 /* report error */ | 150 /* report error */ |
90 if (level == ERROR) | 151 if (level == ERROR) |
91 l->onerror(level, msg); | 152 l->onerror(level, msg); |
92 | 153 |
154 /* rotate log file based on current date */ | |
155 rotate(l, t); | |
156 | |
93 /* write to log file */ | 157 /* write to log file */ |
94 if (l->fd >= 0) | 158 if ((level <= l->level) && (l->fd >= 0)) |
95 write(l->fd, msg, len); | 159 write(l->fd, msg, len); |
96 } | 160 } |
161 | |
162 | |
163 void __logger_panel_visible(struct logger *l, visible) | |
164 { | |
165 SetPanelAttribute(l->panel, ATTR_VISIBLE, visible); | |
166 } |