1 #include "logging.h" |
1 #include "logging.h" |
2 #include <stdlib.h> |
2 #include <stdlib.h> |
3 #include <string.h> |
3 #include <string.h> |
|
4 #include <stdarg.h> |
4 |
5 |
5 UcxLogger *ucx_logger_new(FILE *stream, unsigned int level, unsigned int mask) { |
6 UcxLogger *ucx_logger_new(FILE *stream, unsigned int level, unsigned int mask) { |
6 UcxLogger *logger = (UcxLogger*) malloc(sizeof(UcxLogger)); |
7 UcxLogger *logger = (UcxLogger*) malloc(sizeof(UcxLogger)); |
7 if (logger != NULL) { |
8 if (logger != NULL) { |
8 logger->stream = stream; |
9 logger->stream = stream; |
|
10 logger->writer = fwrite; |
9 logger->level = level; |
11 logger->level = level; |
10 logger->mask = mask; |
12 logger->mask = mask; |
11 logger->levels = ucx_map_new(8); |
13 logger->levels = ucx_map_new(8); |
12 |
14 |
13 unsigned int l; |
15 unsigned int l; |
27 void ucx_logger_free(UcxLogger *logger) { |
29 void ucx_logger_free(UcxLogger *logger) { |
28 ucx_map_free(logger->levels); |
30 ucx_map_free(logger->levels); |
29 free(logger); |
31 free(logger); |
30 } |
32 } |
31 |
33 |
32 void ucx_logger_log(UcxLogger *logger, unsigned int level, |
34 void ucx_logger_setoutput(UcxLogger *logger, FILE *stream, |
33 const sstr_t message, const char* file, const unsigned int line) { |
35 size_t(*writer)(const void*,size_t,size_t,FILE*)) { |
|
36 if (stream) { |
|
37 logger->stream = stream; |
|
38 } |
|
39 if (writer) { |
|
40 logger->writer = writer; |
|
41 } |
|
42 } |
|
43 |
|
44 void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file, |
|
45 const unsigned int line, const char *format, ...) { |
34 if (level <= logger->level) { |
46 if (level <= logger->level) { |
35 size_t n = message.length; |
47 const size_t max = 4096; // estimated maximum message length |
36 if ((logger->mask & UCX_LOGGER_SOURCE) > 0) { |
48 char msg[max]; |
37 n += strlen(file); |
49 char *text; |
38 n += 10; // line |
50 size_t k = 0; |
39 } |
51 size_t n; |
40 // TODO: add k bytes for timestamp |
|
41 n += 16; // extra space for fill characters (:, -, etc.) |
|
42 |
|
43 char msg[n]; |
|
44 off_t k = 0; |
|
45 |
52 |
46 if ((logger->mask & UCX_LOGGER_LEVEL) > 0) { |
53 if ((logger->mask & UCX_LOGGER_LEVEL) > 0) { |
47 k += sprintf(msg+k, "%s ", (char*) |
54 text = (char*) ucx_map_int_get(logger->levels, level); |
48 ucx_map_int_get(logger->levels, level)); |
55 n = strlen(text); |
|
56 memcpy(msg+k, text, n); |
|
57 k += n; |
|
58 msg[k++] = ' '; |
49 } |
59 } |
50 // TODO: timestamp |
60 // TODO: timestamp |
51 if ((logger->mask & UCX_LOGGER_SOURCE) > 0) { |
61 if ((logger->mask & UCX_LOGGER_SOURCE) > 0) { |
52 k += sprintf(msg+k, "%s:%d ", file, line); |
62 n = strlen(file); |
|
63 memcpy(msg+k, file, n); |
|
64 k += n; |
|
65 k += sprintf(msg+k, ":%d ", line); |
53 } |
66 } |
54 |
67 |
55 msg[k++] = '-'; msg[k++] = ' '; msg[k] = 0; |
68 msg[k++] = '-'; msg[k++] = ' '; |
56 strncat(msg, message.ptr, message.length); |
69 |
57 k += message.length; |
70 va_list args; |
|
71 va_start (args, format); |
|
72 k += vsnprintf(msg+k, max-k-1, format, args); |
|
73 va_end (args); |
|
74 |
58 msg[k++] = '\n'; |
75 msg[k++] = '\n'; |
59 |
76 |
60 fwrite(msg, 1, k, logger->stream); |
77 logger->writer(msg, 1, k, logger->stream); |
61 fflush(logger->stream); |
78 fflush(logger->stream); |
62 } |
79 } |
63 } |
80 } |