GCC Code Coverage Report


Directory: src/gate/
File: src/gate/io/logging.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 112 200 56.0%
Functions: 11 19 57.9%
Branches: 30 80 37.5%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/io/logging.h"
30 #include "gate/times.h"
31 #include "gate/threading.h"
32 #include "gate/processes.h"
33 #include "gate/streams.h"
34 #include "gate/console.h"
35 #include "gate/files.h"
36 #include "gate/environments.h"
37 #include "gate/results.h"
38
39 #if defined(GATE_SYS_WIN16)
40 # define GATE_IO_LOGGING_NO_IMPL 1
41 #elif defined(GATE_SYS_WIN)
42 # define GATE_IO_LOGGING_WINAPI_IMPL 1
43 #elif defined(GATE_SYS_POSIX)
44 # define GATE_IO_LOGGING_POSIX_IMPL 1
45 #else
46 # define GATE_IO_LOGGING_NO_IMPL 1
47 #endif
48
49
50 #define GATE_LOGGING_STDERR_LOG_TYPE GATE_LOG_TYPE_STATUS
51
52 13 static char const* gate_logging_print_type(gate_enumint_t log_type)
53 {
54
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (log_type >= GATE_LOG_TYPE_FATAL) return "FATAL";
55
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 if (log_type >= GATE_LOG_TYPE_ERROR) return "ERROR";
56
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (log_type >= GATE_LOG_TYPE_WARN) return "WARN";
57
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (log_type >= GATE_LOG_TYPE_STATUS) return "STATUS";
58
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (log_type >= GATE_LOG_TYPE_INFO) return "INFO";
59
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (log_type >= GATE_LOG_TYPE_DEBUG) return "DEBUG";
60 if (log_type >= GATE_LOG_TYPE_TRACE) return "TRACE";
61 return "";
62 }
63
64 13 static gate_size_t gate_logging_create_line(char* buffer, gate_size_t buffer_len,
65 char const* separator,
66 gate_enumint_t log_type, gate_result_t result_code, gate_int32_t native_code,
67 gate_string_t const* origin, gate_string_t const* message)
68 {
69 13 gate_size_t ret = 0;
70 gate_strbuilder_t builder;
71 13 gate_process_id_t pid = 0;
72 13 gate_thread_id_t tid = 0;
73 13 gate_time_t now = GATE_INIT_EMPTY;
74 13 char time_buffer[64] = GATE_INIT_EMPTY;
75 13 gate_size_t time_buffer_size = sizeof(time_buffer);
76
77 13 gate_time_now(&now);
78 13 gate_time_to_string(&now, NULL, time_buffer, &time_buffer_size);
79
80 13 gate_process_get_id(&pid);
81 13 gate_thread_current(NULL, &tid);
82
83 13 gate_strbuilder_create_static(&builder, buffer, buffer_len, 0);
84 13 gate_strbuilder_append(&builder,
85 GATE_PRINT_CSTR, time_buffer,
86 GATE_PRINT_CSTR, separator,
87 GATE_PRINT_CSTR, "P", GATE_PRINT_UI64, (gate_uint64_t)pid,
88 GATE_PRINT_CSTR, ".", GATE_PRINT_UI64, (gate_uint64_t)tid,
89 GATE_PRINT_CSTR, separator, GATE_PRINT_CSTR, gate_logging_print_type(log_type),
90 GATE_PRINT_CSTR, separator, GATE_PRINT_I32, (gate_int32_t)result_code,
91 GATE_PRINT_CSTR, separator, GATE_PRINT_I32, native_code,
92 GATE_PRINT_CSTR, separator, GATE_PRINT_STRING, origin,
93 GATE_PRINT_CSTR, separator, GATE_PRINT_STRING, message,
94 GATE_PRINT_NEWLINE,
95 GATE_PRINT_END);
96
97 13 ret = gate_strbuilder_length(&builder);
98
99 13 gate_strbuilder_release(&builder);
100 13 return ret;
101 }
102
103 static gate_bool_t gate_global_stderr_enabled(gate_logger_t const* logger, gate_enumint_t log_type)
104 {
105 GATE_UNUSED_ARG(logger);
106 return log_type >= GATE_LOGGING_STDERR_LOG_TYPE;
107 }
108
109 12 static gate_result_t gate_global_stderr_log(gate_logger_t const* logger,
110 gate_enumint_t log_type, gate_result_t result_code, gate_int32_t native_code,
111 gate_string_t const* origin, gate_string_t const* message)
112 {
113 12 gate_result_t ret = GATE_RESULT_OK;
114
115 GATE_UNUSED_ARG(logger);
116
117
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (log_type >= GATE_LOG_TYPE_WARN)
118 {
119 char buffer[8192];
120 6 gate_size_t used = gate_logging_create_line(buffer, sizeof(buffer), "\t", log_type, result_code, native_code, origin, message);
121 6 gate_console_write_err(gate_console(), buffer, used);
122 }
123 12 return ret;
124 }
125
126
127 static gate_logger_t gate_stderr_logger =
128 {
129 &gate_global_stderr_log,
130 &gate_global_stderr_enabled
131 };
132
133 static gate_logger_t* volatile gate_current_global_logger = &gate_stderr_logger;
134
135
136
137 static gate_bool_t gate_filelogger_enabled(gate_logger_t const* logger, gate_enumint_t log_type)
138 {
139 gate_filelogger_t* file_logger = (gate_filelogger_t*)logger;
140 return log_type >= file_logger->log_level;
141 }
142
143 7 static gate_result_t gate_filelogger_log(gate_logger_t const* logger,
144 gate_enumint_t log_type, gate_result_t result_code, gate_int32_t native_code,
145 gate_string_t const* origin, gate_string_t const* message)
146 {
147 7 gate_result_t ret = GATE_RESULT_OK;
148 7 gate_filelogger_t* file_logger = (gate_filelogger_t*)logger;
149 char buffer[8192];
150 gate_size_t used;
151 gate_file_t file;
152 gate_size_t written;
153 7 gate_size_t written_total = 0;
154
155 do
156 {
157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (log_type < file_logger->log_level)
158 {
159 /* log type is filted out */
160 break;
161 }
162
163 7 used = gate_logging_create_line(buffer, sizeof(buffer), "\t", log_type, result_code, native_code, origin, message);
164
165 7 ret = gate_mutex_acquire(&file_logger->mutex);
166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 GATE_BREAK_IF_FAILED(ret);
167
168 do
169 {
170 7 ret = gate_file_open(&file_logger->output_file, GATE_STREAM_OPEN_APPENDWRITE | GATE_FILE_OPEN_SHARED, &file);
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 GATE_BREAK_IF_FAILED(ret);
172
173 do
174 {
175 7 ret = gate_file_lock(file, true);
176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 GATE_BREAK_IF_FAILED(ret);
177
178 7 ret = gate_file_seek(file, 0, GATE_FILE_SEEK_ORIGIN_END, NULL);
179
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (GATE_SUCCEEDED(ret))
180 {
181
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 while (written_total < used)
182 {
183 7 ret = gate_file_write(file, &buffer[written_total], used - written_total, &written);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 GATE_BREAK_IF_FAILED(ret);
185 7 written_total += written;
186 }
187 }
188 7 gate_file_flush(file);
189 7 gate_file_unlock(file);
190 } while (0);
191
192 7 gate_file_close(file);
193 } while (0);
194
195 7 gate_mutex_release(&file_logger->mutex);
196
197 } while (0);
198
199 7 return ret;
200 }
201
202 2 gate_result_t gate_filelogger_create(gate_filelogger_t* logger, gate_string_t const* output_file, gate_enumint_t log_level)
203 {
204 2 gate_result_t ret = GATE_RESULT_FAILED;
205 gate_file_t file;
206
207 2 ret = gate_file_open(output_file, GATE_STREAM_OPEN_APPENDWRITE | GATE_FILE_OPEN_SHARED, &file);
208
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
209 {
210 2 gate_mem_clear(logger, sizeof(gate_filelogger_t));
211
212 2 gate_file_close(file);
213
214 2 ret = gate_mutex_create(&logger->mutex);
215
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
216 {
217 2 gate_string_clone(&logger->output_file, output_file);
218 2 logger->logger_base.log = &gate_filelogger_log;
219 2 logger->logger_base.enabled = &gate_filelogger_enabled;
220 2 logger->log_level = log_level;
221 }
222 }
223
224 2 return ret;
225 }
226 2 gate_result_t gate_filelogger_destroy(gate_filelogger_t* logger)
227 {
228 2 gate_string_release(&logger->output_file);
229 2 gate_mutex_destroy(&logger->mutex);
230 2 gate_mem_clear(logger, sizeof(gate_filelogger_t));
231 2 return GATE_RESULT_OK;
232 }
233
234
235
236
237
238
239
240 19 gate_result_t gate_log(gate_logger_t const* logger,
241 gate_enumint_t log_type, gate_result_t result_code, gate_int32_t native_code,
242 gate_string_t const* origin, gate_string_t const* message)
243 {
244
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 if (logger && logger->log)
245 {
246 19 return logger->log(logger, log_type, result_code, native_code, origin, message);
247 }
248 else
249 {
250 return GATE_RESULT_NOTAVAILABLE;
251 }
252 }
253
254 7 gate_result_t gate_log_str(gate_logger_t const* logger,
255 gate_enumint_t log_type, gate_result_t result_code, gate_int32_t native_code,
256 char const* origin, char const* message)
257 {
258 gate_string_t str_origin;
259 gate_string_t str_msg;
260
261 7 gate_string_create_static(&str_origin, origin);
262 7 gate_string_create_static(&str_msg, message);
263 7 return gate_log(logger, log_type, result_code, native_code, &str_origin, &str_msg);
264 }
265
266
267 gate_bool_t gate_log_enabled(gate_logger_t const* logger,
268 gate_enumint_t log_type)
269 {
270 if (logger && logger->enabled)
271 {
272 return logger->enabled(logger, log_type);
273 }
274 else
275 {
276 return false;
277 }
278 }
279
280
281
282 static gate_filelogger_t global_file_logger = GATE_INIT_EMPTY;
283
284 2 gate_result_t gate_logger_start(gate_string_t const* output_file, gate_enumint_t log_level)
285 {
286 2 gate_result_t ret = GATE_RESULT_INVALIDSTATE;
287 2 gate_string_t tmp_file = GATE_STRING_INIT_EMPTY;
288 2 gate_strbuilder_t builder = GATE_INIT_EMPTY;
289 2 gate_string_t tmp_root = GATE_STRING_INIT_EMPTY;
290 char name[GATE_MAX_FILENAME_LENGTH];
291 2 gate_size_t name_len = sizeof(name);
292 2 gate_process_id_t pid = 0;
293
294
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (gate_current_global_logger != &global_file_logger.logger_base)
295 {
296
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_string_is_empty(output_file))
297 {
298 1 gate_process_get_id(&pid);
299 1 gate_env_app_executable_name_str(name, &name_len);
300 1 gate_env_temp_rootpath(&tmp_root);
301 1 gate_strbuilder_create(&builder, 0);
302 1 gate_strbuilder_append_string(&builder, &tmp_root);
303 1 gate_strbuilder_append_cstr(&builder, name);
304 1 gate_strbuilder_append_cstr(&builder, "_");
305 1 gate_strbuilder_append_int64(&builder, (gate_int64_t)pid);
306 1 gate_strbuilder_append_cstr(&builder, ".log");
307 1 gate_strbuilder_to_string(&builder, &tmp_file);
308 }
309 else
310 {
311 1 gate_string_clone(&tmp_file, output_file);
312 }
313
314 2 ret = gate_filelogger_create(&global_file_logger, &tmp_file, log_level);
315
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
316 {
317 2 gate_current_global_logger = &global_file_logger.logger_base;
318 }
319 }
320
321 2 gate_strbuilder_release(&builder);
322 2 gate_string_release(&tmp_file);
323 2 gate_string_release(&tmp_root);
324
325 2 return ret;
326 }
327 6 gate_logger_t const* gate_logger_get()
328 {
329 6 return gate_current_global_logger;
330 }
331 2 gate_result_t gate_logger_stop()
332 {
333 2 gate_result_t ret = GATE_RESULT_OK;
334
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (gate_current_global_logger == &global_file_logger.logger_base)
335 {
336 2 gate_current_global_logger = &gate_stderr_logger;
337 2 ret = gate_filelogger_destroy(&global_file_logger);
338 }
339 2 return ret;
340 }
341
342
343
344
345
346 #if defined(GATE_IO_LOGGING_WINAPI_IMPL)
347
348 #include "gate/platform/windows/win32registry.h"
349 #include "gate/environments.h"
350
351
352 typedef struct gate_syslogger_class
353 {
354 gate_logger_t logger_base;
355
356 TCHAR app_name[GATE_MAX_FILENAME_LENGTH];
357 HANDLE heventlog;
358
359 } gate_syslogger_t;
360
361 static gate_syslogger_t global_syslogger = GATE_INIT_EMPTY;
362 static gate_atomic_flag_t global_syslogger_initialized = GATE_ATOMIC_FLAG_INIT;
363
364
365 static gate_bool_t syslogger_enabled(struct gate_logger_class const* logger, gate_enumint_t log_type)
366 {
367 (void)logger;
368 (void)log_type;
369 return true;
370 }
371
372 static gate_result_t syslogger_log(struct gate_logger_class const* logger,
373 gate_enumint_t log_type, gate_result_t result_code, gate_int32_t native_code,
374 gate_string_t const* origin, gate_string_t const* message)
375 {
376 gate_result_t ret = GATE_RESULT_FAILED;
377 gate_syslogger_t const* impl = (gate_syslogger_t const*)logger;
378 WORD wType = EVENTLOG_INFORMATION_TYPE;
379 WORD wCategory = 0;
380 DWORD dwEventId = (result_code == 0) ? 0 : (65536 + result_code);
381 TCHAR msg_buffer[4096];
382 gate_size_t msg_buffer_capacity = sizeof(msg_buffer) / sizeof(msg_buffer[0]);
383 gate_size_t msg_buffer_used;
384 TCHAR const* ptr_buffer = &msg_buffer[0];
385
386 do
387 {
388 if (log_type <= GATE_LOG_TYPE_DEBUG)
389 {
390 /* debug messages should not be logged in system log */
391 return GATE_RESULT_OK;
392 }
393 else if (log_type <= GATE_LOG_TYPE_INFO)
394 {
395 wType = GATE_SUCCEEDED(result_code) ? EVENTLOG_SUCCESS : EVENTLOG_INFORMATION_TYPE;
396 }
397 else if (log_type <= GATE_LOG_TYPE_STATUS)
398 {
399 wType = GATE_SUCCEEDED(result_code) ? EVENTLOG_AUDIT_SUCCESS : EVENTLOG_AUDIT_FAILURE;
400 }
401 else if (log_type <= GATE_LOG_TYPE_WARN)
402 {
403 wType = EVENTLOG_WARNING_TYPE;
404 }
405 else if (log_type <= GATE_LOG_TYPE_ERROR)
406 {
407 wType = EVENTLOG_ERROR_TYPE;
408 }
409 else if (log_type <= GATE_LOG_TYPE_FATAL)
410 {
411 wType = EVENTLOG_ERROR_TYPE;
412 }
413
414 msg_buffer_used = 0;
415 if (GATE_FAILED(result_code))
416 {
417 msg_buffer_used += gate_win32_winstr_print_text(
418 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, _T("Result: "), 8);
419 msg_buffer_used += gate_win32_winstr_print_int32(
420 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, (gate_int32_t)result_code);
421 msg_buffer_used += gate_win32_winstr_print_text(
422 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, _T("\r\n"), 2);
423 }
424 if (native_code != 0)
425 {
426 msg_buffer_used += gate_win32_winstr_print_text(
427 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, _T("Code: "), 6);
428 msg_buffer_used += gate_win32_winstr_print_int32(
429 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, (gate_int32_t)native_code);
430 msg_buffer_used += gate_win32_winstr_print_text(
431 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, _T("\r\n"), 2);
432 }
433 if (!gate_string_is_empty(origin))
434 {
435 msg_buffer_used += gate_win32_winstr_print_text(
436 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, _T("Origin: "), 8);
437 msg_buffer_used += gate_win32_utf8_2_winstr(
438 origin->str, origin->length, &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used);
439 msg_buffer_used += gate_win32_winstr_print_text(
440 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, _T("\r\n"), 2);
441 }
442 if (!gate_string_is_empty(message))
443 {
444 msg_buffer_used += gate_win32_utf8_2_winstr(
445 message->str, message->length, &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used);
446 }
447
448 #if !defined(GATE_SYS_WINCE)
449 if (gate_platform.AdvReportEvent(impl->heventlog, wType, wCategory, dwEventId, NULL, 1, 0, &ptr_buffer, NULL))
450 {
451 ret = GATE_RESULT_OK;
452 }
453 #endif
454
455 } while (0);
456 return ret;
457 }
458
459 gate_result_t gate_syslog_start()
460 {
461 gate_result_t ret = GATE_RESULT_FAILED;
462 gate_result_t result;
463 char app_name[GATE_MAX_FILENAME_LENGTH] = GATE_INIT_EMPTY;
464 gate_size_t app_name_len = sizeof(app_name);
465
466 do
467 {
468 if (gate_atomic_flag_set(&global_syslogger_initialized))
469 {
470 ret = GATE_RESULT_OK;
471 break;
472 }
473 #if !defined(GATE_SYS_WINCE)
474 if (!gate_platform.AdvRegisterEventSource || !gate_platform.AdvDeregisterEventSource || !gate_platform.AdvReportEvent)
475 #endif
476 {
477 ret = GATE_RESULT_NOTSUPPORTED;
478 break;
479 }
480
481 result = gate_env_app_executable_name_str(app_name, &app_name_len);
482 if (GATE_FAILED(result))
483 {
484 app_name_len = GATE_STR_PRINT_TEXT(app_name, "gate-logs");
485 }
486
487 gate_win32_utf8_2_winstr(app_name, app_name_len, global_syslogger.app_name,
488 sizeof(global_syslogger.app_name) / sizeof(global_syslogger.app_name[0]));
489
490 #if !defined(GATE_SYS_WINCE)
491 global_syslogger.heventlog = gate_platform.AdvRegisterEventSource(NULL, global_syslogger.app_name);
492 #endif
493 if (NULL == global_syslogger.heventlog)
494 {
495 ret = GATE_RESULT_FAILED;
496 break;
497 }
498
499 global_syslogger.logger_base.log = &syslogger_log;
500 global_syslogger.logger_base.enabled = &syslogger_enabled;
501 ret = GATE_RESULT_OK;
502 } while (0);
503
504 if (GATE_FAILED(ret))
505 {
506 gate_atomic_flag_clear(&global_syslogger_initialized);
507 }
508
509 return ret;
510 }
511
512 gate_result_t gate_syslog_stop()
513 {
514 gate_result_t ret = GATE_RESULT_OK;
515 if (gate_atomic_flag_set(&global_syslogger_initialized))
516 {
517 #if !defined(GATE_SYS_WINCE)
518 gate_platform.AdvDeregisterEventSource(global_syslogger.heventlog);
519 #endif
520 }
521 gate_atomic_flag_clear(&global_syslogger_initialized);
522 return ret;
523 }
524
525 gate_logger_t const* gate_syslog_get()
526 {
527 gate_result_t result = gate_syslog_start();
528
529 if (GATE_SUCCEEDED(result))
530 {
531 return &global_syslogger.logger_base;
532 }
533 else
534 {
535 return gate_logger_get();
536 }
537 }
538
539 #endif /* GATE_IO_LOGGING_WINAPI_IMPL */
540
541
542 #if defined(GATE_IO_LOGGING_POSIX_IMPL)
543
544 #include <syslog.h>
545
546
547 typedef struct gate_syslogger_class
548 {
549 gate_logger_t logger_base;
550
551 } gate_syslogger_t;
552
553 static gate_syslogger_t global_syslogger = GATE_INIT_EMPTY;
554 static gate_atomic_flag_t global_syslogger_initialized = GATE_ATOMIC_FLAG_INIT;
555
556 static gate_bool_t syslogger_enabled(struct gate_logger_class const* logger, gate_enumint_t log_type)
557 {
558 (void)logger;
559 (void)log_type;
560 return true;
561 }
562
563 static gate_result_t syslogger_log(struct gate_logger_class const* logger,
564 gate_enumint_t log_type, gate_result_t result_code, gate_int32_t native_code,
565 gate_string_t const* origin, gate_string_t const* message)
566 {
567 gate_result_t ret = GATE_RESULT_FAILED;
568 /*gate_syslogger_t const* impl = (gate_syslogger_t const*)logger;*/
569 char priority = LOG_USER;
570 char msg_buffer[4096];
571 gate_size_t msg_buffer_capacity = sizeof(msg_buffer) / sizeof(msg_buffer[0]);
572 gate_size_t msg_buffer_used;
573
574 do
575 {
576 if (log_type <= GATE_LOG_TYPE_DEBUG)
577 {
578 /* debug messages should not be logged in system log */
579 return GATE_RESULT_OK;
580 }
581 else if (log_type <= GATE_LOG_TYPE_INFO)
582 {
583 priority |= LOG_INFO;
584 }
585 else if (log_type <= GATE_LOG_TYPE_STATUS)
586 {
587 priority |= LOG_NOTICE;
588 }
589 else if (log_type <= GATE_LOG_TYPE_WARN)
590 {
591 priority |= LOG_WARNING;
592 }
593 else if (log_type <= GATE_LOG_TYPE_ERROR)
594 {
595 priority |= LOG_ERR;
596 }
597 else if (log_type <= GATE_LOG_TYPE_FATAL)
598 {
599 priority |= LOG_ALERT;
600 }
601
602 msg_buffer_used = 0;
603 if (GATE_FAILED(result_code))
604 {
605 msg_buffer_used += gate_str_print_text(
606 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, "Result: ", 8);
607 msg_buffer_used += gate_str_print_int32(
608 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, (gate_int32_t)result_code);
609 msg_buffer_used += gate_str_print_text(
610 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, "\r\n", 2);
611 }
612 if (native_code != 0)
613 {
614 msg_buffer_used += gate_str_print_text(
615 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, "Code: ", 6);
616 msg_buffer_used += gate_str_print_int32(
617 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, (gate_int32_t)native_code);
618 msg_buffer_used += gate_str_print_text(
619 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, "\r\n", 2);
620 }
621 if (!gate_string_is_empty(origin))
622 {
623 msg_buffer_used += gate_str_print_text(
624 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, "Origin: ", 8);
625 msg_buffer_used += gate_str_print_text(
626 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, origin->str, origin->length);
627 msg_buffer_used += gate_str_print_text(
628 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, "\r\n", 2);
629 }
630 if (!gate_string_is_empty(message))
631 {
632 msg_buffer_used += gate_str_print_text(
633 &msg_buffer[msg_buffer_used], msg_buffer_capacity - msg_buffer_used, message->str, message->length);
634 }
635
636 syslog(priority, "%s", msg_buffer);
637
638 ret = GATE_RESULT_OK;
639 } while (0);
640 return ret;
641 }
642
643
644 gate_result_t gate_syslog_start()
645 {
646 gate_result_t ret = GATE_RESULT_FAILED;
647 gate_result_t result;
648 char app_name[GATE_MAX_FILENAME_LENGTH] = GATE_INIT_EMPTY;
649 char const* ptr_app_name = &app_name[0];
650 gate_size_t app_name_len = sizeof(app_name);
651
652 do
653 {
654 if (gate_atomic_flag_set(&global_syslogger_initialized))
655 {
656 ret = GATE_RESULT_OK;
657 break;
658 }
659
660 result = gate_env_app_executable_name_str(app_name, &app_name_len);
661 if (GATE_FAILED(result))
662 {
663 ptr_app_name = NULL;
664 }
665
666 openlog(ptr_app_name, LOG_NOWAIT | LOG_NDELAY | LOG_PID, LOG_USER);
667
668 global_syslogger.logger_base.log = &syslogger_log;
669 global_syslogger.logger_base.enabled = &syslogger_enabled;
670
671 ret = GATE_RESULT_OK;
672 } while (0);
673
674 if (GATE_FAILED(ret))
675 {
676 gate_atomic_flag_clear(&global_syslogger_initialized);
677 }
678
679 return ret;
680
681 }
682 gate_logger_t const* gate_syslog_get()
683 {
684 gate_result_t result = gate_syslog_start();
685
686 if (GATE_SUCCEEDED(result))
687 {
688 return &global_syslogger.logger_base;
689 }
690 else
691 {
692 return gate_logger_get();
693 }
694 }
695 gate_result_t gate_syslog_stop()
696 {
697 gate_result_t ret = GATE_RESULT_OK;
698 if (gate_atomic_flag_set(&global_syslogger_initialized))
699 {
700 closelog();
701 }
702 gate_atomic_flag_clear(&global_syslogger_initialized);
703 return ret;
704 }
705
706
707 #endif /* GATE_IO_LOGGING_POSIX_IMPL */
708
709
710
711
712 #if defined(GATE_IO_LOGGING_NO_IMPL)
713
714 gate_result_t gate_syslog_start()
715 {
716 return GATE_RESULT_OK;
717 }
718 gate_logger_t const* gate_syslog_get()
719 {
720 return gate_logger_get();
721 }
722 gate_result_t gate_syslog_stop()
723 {
724 return GATE_RESULT_OK;
725 }
726
727 #endif /* GATE_IO_LOGGING_NO_IMPL */
728