/*
* Copyright (C) 2015 by Multi-Tech Systems
*
* This file is part of libmts.
*
* libmts is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* libmts is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libmts. If not, see .
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace MTS;
const char* Logger::PrintLevel::OFF_LABEL = "OFF";
const char* Logger::PrintLevel::FATAL_LABEL = "FATAL";
const char* Logger::PrintLevel::ERROR_LABEL = "ERROR";
const char* Logger::PrintLevel::WARNING_LABEL = "WARNING";
const char* Logger::PrintLevel::INFO_LABEL = "INFO";
const char* Logger::PrintLevel::CONFIG_LABEL = "CONFIG";
const char* Logger::PrintLevel::DEBUG_LABEL = "DEBUG";
const char* Logger::PrintLevel::TRACE_LABEL = "TRACE";
const char* Logger::PrintLevel::MAXIMUM_LABEL = "MAXIMUM";
const int Logger::PrintLevel::OFF_LEVEL = 0;
const int Logger::PrintLevel::MINIMUM_LEVEL = 1;
const int Logger::PrintLevel::FATAL_LEVEL = 1;
const int Logger::PrintLevel::ERROR_LEVEL = 10;
const int Logger::PrintLevel::WARNING_LEVEL = 20;
const int Logger::PrintLevel::INFO_LEVEL = 30;
const int Logger::PrintLevel::CONFIG_LEVEL = 40;
const int Logger::PrintLevel::DEBUG_LEVEL = 50;
const int Logger::PrintLevel::TRACE_LEVEL = 60;
const int Logger::PrintLevel::MAXIMUM_LEVEL = 100;
volatile int Logger::m_iPrintLevel = Logger::PrintLevel::MAXIMUM_LEVEL;
std::string Logger::m_sPrintLevel = Logger::PrintLevel::MAXIMUM_LABEL;
Logger::PrintMode Logger::m_eMode = Logger::PrintMode::STDOUT_ONLY;
FILE* Logger::m_pFile = NULL;
int Logger::m_iLogFacility = -1;
Lock Logger::m_oPrintLock;
std::string Logger::m_sIdent;
std::string Logger::m_sFileName;
int Logger::getPrintLevel() {
return m_iPrintLevel;
}
const std::string& Logger::getPrintLevelString() {
if (m_iPrintLevel == PrintLevel::OFF_LEVEL)
m_sPrintLevel = std::string(PrintLevel::OFF_LABEL);
else if (m_iPrintLevel == PrintLevel::FATAL_LEVEL)
m_sPrintLevel = std::string(PrintLevel::FATAL_LABEL);
else if (m_iPrintLevel > PrintLevel::FATAL_LEVEL && m_iPrintLevel <= PrintLevel::ERROR_LEVEL)
m_sPrintLevel = std::string(PrintLevel::ERROR_LABEL);
else if (m_iPrintLevel > PrintLevel::ERROR_LEVEL && m_iPrintLevel <= PrintLevel::WARNING_LEVEL)
m_sPrintLevel = std::string(PrintLevel::WARNING_LABEL);
else if (m_iPrintLevel > PrintLevel::WARNING_LEVEL && m_iPrintLevel <= PrintLevel::INFO_LEVEL)
m_sPrintLevel = std::string(PrintLevel::INFO_LABEL);
else if (m_iPrintLevel > PrintLevel::INFO_LEVEL && m_iPrintLevel <= PrintLevel::CONFIG_LEVEL)
m_sPrintLevel = std::string(PrintLevel::CONFIG_LABEL);
else if (m_iPrintLevel > PrintLevel::CONFIG_LEVEL && m_iPrintLevel <= PrintLevel::DEBUG_LEVEL)
m_sPrintLevel = std::string(PrintLevel::DEBUG_LABEL);
else if (m_iPrintLevel > PrintLevel::DEBUG_LEVEL && m_iPrintLevel <= PrintLevel::TRACE_LEVEL)
m_sPrintLevel = std::string(PrintLevel::TRACE_LABEL);
else
m_sPrintLevel = std::string(PrintLevel::MAXIMUM_LABEL);
return m_sPrintLevel;
}
void Logger::setPrintLevel(int32_t level, bool silent) {
m_iPrintLevel = level;
if (!silent) {
printf(level, "Logger Level Changed to %d\n", level);
}
}
bool Logger::isPrintable(int32_t level) {
int32_t currentLevel = getPrintLevel();
return (level <= currentLevel) && (currentLevel > PrintLevel::OFF_LEVEL);
}
int32_t Logger::syslogPrintLevelConversion(const int32_t& level) {
if (level < 10) {
return LOG_EMERG;
} else if (level < 20) {
return LOG_ERR;
} else if (level < 30) {
return LOG_WARNING;
} else if (level < 50) {
return LOG_INFO;
} else {
return LOG_DEBUG;
}
}
void Logger::printMessage(const int32_t& level, const char* label, const char* format, va_list argptr) {
m_oPrintLock.lock();
switch (m_eMode) {
case Logger::PrintMode::STDOUT_ONLY:
::printf("%s|%s|", MTS::Text::time(MTS::System::timeMicros()).c_str(), label);
vprintf(format, argptr);
::printf("\n");
break;
case Logger::PrintMode::FILE_ONLY:
fprintf(m_pFile, "%s|%s| ", MTS::Text::time(MTS::System::timeMicros()).c_str(), label);
vfprintf(m_pFile, format, argptr);
fprintf(m_pFile, "\n");
fflush(m_pFile);
break;
case Logger::PrintMode::SYSLOG_ONLY:
if (level <= Logger::PrintLevel::TRACE_LEVEL) {
vsyslog(syslogPrintLevelConversion(level), format, argptr);
}
break;
case Logger::PrintMode::STDOUT_AND_FILE: {
const std::string timestr(MTS::Text::time(MTS::System::timeMicros()));
va_list argptr2;
va_copy(argptr2, argptr);
::printf("%s|%s|", timestr.c_str(), label);
vprintf(format, argptr);
::printf("\n");
fprintf(m_pFile, "%s|%s| ", timestr.c_str(), label);
vfprintf(m_pFile, format, argptr2);
fprintf(m_pFile, "\n");
fflush(m_pFile);
va_end(argptr2);
}
break;
case Logger::PrintMode::STDOUT_AND_SYSLOG: {
if (level <= Logger::PrintLevel::TRACE_LEVEL) {
va_list argptr2;
va_copy(argptr2, argptr);
vsyslog(syslogPrintLevelConversion(level), format, argptr2);
va_end(argptr2);
}
::printf("%s|", MTS::Text::time(MTS::System::timeMicros()).c_str());
::printf("%s|", label);
vprintf(format, argptr);
::printf("\n");
}
break;
case Logger::PrintMode::NO_PRINTING:
default:
break;
}
m_oPrintLock.unlock();
}
void Logger::printfFatal(const char* format, ...) {
if (isPrintable(PrintLevel::FATAL_LEVEL)) {
va_list argptr;
va_start(argptr, format);
printMessage(PrintLevel::FATAL_LEVEL, PrintLevel::FATAL_LABEL, format, argptr);
va_end(argptr);
}
}
void Logger::printfError(const char* format, ...) {
if (isPrintable(PrintLevel::ERROR_LEVEL)) {
va_list argptr;
va_start(argptr, format);
printMessage(PrintLevel::ERROR_LEVEL, PrintLevel::ERROR_LABEL, format, argptr);
va_end(argptr);
}
}
void Logger::printfWarning(const char* format, ...) {
if (isPrintable(PrintLevel::WARNING_LEVEL)) {
va_list argptr;
va_start(argptr, format);
printMessage(PrintLevel::WARNING_LEVEL, PrintLevel::WARNING_LABEL, format, argptr);
va_end(argptr);
}
}
void Logger::printfInfo(const char* format, ...) {
if (isPrintable(PrintLevel::INFO_LEVEL)) {
va_list argptr;
va_start(argptr, format);
printMessage(PrintLevel::INFO_LEVEL, PrintLevel::INFO_LABEL, format, argptr);
va_end(argptr);
}
}
void Logger::printfConfig(const char* format, ...) {
if (isPrintable(PrintLevel::CONFIG_LEVEL)) {
va_list argptr;
va_start(argptr, format);
printMessage(PrintLevel::CONFIG_LEVEL, PrintLevel::CONFIG_LABEL, format, argptr);
va_end(argptr);
}
}
void Logger::printfDebug(const char* format, ...) {
if (isPrintable(PrintLevel::DEBUG_LEVEL)) {
va_list argptr;
va_start(argptr, format);
printMessage(PrintLevel::DEBUG_LEVEL, PrintLevel::DEBUG_LABEL, format, argptr);
va_end(argptr);
}
}
void Logger::printfTrace(const char* format, ...) {
if (isPrintable(PrintLevel::TRACE_LEVEL)) {
va_list argptr;
va_start(argptr, format);
printMessage(PrintLevel::TRACE_LEVEL, PrintLevel::TRACE_LABEL, format, argptr);
va_end(argptr);
}
}
void Logger::printfGeneric(int level, const char* label, const char* format, ...) {
va_list argptr;
va_start(argptr, format);
printMessage(level, label, format, argptr);
va_end(argptr);
}
void Logger::printf(int level, const char* format, ...) {
if (isPrintable(level)) {
va_list argptr;
va_start(argptr, format);
m_oPrintLock.lock();
vprintf(format, argptr);
m_oPrintLock.unlock();
va_end(argptr);
}
}
void Logger::printf(const char* format, ...) {
if (isPrintable(PrintLevel::MAXIMUM_LEVEL)) {
va_list argptr;
va_start(argptr, format);
m_oPrintLock.lock();
vprintf(format, argptr);
m_oPrintLock.unlock();
va_end(argptr);
}
}
bool Logger::setup(const PrintMode& mode) {
m_oPrintLock.lock();
m_eMode = mode;
m_oPrintLock.unlock();
return true;
}
bool Logger::setup(const PrintMode& mode, const std::string& filename) {
/* close the handle and reopen it each time setup() is called in case
* we are being used with programs like logrotate, etc
*
* if the file is different, switch to the new file */
m_oPrintLock.lock();
if (m_pFile) {
fclose(m_pFile);
}
if (m_sFileName != filename) {
m_sFileName = filename;
}
m_pFile = fopen(m_sFileName.c_str(), "a");
m_iLogFacility = -1;
m_oPrintLock.unlock();
if (!m_pFile) {
fprintf(stderr, "Error opening logfile %s\n", m_sFileName.c_str());
return false;
}
m_eMode = mode;
return true;
}
bool Logger::setup(const PrintMode& mode, const std::string& ident, const int& option, const int& facility) {
m_oPrintLock.lock();
m_pFile = NULL;
m_sFileName = "";
m_iLogFacility = facility;
m_sIdent = ident;
m_eMode = mode;
m_oPrintLock.unlock();
openlog(m_sIdent.c_str(), option, m_iLogFacility);
return true;
}