Coverage Report

Created: 2026-02-26 07:11

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
     "application", "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
55
0
#define LOGBUFSIZE 512
56
0
    char logbuf[LOGBUFSIZE];
57
0
    int pos = mp_snprintf(logbuf, LOGBUFSIZE, "[%s/%s] ",
58
0
                          syslogLevelNames[logLevelSlot],
59
0
                          syslogCategoryNames[category]);
60
0
    if(pos < 0) {
61
0
        syslog(LOG_WARNING, "Log message too long for syslog");
62
0
        return;
63
0
    }
64
0
    pos = mp_vsnprintf(&logbuf[pos], LOGBUFSIZE - (size_t)pos, msg, args);
65
0
    if(pos < 0) {
66
0
        syslog(LOG_WARNING, "Log message too long for syslog");
67
0
        return;
68
0
    }
69
70
0
    syslog(priority, "%s", logbuf);
71
0
}
72
73
static void
74
0
UA_Log_Syslog_clear(UA_Logger *logger) {
75
    /* closelog is optional. We don't use it as several loggers might be
76
     * instantiated in parallel. */
77
    /* closelog(); */
78
0
    UA_free(logger);
79
0
}
80
81
UA_Logger
82
0
UA_Log_Syslog(void) {
83
0
    return UA_Log_Syslog_withLevel(UA_LOGLEVEL_TRACE);
84
0
}
85
86
UA_Logger
87
0
UA_Log_Syslog_withLevel(UA_LogLevel minlevel) {
88
0
    UA_Logger logger = {UA_Log_Syslog_log, (void*)(uintptr_t)minlevel, NULL};
89
0
    return logger;
90
0
}
91
92
UA_Logger *
93
0
UA_Log_Syslog_new(UA_LogLevel minlevel) {
94
0
    UA_Logger *logger = (UA_Logger*)UA_malloc(sizeof(UA_Logger));
95
0
    if(!logger)
96
0
        return NULL;
97
0
    *logger = UA_Log_Syslog_withLevel(minlevel);
98
0
    logger->clear = UA_Log_Syslog_clear;
99
0
    return logger;
100
0
}
101
102
#endif