Coverage Report

Created: 2025-10-10 07:13

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