Commit 4bd1a200 authored by Adrien Oliva's avatar Adrien Oliva

feat(conf): Allow user to set conf variable

Configuration of logger is done by setting 2 environment variables: one
to give log destination and one to give log level.
By default, destination is given by content of LOGDESTINATION
environment variable, and level is given by content of LOGLEVEL
environment variable.
Those 2 names can be customized to any string user wants.
parent f17259c2
Pipeline #217 passed with stages
in 1 minute and 19 seconds
......@@ -6,6 +6,7 @@ SUBDIRS = yaplog
lib_LTLIBRARIES = libyaplog.la
libyaplog_la_SOURCES = yaplog.h
libyaplog_la_SOURCES += yaplog.cpp
libyaplog_la_LIBADD = yaplog/libinternalyaplog.la
include_HEADERS = yaplog.h
......
#include "yaplog.h"
__attribute__((constructor)) static void yaplog_static_init()
{
logger::setDestinationVariable(YAPLOG_DEST_DEFAULT);
logger::setLevelVariable(YAPLOG_LEVEL_DEFAULT);
}
__attribute__((destructor)) static void yaplog_static_deinit()
{
logger::unsetDestinationVariable();
logger::unsetLevelVariable();
}
void logger::setDestinationVariable(const char *dest)
{
InternalLog::setDestinationVariable(dest);
}
void logger::setLevelVariable(const char *level)
{
InternalLog::setLevelVariable(level);
}
void logger::unsetDestinationVariable()
{
InternalLog::unsetDestinationVariable();
}
void logger::unsetLevelVariable()
{
InternalLog::unsetLevelVariable();
}
......@@ -87,4 +87,16 @@
logger::InternalLog::getOstream(), \
logger::InternalLog::getSystemLevel())
namespace logger {
/**
* @brief Set environment variable to check for log file destination.
*
* @param dest New destination environement variable
*/
void setDestinationVariable(const char *dest);
void setLevelVariable(const char *level);
void unsetDestinationVariable();
void unsetLevelVariable();
};
#endif /* end of include guard: YAPLOG_H_UGV90DZC */
#include "internallog.h"
#include "yaplog.h"
#include <iostream>
#include <cstring>
......@@ -6,6 +6,9 @@
using namespace logger;
char *InternalLog::s_destination = NULL;
char *InternalLog::s_level = NULL;
InternalLog::InternalLog(log_level level, const log_location &loc,
std::ostream *destination,
log_level system_level)
......@@ -26,13 +29,6 @@ InternalLog::~InternalLog()
closeOstream(m_output);
}
/**
* @brief Convert a log level to a single character.
*
* @param l Loglevel to convert.
*
* @return Single character symbolizes log level.
*/
char InternalLog::char_from_level(enum log_level l)
{
switch (l) {
......@@ -59,21 +55,6 @@ char InternalLog::char_from_level(enum log_level l)
}
}
/**
* @brief Prepare and print log prefix.
*
* Any log use the following prefix:
* - "[X] file:line(function) "
*
* where:
* - X is one of the following character ('F' for fatal, 'A' for
* alert, 'C' for critical, 'E' for error, 'W' for warning, 'N'
* for notice, 'I' for information, 'D' for debug, 'T' for trace
* or a space for any other level.
* - file is the name of the file where log append.
* - line is the line number where log append.
* - function is the function name where log append.
*/
void InternalLog::print_header()
{
(*m_output) << "[" << char_from_level(m_level) << "] "
......@@ -82,64 +63,44 @@ void InternalLog::print_header()
<< m_location.m_function << ") ";
}
/**
* @brief Get configured output stream where log are put.
*
* @return Output stream to be used by logger, depending on
* `CSER_LOGDESTINATION` environment variable.
*
* If no environment variable is set, default is std::cerr.
* When `CSER_LOGDESTINATION` is set to `stdout` or `stderr`, stream
* is respectively redirected to std::cout or std::cerr, otherwise,
* logger considers variable content as a filename and try to open
* it in append mode. If file does not exists, logger create file.
* Upon failure, logger falls back to std::cerr.
*/
std::ostream *InternalLog::getOstream()
std::ostream *InternalLog::getOstream(const char *destination)
{
const char *cser_logdestination = std::getenv("CSER_LOGDESTINATION");
if (cser_logdestination == NULL) {
if (destination == NULL) {
return new std::ostream(std::cerr.rdbuf());
} else {
if (strcmp(cser_logdestination, "stderr") == 0) {
if (strcmp(destination, "stderr") == 0) {
return new std::ostream(std::cerr.rdbuf());
} else if (strcmp(cser_logdestination, "stdout") == 0) {
} else if (strcmp(destination, "stdout") == 0) {
return new std::ostream(std::cout.rdbuf());
} else {
return new std::ofstream(cser_logdestination,
std::ofstream::app);
std::ofstream *ofs;
ofs = new std::ofstream(destination, std::ofstream::app);
if (ofs != NULL && ofs->is_open()) {
return ofs;
} else {
std::cerr << "Fail to open " << destination << std::endl;
delete ofs;
return new std::ostream(std::cerr.rdbuf());
}
}
}
return new std::ostream(std::cerr.rdbuf());
}
/**
* @brief Close the given output stream properly.
*
* @param os Output stream to close.
*/
std::ostream *InternalLog::getOstream()
{
const char *logdestination = std::getenv(getDestinationVariable());
return getOstream(logdestination);
}
void InternalLog::closeOstream(std::ostream *os)
{
delete os;
}
/**
* @brief Get configured logger level to show.
*
* @return Log level used by logger, depending on `CSER_LOGLEVEL`
* environment variable.
*
* When `CSER_LOGLEVEL` is set to any number between 0 and 9, logger
* directly use the log level and print to output every log message
* with level lower or equal to the given system log level.
* If `CSER_LOGLEVEL` is set to a number lower than 0, 0 is used.
* If `CSER_LOGLEVEL` is set to a number higher than 9, 9 is used.
* If `CSER_LOGLEVEL` is not set to a number, 0 is used.
* If no environment variable is set, default is 0.
*/
log_level InternalLog::getSystemLevel()
{
const char *cser_loglevel = std::getenv("CSER_LOGLEVEL");
const char *cser_loglevel = std::getenv(getLevelVariable());
if (cser_loglevel == NULL) {
return log_level::none;
} else {
......@@ -155,3 +116,39 @@ log_level InternalLog::getSystemLevel()
}
}
}
const char *InternalLog::getDestinationVariable()
{
return s_destination ? s_destination : YAPLOG_DEST_DEFAULT;
}
const char *InternalLog::getLevelVariable()
{
return s_level ? s_level : YAPLOG_LEVEL_DEFAULT;
}
void InternalLog::setDestinationVariable(const char *dest)
{
unsetDestinationVariable();
s_destination = strdup(dest);
}
void InternalLog::setLevelVariable(const char *level)
{
unsetLevelVariable();
s_level = strdup(level);
}
void InternalLog::unsetDestinationVariable()
{
if (s_destination != NULL)
free(static_cast<void *>(s_destination));
s_destination = NULL;
}
void InternalLog::unsetLevelVariable()
{
if (s_level != NULL)
free(static_cast<void *>(s_level));
s_level = NULL;
}
......@@ -6,6 +6,9 @@
#include <ostream>
#define YAPLOG_LEVEL_DEFAULT "LOGLEVEL"
#define YAPLOG_DEST_DEFAULT "LOGDESTINATION"
namespace logger {
/**
......@@ -74,15 +77,26 @@ namespace logger {
*/
void print_header();
protected:
/**
* @brief Get configured output stream where log are pat.
*
* @param destination Environment variable to use.
*
* @return Output stream to be used by logger, depending on
* environment variable given by `destination`.
*/
static std::ostream *getOstream(const char *destination);
public:
/**
* @brief Get configured output stream where log are put.
*
* @return Output stream to be used by logger, depending on
* `CSER_LOGDESTINATION` environment variable.
* configured environment variable.
*
* If no environment variable is set, default is std::cerr.
* When `CSER_LOGDESTINATION` is set to `stdout` or `stderr`, stream
* When configured env var is set to `stdout` or `stderr`, stream
* is respectively redirected to std::cout or std::cerr, otherwise,
* logger considers variable content as a filename and try to open
* it in append mode. If file does not exists, logger create file.
......@@ -100,15 +114,15 @@ namespace logger {
/**
* @brief Get configured logger level to show.
*
* @return Log level used by logger, depending on `CSER_LOGLEVEL`
* @return Log level used by logger, depending on configured
* environment variable.
*
* When `CSER_LOGLEVEL` is set to any number between 0 and 9, logger
* directly use the log level and print to output every log message
* with level lower or equal to the given system log level.
* If `CSER_LOGLEVEL` is set to a number lower than 0, 0 is used.
* If `CSER_LOGLEVEL` is set to a number higher than 9, 9 is used.
* If `CSER_LOGLEVEL` is not set to a number, 0 is used.
* When configured env var is set to any number between 0 and 9,
* logger directly use the log level and print to output every log
* message with level lower or equal to the given system log level.
* If `LOGLEVEL` is set to a number lower than 0, 0 is used.
* If `LOGLEVEL` is set to a number higher than 9, 9 is used.
* If `LOGLEVEL` is not set to a number, 0 is used.
* If no environment variable is set, default is 0.
*/
static log_level getSystemLevel();
......@@ -130,6 +144,52 @@ namespace logger {
* @brief System log level.
*/
log_level m_systemlevel;
protected:
/**
* @brief Get environment variable to check for log file destination.
*
* @return Destination environment variable
*/
static const char *getDestinationVariable();
/**
* @brief Get environment variable to check for log level to show.
*
* @return Level environment variable
*/
static const char *getLevelVariable();
/**
* @brief Environment variable name of log destination
* configuration.
*/
static char *s_destination;
/**
* @brief Environment variable name of log level configuration.
*/
static char *s_level;
public:
/**
* @brief Set environment variable to check for log file destination.
*
* @param dest New destination environement variable
*/
static void setDestinationVariable(const char *dest);
/**
* @brief Set environment variable to check for log level.
*
* @param level New level environement variable
*/
static void setLevelVariable(const char *level);
/**
* @brief Unset environment variable to check for log file destination.
*/
static void unsetDestinationVariable();
/**
* @brief Unset environment variable to check for log level.
*/
static void unsetLevelVariable();
};
/**
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment