105 lines
2.9 KiB
C
105 lines
2.9 KiB
C
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
|
|
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
|
|
*
|
|
* Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
|
|
*/
|
|
|
|
#include <open62541/plugin/log_syslog.h>
|
|
#include <open62541/types.h>
|
|
|
|
#if defined(__linux__) || defined(__unix__)
|
|
|
|
#include <syslog.h>
|
|
#include <stdio.h>
|
|
|
|
const char *syslogLevelNames[6] = {"trace", "debug", "info",
|
|
"warn", "error", "fatal"};
|
|
const char *syslogCategoryNames[UA_LOGCATEGORIES] =
|
|
{"network", "channel", "session", "server", "client",
|
|
"userland", "securitypolicy", "eventloop", "pubsub", "discovery"};
|
|
|
|
#ifdef __clang__
|
|
__attribute__((__format__(__printf__, 4 , 0)))
|
|
#endif
|
|
static void
|
|
UA_Log_Syslog_log(void *context, UA_LogLevel level, UA_LogCategory category,
|
|
const char *msg, va_list args) {
|
|
/* Assume that context is casted to UA_LogLevel */
|
|
if(context != NULL && (UA_LogLevel)(uintptr_t)context > level)
|
|
return;
|
|
|
|
int priority = LOG_INFO;
|
|
switch(level) {
|
|
case UA_LOGLEVEL_DEBUG:
|
|
priority = LOG_DEBUG;
|
|
break;
|
|
case UA_LOGLEVEL_INFO:
|
|
priority = LOG_INFO;
|
|
break;
|
|
case UA_LOGLEVEL_WARNING:
|
|
priority = LOG_WARNING;
|
|
break;
|
|
case UA_LOGLEVEL_ERROR:
|
|
priority = LOG_ERR;
|
|
break;
|
|
case UA_LOGLEVEL_FATAL:
|
|
priority = LOG_CRIT;
|
|
break;
|
|
case UA_LOGLEVEL_TRACE:
|
|
default:
|
|
return;
|
|
}
|
|
|
|
int logLevelSlot = ((int)level / 100) - 1;
|
|
if(logLevelSlot < 0 || logLevelSlot > 5)
|
|
logLevelSlot = 5; /* Set to fatal if the level is outside the range */
|
|
|
|
#define LOGBUFSIZE 512
|
|
char logbuf[LOGBUFSIZE];
|
|
int pos = snprintf(logbuf, LOGBUFSIZE, "[%s/%s] ",
|
|
syslogLevelNames[logLevelSlot],
|
|
syslogCategoryNames[category]);
|
|
if(pos < 0) {
|
|
syslog(LOG_WARNING, "Log message too long for syslog");
|
|
return;
|
|
}
|
|
pos = vsnprintf(&logbuf[pos], LOGBUFSIZE - (size_t)pos, msg, args);
|
|
if(pos < 0) {
|
|
syslog(LOG_WARNING, "Log message too long for syslog");
|
|
return;
|
|
}
|
|
|
|
syslog(priority, "%s", logbuf);
|
|
}
|
|
|
|
static void
|
|
UA_Log_Syslog_clear(UA_Logger *logger) {
|
|
/* closelog is optional. We don't use it as several loggers might be
|
|
* instantiated in parallel. */
|
|
/* closelog(); */
|
|
UA_free(logger);
|
|
}
|
|
|
|
UA_Logger
|
|
UA_Log_Syslog(void) {
|
|
return UA_Log_Syslog_withLevel(UA_LOGLEVEL_TRACE);
|
|
}
|
|
|
|
UA_Logger
|
|
UA_Log_Syslog_withLevel(UA_LogLevel minlevel) {
|
|
UA_Logger logger = {UA_Log_Syslog_log, (void*)(uintptr_t)minlevel, NULL};
|
|
return logger;
|
|
}
|
|
|
|
UA_Logger *
|
|
UA_Log_Syslog_new(UA_LogLevel minlevel) {
|
|
UA_Logger *logger = (UA_Logger*)UA_malloc(sizeof(UA_Logger));
|
|
if(!logger)
|
|
return NULL;
|
|
*logger = UA_Log_Syslog_withLevel(minlevel);
|
|
logger->clear = UA_Log_Syslog_clear;
|
|
return logger;
|
|
}
|
|
|
|
#endif
|