Coverage Report

Created: 2025-07-18 06:17

/src/open62541/plugins/ua_log_syslog.c
Line
Count
Source (jump to first uncovered line)
1
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
2
 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
3
 *
4
 *    Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
5
 */
6
7
#include <open62541/plugin/log_syslog.h>
8
#include <open62541/types.h>
9
10
#if defined(__linux__) || defined(__unix__)
11
12
#include <syslog.h>
13
#include <stdio.h>
14
#include "mp_printf.h"
15
16
const char *syslogLevelNames[6] = {"trace", "debug", "info",
17
                                   "warn", "error", "fatal"};
18
const char *syslogCategoryNames[UA_LOGCATEGORIES] =
19
    {"network", "channel", "session", "server", "client",
20
     "userland", "security", "eventloop", "pubsub", "discovery"};
21
22
#ifdef __clang__
23
__attribute__((__format__(__printf__, 4 , 0)))
24
#endif
25
static void
26
UA_Log_Syslog_log(void *context, UA_LogLevel level, UA_LogCategory category,
27
0
                  const char *msg, va_list args) {
28
    /* Assume that context is casted to UA_LogLevel */
29
0
    if(context != NULL && (UA_LogLevel)(uintptr_t)context > level)
30
0
        return;
31
32
0
    int priority = LOG_INFO;
33
0
    switch(level) {
34
0
    case UA_LOGLEVEL_DEBUG:
35
0
        priority = LOG_DEBUG;
36
0
        break;
37
0
    case UA_LOGLEVEL_INFO:
38
0
        priority = LOG_INFO;
39
0
        break;
40
0
    case UA_LOGLEVEL_WARNING:
41
0
        priority = LOG_WARNING;
42
0
        break;
43
0
    case UA_LOGLEVEL_ERROR:
44
0
        priority = LOG_ERR;
45
0
        break;
46
0
    case UA_LOGLEVEL_FATAL:
47
0
        priority = LOG_CRIT;
48
0
        break;
49
0
    case UA_LOGLEVEL_TRACE:
50
0
    default:
51
0
        return;
52
0
    }
53
54
0
    int logLevelSlot = ((int)level / 100) - 1;
55
0
    if(logLevelSlot < 0 || logLevelSlot > 5)
56
0
        logLevelSlot = 5; /* Set to fatal if the level is outside the range */
57
58
0
#define LOGBUFSIZE 512
59
0
    char logbuf[LOGBUFSIZE];
60
0
    int pos = mp_snprintf(logbuf, LOGBUFSIZE, "[%s/%s] ",
61
0
                          syslogLevelNames[logLevelSlot],
62
0
                          syslogCategoryNames[category]);
63
0
    if(pos < 0) {
64
0
        syslog(LOG_WARNING, "Log message too long for syslog");
65
0
        return;
66
0
    }
67
0
    pos = vsnprintf(&logbuf[pos], LOGBUFSIZE - (size_t)pos, msg, args);
68
0
    if(pos < 0) {
69
0
        syslog(LOG_WARNING, "Log message too long for syslog");
70
0
        return;
71
0
    }
72
73
0
    syslog(priority, "%s", logbuf);
74
0
}
75
76
static void
77
0
UA_Log_Syslog_clear(UA_Logger *logger) {
78
    /* closelog is optional. We don't use it as several loggers might be
79
     * instantiated in parallel. */
80
    /* closelog(); */
81
0
    UA_free(logger);
82
0
}
83
84
UA_Logger
85
0
UA_Log_Syslog(void) {
86
0
    return UA_Log_Syslog_withLevel(UA_LOGLEVEL_TRACE);
87
0
}
88
89
UA_Logger
90
0
UA_Log_Syslog_withLevel(UA_LogLevel minlevel) {
91
0
    UA_Logger logger = {UA_Log_Syslog_log, (void*)(uintptr_t)minlevel, NULL};
92
0
    return logger;
93
0
}
94
95
UA_Logger *
96
0
UA_Log_Syslog_new(UA_LogLevel minlevel) {
97
0
    UA_Logger *logger = (UA_Logger*)UA_malloc(sizeof(UA_Logger));
98
0
    if(!logger)
99
0
        return NULL;
100
0
    *logger = UA_Log_Syslog_withLevel(minlevel);
101
0
    logger->clear = UA_Log_Syslog_clear;
102
0
    return logger;
103
0
}
104
105
#endif