mirror of
https://github.com/Fishwaldo/Fuzzylite.git
synced 2025-03-15 19:31:36 +00:00
build LoggerCpp into FL Sources
This commit is contained in:
parent
9b11338dce
commit
ee1a7fee77
50 changed files with 1903 additions and 4049 deletions
|
@ -77,7 +77,7 @@ if(NOT FL_BACKTRACE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(.)
|
include_directories(.)
|
||||||
include_directories ("${PROJECT_SOURCE_DIR}/LoggerCpp/include/")
|
include_directories ("${PROJECT_SOURCE_DIR}/fl/")
|
||||||
add_definitions (-std=c++0x) # -std=c++11
|
add_definitions (-std=c++0x) # -std=c++11
|
||||||
|
|
||||||
file(STRINGS FL_HEADERS fl-headers)
|
file(STRINGS FL_HEADERS fl-headers)
|
||||||
|
@ -91,29 +91,29 @@ message("${exepath}")
|
||||||
|
|
||||||
# add sources of the logger library as a "LoggerCpp" library
|
# add sources of the logger library as a "LoggerCpp" library
|
||||||
add_library (LoggerCpp STATIC
|
add_library (LoggerCpp STATIC
|
||||||
LoggerCpp/include/LoggerCpp/Channel.h
|
fl/LoggerCpp/Channel.h
|
||||||
LoggerCpp/include/LoggerCpp/Config.h
|
fl/LoggerCpp/Config.h
|
||||||
LoggerCpp/include/LoggerCpp/DateTime.h
|
fl/LoggerCpp/DateTime.h
|
||||||
LoggerCpp/include/LoggerCpp/Exception.h
|
fl/LoggerCpp/Exception.h
|
||||||
LoggerCpp/include/LoggerCpp/Formatter.h
|
fl/LoggerCpp/Formatter.h
|
||||||
LoggerCpp/include/LoggerCpp/Log.h
|
fl/LoggerCpp/Log.h
|
||||||
LoggerCpp/include/LoggerCpp/Logger.h
|
fl/LoggerCpp/Logger.h
|
||||||
LoggerCpp/include/LoggerCpp/LoggerCpp.h
|
fl/LoggerCpp/LoggerCpp.h
|
||||||
LoggerCpp/include/LoggerCpp/Manager.h
|
fl/LoggerCpp/Manager.h
|
||||||
LoggerCpp/include/LoggerCpp/Output.h
|
fl/LoggerCpp/Output.h
|
||||||
LoggerCpp/include/LoggerCpp/OutputConsole.h
|
fl/LoggerCpp/OutputConsole.h
|
||||||
LoggerCpp/include/LoggerCpp/OutputDebug.h
|
fl/LoggerCpp/OutputDebug.h
|
||||||
LoggerCpp/include/LoggerCpp/OutputFile.h
|
fl/LoggerCpp/OutputFile.h
|
||||||
LoggerCpp/include/LoggerCpp/shared_ptr.hpp
|
fl/LoggerCpp/shared_ptr.hpp
|
||||||
LoggerCpp/include/LoggerCpp/Utils.h
|
fl/LoggerCpp/Utils.h
|
||||||
LoggerCpp/src/Config.cpp
|
src/LoggerCpp/Config.cpp
|
||||||
LoggerCpp/src/DateTime.cpp
|
src/LoggerCpp/DateTime.cpp
|
||||||
LoggerCpp/src/Log.cpp
|
src/LoggerCpp/Log.cpp
|
||||||
LoggerCpp/src/Logger.cpp
|
src/LoggerCpp/Logger.cpp
|
||||||
LoggerCpp/src/Manager.cpp
|
src/LoggerCpp/Manager.cpp
|
||||||
LoggerCpp/src/OutputConsole.cpp
|
src/LoggerCpp/OutputConsole.cpp
|
||||||
LoggerCpp/src/OutputDebug.cpp
|
src/LoggerCpp/OutputDebug.cpp
|
||||||
LoggerCpp/src/OutputFile.cpp
|
src/LoggerCpp/OutputFile.cpp
|
||||||
)
|
)
|
||||||
#set_target_properties(LoggerCpp PROPERTIES COMPILE_FLAGS -fvisibility=hidden)
|
#set_target_properties(LoggerCpp PROPERTIES COMPILE_FLAGS -fvisibility=hidden)
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ install(TARGETS fl-bin fl-shared
|
||||||
)
|
)
|
||||||
|
|
||||||
install(DIRECTORY fl/ DESTINATION include/fl)
|
install(DIRECTORY fl/ DESTINATION include/fl)
|
||||||
install(DIRECTORY LoggerCpp/include/LoggerCpp DESTINATION include)
|
#install(DIRECTORY DESTINATION include)
|
||||||
|
|
||||||
#if(WIN32)
|
#if(WIN32)
|
||||||
# set(fl-suffix)
|
# set(fl-suffix)
|
||||||
|
|
27
LoggerCpp/.gitignore
vendored
27
LoggerCpp/.gitignore
vendored
|
@ -1,27 +0,0 @@
|
||||||
Debug
|
|
||||||
Release
|
|
||||||
build
|
|
||||||
lib
|
|
||||||
doc
|
|
||||||
|
|
||||||
CMakeCache.txt
|
|
||||||
CMakeFiles
|
|
||||||
*.cmake
|
|
||||||
*.dir
|
|
||||||
|
|
||||||
*.sln
|
|
||||||
*.vcproj*
|
|
||||||
*.vcxproj*
|
|
||||||
*.ncb
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*sdf
|
|
||||||
*ipch
|
|
||||||
*.make
|
|
||||||
Makefile
|
|
||||||
.settings
|
|
||||||
|
|
||||||
*~
|
|
||||||
|
|
||||||
log*.txt
|
|
||||||
core
|
|
|
@ -1,106 +0,0 @@
|
||||||
# Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
#
|
|
||||||
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
# or copy at http://opensource.org/licenses/MIT)
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.6)
|
|
||||||
project(LoggerCpp)
|
|
||||||
|
|
||||||
# Define useful variables to handle OS/Compiler differences
|
|
||||||
if (MSVC)
|
|
||||||
set(CPPLINT_ARG_OUTPUT "--output=vs7")
|
|
||||||
set(CPPCHECK_ARG_TEMPLATE "--template=vs")
|
|
||||||
set(DEV_NULL "NUL")
|
|
||||||
set(SYSTEM_LIBRARIES "")
|
|
||||||
add_definitions (/D_CRT_SECURE_NO_WARNINGS)
|
|
||||||
else()
|
|
||||||
set(CPPLINT_ARG_OUTPUT "--output=eclipse")
|
|
||||||
set(CPPCHECK_ARG_TEMPLATE "--template=gcc")
|
|
||||||
set(DEV_NULL "/dev/null")
|
|
||||||
set(SYSTEM_LIBRARIES "rt")
|
|
||||||
add_definitions (-std=c++0x) # -std=c++11
|
|
||||||
endif()
|
|
||||||
set(CPPLINT_ARG_VERBOSE "--verbose=3")
|
|
||||||
set(CPPLINT_ARG_LINELENGTH "--linelength=120")
|
|
||||||
|
|
||||||
# All includes are relative to the "include" directory
|
|
||||||
include_directories ("${PROJECT_SOURCE_DIR}/include")
|
|
||||||
|
|
||||||
# add sources of the logger library as a "LoggerCpp" library
|
|
||||||
add_library (LoggerCpp
|
|
||||||
include/LoggerCpp/Channel.h
|
|
||||||
include/LoggerCpp/Config.h
|
|
||||||
include/LoggerCpp/DateTime.h
|
|
||||||
include/LoggerCpp/Exception.h
|
|
||||||
include/LoggerCpp/Formatter.h
|
|
||||||
include/LoggerCpp/Log.h
|
|
||||||
include/LoggerCpp/Logger.h
|
|
||||||
include/LoggerCpp/LoggerCpp.h
|
|
||||||
include/LoggerCpp/Manager.h
|
|
||||||
include/LoggerCpp/Output.h
|
|
||||||
include/LoggerCpp/OutputConsole.h
|
|
||||||
include/LoggerCpp/OutputDebug.h
|
|
||||||
include/LoggerCpp/OutputFile.h
|
|
||||||
include/LoggerCpp/shared_ptr.hpp
|
|
||||||
include/LoggerCpp/Utils.h
|
|
||||||
src/Config.cpp
|
|
||||||
src/DateTime.cpp
|
|
||||||
src/Log.cpp
|
|
||||||
src/Logger.cpp
|
|
||||||
src/Manager.cpp
|
|
||||||
src/OutputConsole.cpp
|
|
||||||
src/OutputDebug.cpp
|
|
||||||
src/OutputFile.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Optional additional targets:
|
|
||||||
|
|
||||||
option(LOGGERCPP_BUILD_EXAMPLE "Build the example of LoggerCpp." ON)
|
|
||||||
if (LOGGERCPP_BUILD_EXAMPLE)
|
|
||||||
# add the example executable, linked with the LoggerCpp library
|
|
||||||
add_executable(LoggerCpp_Example examples/Main.cpp)
|
|
||||||
target_link_libraries (LoggerCpp_Example LoggerCpp ${SYSTEM_LIBRARIES})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
option(LOGGERCPP_RUN_CPPLINT "Run cpplint.py tool for Google C++ StyleGuide." ON)
|
|
||||||
if (LOGGERCPP_RUN_CPPLINT)
|
|
||||||
# List all sources/headers files for cpplint:
|
|
||||||
# adding a file still require explicittly modifing the CMakeLists.txt
|
|
||||||
# so that CMake know that it should rebuild the project (it is best practice)
|
|
||||||
file(GLOB all_source_files
|
|
||||||
"${PROJECT_SOURCE_DIR}/include/LoggerCpp/*.h"
|
|
||||||
"${PROJECT_SOURCE_DIR}/src/*.cpp"
|
|
||||||
)
|
|
||||||
|
|
||||||
# add a cpplint target to the "all" target
|
|
||||||
add_custom_target(LoggerCpp_cpplint
|
|
||||||
ALL
|
|
||||||
COMMAND python cpplint.py ${CPPLINT_ARG_OUTPUT} ${CPPLINT_ARG_VERBOSE} ${all_source_files}
|
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(LOGGERCPP_RUN_CPPCHECK "Run cppcheck C++ static analysis tool." ON)
|
|
||||||
if (LOGGERCPP_RUN_CPPCHECK)
|
|
||||||
# add a cppcheck target to the "all" target
|
|
||||||
add_custom_target(LoggerCpp_cppcheck
|
|
||||||
ALL
|
|
||||||
COMMAND cppcheck -j 4 cppcheck --enable=style --quiet ${CPPCHECK_ARG_TEMPLATE} ${PROJECT_SOURCE_DIR}/src
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT DEFINED ENV{TRAVIS})
|
|
||||||
option(LOGGERCPP_RUN_DOXYGEN "Run Doxygen C++ documentation tool." ON)
|
|
||||||
if (LOGGERCPP_RUN_DOXYGEN)
|
|
||||||
# add a Doxygen target to the "all" target
|
|
||||||
add_custom_target(LoggerCpp_doxygen
|
|
||||||
ALL
|
|
||||||
COMMAND doxygen Doxyfile > ${DEV_NULL}
|
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# but no Doxygen under Travis CI: too costly and no real benefit
|
|
||||||
message("no Doxygen target when TRAVIS is defined")
|
|
||||||
endif()
|
|
1874
LoggerCpp/Doxyfile
1874
LoggerCpp/Doxyfile
File diff suppressed because it is too large
Load diff
|
@ -1,21 +0,0 @@
|
||||||
Update shared_ptr to tag v1.0
|
|
||||||
|
|
||||||
test
|
|
||||||
|
|
||||||
Github Pages
|
|
||||||
|
|
||||||
Release
|
|
||||||
|
|
||||||
Manager: configure channels
|
|
||||||
|
|
||||||
Add a basic thread-safety security (throw if multiple threads create Loggers)
|
|
||||||
- Add a static Thread::getCurrentId()
|
|
||||||
|
|
||||||
Searching for a more compact or standard output format
|
|
||||||
- XML
|
|
||||||
- HTML
|
|
||||||
- json
|
|
||||||
- db3
|
|
||||||
- no SQL
|
|
||||||
- google protocol buffer
|
|
||||||
- message pack
|
|
|
@ -1,147 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Main.cpp
|
|
||||||
* @brief Example program for the simple LoggerC++ system
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LoggerCpp/LoggerCpp.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Simple test class
|
|
||||||
*/
|
|
||||||
class Tester {
|
|
||||||
public:
|
|
||||||
Tester() :
|
|
||||||
mLogger("main.Tester")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void constTest (void) const {
|
|
||||||
mLogger.debug() << "log within a const method";
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Log::Logger mLogger; ///< A named logger to produce log
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Simple example program
|
|
||||||
*/
|
|
||||||
int main ()
|
|
||||||
{
|
|
||||||
// Configure the default severity Level of new Channel objects
|
|
||||||
#ifndef NDEBUG
|
|
||||||
Log::Manager::setDefaultLevel(Log::Log::eDebug);
|
|
||||||
#else
|
|
||||||
Log::Manager::setDefaultLevel(Log::Log::eNotice);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int val;
|
|
||||||
if (false)
|
|
||||||
{
|
|
||||||
val = 2;
|
|
||||||
}
|
|
||||||
if (true)
|
|
||||||
{
|
|
||||||
// TODO SRombauts : testing
|
|
||||||
int* p = new int(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the Output objects
|
|
||||||
Log::Config::Vector configList;
|
|
||||||
Log::Config::addOutput(configList, "OutputConsole");
|
|
||||||
Log::Config::addOutput(configList, "OutputFile");
|
|
||||||
Log::Config::setOption(configList, "filename", "log.txt");
|
|
||||||
Log::Config::setOption(configList, "filename_old", "log.old.txt");
|
|
||||||
Log::Config::setOption(configList, "max_startup_size", "0");
|
|
||||||
Log::Config::setOption(configList, "max_size", "10000");
|
|
||||||
#ifdef WIN32
|
|
||||||
Log::Config::addOutput(configList, "OutputDebug");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create a Logger object, using a "Main.Example" Channel
|
|
||||||
Log::Logger logger("Main.Example");
|
|
||||||
logger.warning() << "NO logs before configure()";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Configure the Log Manager (create the Output objects)
|
|
||||||
//Log::Manager::configure(configList);
|
|
||||||
std::cout << "Configure" << std::endl;
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test outputs of various kind of variables, and some common stream manipulations.
|
|
||||||
std::string str("string");
|
|
||||||
unsigned int ui = 123;
|
|
||||||
double dbl = -0.023f;
|
|
||||||
logger.debug() << "Variables ; '" << str << "', '" << ui << "', '" << dbl << "'";
|
|
||||||
logger.debug() << "Hexa = " << std::hex << 0x75af0 << " test";
|
|
||||||
logger.debug() << "Deci = " << std::right << std::setfill('0') << std::setw(8) << 76035 << " test";
|
|
||||||
logger.debug() << "sizeof(logger)=" << sizeof(logger);
|
|
||||||
|
|
||||||
// Test outputs of various severity Level
|
|
||||||
logger.debug() << "Debug.";
|
|
||||||
logger.info() << "Info.";
|
|
||||||
logger.notice() << "Notice.";
|
|
||||||
logger.warning()<< "Warning.";
|
|
||||||
logger.error() << "Error.";
|
|
||||||
logger.critic() << "Critic.";
|
|
||||||
|
|
||||||
// Modify the output Level of the underlying Channel, and test various severity Level again
|
|
||||||
logger.setLevel(Log::Log::eWarning);
|
|
||||||
logger.debug() << "NO Debug."; // NO more debug logs
|
|
||||||
logger.info() << "NO Info."; // NO more info logs
|
|
||||||
logger.notice() << "NO Notice."; // NO more notice logs
|
|
||||||
logger.warning()<< "Warning.";
|
|
||||||
logger.error() << "Error.";
|
|
||||||
logger.critic() << "Critic.";
|
|
||||||
|
|
||||||
// Reset Level of the "Main.example" channel by its name
|
|
||||||
Log::Manager::get("Main.Example")->setLevel(Log::Log::eDebug);
|
|
||||||
|
|
||||||
// Create other loggers, sharing the "Main.Example" Channel, and creating a new one
|
|
||||||
Log::Logger logger2("Main.Example");
|
|
||||||
Log::Logger logger3("Main.Other");
|
|
||||||
logger.debug() << "First logger to the Channel";
|
|
||||||
logger2.debug() << "Second logger to the Channel";
|
|
||||||
logger3.debug() << "Third logger, other Channel";
|
|
||||||
// Modify the Level of the "Main.example" channel by its name
|
|
||||||
Log::Manager::get("Main.Example")->setLevel(Log::Log::eInfo);
|
|
||||||
logger.debug() << "first logger inhibited"; // NO more debug logs for this logger
|
|
||||||
logger2.debug() << "second logger also disabled"; // NO more debug logs (sharing the same underlying channel)
|
|
||||||
logger3.debug() << "third logger still active";
|
|
||||||
// Reset the Level of the "Main.example" channel by its name
|
|
||||||
Log::Manager::get("Main.Example")->setLevel(Log::Log::eDebug);
|
|
||||||
logger.debug() << "first logger re-activated";
|
|
||||||
logger2.debug() << "second logger also re-activated";
|
|
||||||
logger3.debug() << "third logger always active";
|
|
||||||
|
|
||||||
// Create an object using a Logger as member variable
|
|
||||||
Tester tester;
|
|
||||||
tester.constTest();
|
|
||||||
|
|
||||||
// Show how to get the current Channel configuration (to save it to a file, for instance)
|
|
||||||
Log::Manager::get("Main.OtherChannel")->setLevel(Log::Log::eNotice);
|
|
||||||
Log::Config::Ptr ChannelConfigPtr = Log::Manager::getChannelConfig();
|
|
||||||
// Show how to set the current Channel configuration (restored from a file, for instance)
|
|
||||||
Log::Manager::setChannelConfig(ChannelConfigPtr);
|
|
||||||
|
|
||||||
// Terminate the Log Manager (destroy the Output objects)
|
|
||||||
Log::Manager::terminate();
|
|
||||||
logger.warning() << "NO more logs after terminate()";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Channel.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief The named channel shared by Logger objects using the same name
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LoggerCpp/Log.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// The following includes "boost/shared_ptr.hpp" if LOGGER_USE_BOOST_SHARED_PTR is defined,
|
|
||||||
// or <memory> (or <tr1/memory>) when C++11 (or experimental C++0x) is available,
|
|
||||||
// or a custom minimal shared_ptr implementation,
|
|
||||||
// and imports the "shared_ptr" symbol inside the Log namespace (ie. Log::shared_ptr)
|
|
||||||
#include "LoggerCpp/shared_ptr.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The named channel shared by Logger objects using the same name
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*
|
|
||||||
* A Channel is the underlying object used by one or many Logger objects to
|
|
||||||
* associate a named prefix and an output Log::Level.
|
|
||||||
* Sharing a same Channel between multiple Logger enable changing the
|
|
||||||
* Level of many Logger objects at once.
|
|
||||||
*/
|
|
||||||
class Channel {
|
|
||||||
public:
|
|
||||||
/// @brief Shared Pointer to a Channel object
|
|
||||||
typedef shared_ptr<Channel> Ptr;
|
|
||||||
/// @brief Map of shared pointer of Channel objects
|
|
||||||
typedef std::map<std::string, Ptr> Map;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Initialize a named Channel
|
|
||||||
*
|
|
||||||
* @param[in] apChannelName String to identify origin of Log output by this Channel
|
|
||||||
* @param[in] aChannelLevel The default minimum Log::Level of severity from which to output Log
|
|
||||||
*/
|
|
||||||
Channel(const char* apChannelName, Log::Level aChannelLevel) :
|
|
||||||
mName(apChannelName),
|
|
||||||
mLevel(aChannelLevel)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/// @brief Non virtual destructor
|
|
||||||
~Channel(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Name of the Channel
|
|
||||||
inline const std::string& getName(void) const {
|
|
||||||
return mName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Set the current output Log::Level of the Channel
|
|
||||||
inline void setLevel(Log::Level aLevel) {
|
|
||||||
mLevel = aLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Current Log::Level of the Channel
|
|
||||||
inline Log::Level getLevel(void) const {
|
|
||||||
return mLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// @{ Non-copyable object
|
|
||||||
Channel(Channel&);
|
|
||||||
void operator=(Channel&);
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string mName; ///< Name of the Channel
|
|
||||||
Log::Level mLevel; ///< Current Log::Level of the Channel
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,123 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Config.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Configuration for an Output object
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
// The following includes "boost/shared_ptr.hpp" if LOGGER_USE_BOOST_SHARED_PTR is defined,
|
|
||||||
// or <memory> (or <tr1/memory>) when C++11 (or experimental C++0x) is available,
|
|
||||||
// or a custom minimal shared_ptr implementation,
|
|
||||||
// and imports the "shared_ptr" symbol inside the Log namespace (ie. Log::shared_ptr)
|
|
||||||
#include "LoggerCpp/shared_ptr.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
// forward declaration
|
|
||||||
class Logger;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configuration for an Output object
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*
|
|
||||||
* A Config object is an associative container of strings key and values,
|
|
||||||
* with easy to use helper manipulation functions.
|
|
||||||
*/
|
|
||||||
class Config {
|
|
||||||
public:
|
|
||||||
/// @brief Shared Pointer to a Config object
|
|
||||||
typedef shared_ptr<Config> Ptr;
|
|
||||||
/// @brief List of Config objects
|
|
||||||
typedef std::vector<Ptr> Vector;
|
|
||||||
/// @brief Map of string values
|
|
||||||
typedef std::map<std::string, std::string> Values;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
*
|
|
||||||
* @param[in] apName Name of the Config object
|
|
||||||
*/
|
|
||||||
explicit Config(const char* apName);
|
|
||||||
|
|
||||||
/// @brief Non virtual destructor
|
|
||||||
~Config(void);
|
|
||||||
|
|
||||||
/// @brief Get the name of this Config object
|
|
||||||
inline const std::string& getName(void) const {
|
|
||||||
return mName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Get the string values of this Config object
|
|
||||||
inline const Values& getValues(void) const {
|
|
||||||
return mValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set a string value
|
|
||||||
*
|
|
||||||
* @param[in] apKey String key identifying the string value
|
|
||||||
* @param[in] apValue String value associated to the given key
|
|
||||||
*/
|
|
||||||
inline void setValue(const char* apKey, const char* apValue) {
|
|
||||||
mValues[apKey] = apValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get a string value, or return the provided default one
|
|
||||||
*
|
|
||||||
* @param[in] apKey String key identifying the string value
|
|
||||||
* @param[in] apDefaultValue String default value
|
|
||||||
*
|
|
||||||
* @return String value associated to the given key
|
|
||||||
*/
|
|
||||||
const char* get(const char* apKey, const char* apDefaultValue) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get a long value, or return the provided default one
|
|
||||||
*
|
|
||||||
* @param[in] apKey String key identifying the string value
|
|
||||||
* @param[in] aDefaultValue Long default value
|
|
||||||
*
|
|
||||||
* @return Long value associated to the given key
|
|
||||||
*/
|
|
||||||
long get(const char* apKey, const long aDefaultValue) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Create the Config for a new Output
|
|
||||||
*
|
|
||||||
* @param[in,out] aConfigList Config list to complete with a new Output
|
|
||||||
* @param[in] apOutputName Name of the new Output
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void addOutput(Vector& aConfigList, const char* apOutputName);
|
|
||||||
/**
|
|
||||||
* @brief Set an option for the last added Output
|
|
||||||
*
|
|
||||||
* @param[in,out] aConfigList Config list to complete with a new option value
|
|
||||||
* @param[in] apKey String key identifying the string value
|
|
||||||
* @param[in] apValue String value associated to the given key
|
|
||||||
*/
|
|
||||||
static void setOption(Vector& aConfigList, const char* apKey, const char* apValue);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string mName; ///< Name of the Config
|
|
||||||
Values mValues; ///< Map of string values
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DateTime.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Current time precise to the millisecond.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Current time precise to the millisecond.
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*
|
|
||||||
* Using a struct to enable easy direct access to public members.
|
|
||||||
*
|
|
||||||
* Under Windows, the time is given to the millisecond.
|
|
||||||
* Under Linux, the time is given to the microsecond.
|
|
||||||
*/
|
|
||||||
struct DateTime {
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
*/
|
|
||||||
DateTime(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set to current time
|
|
||||||
*/
|
|
||||||
void make(void);
|
|
||||||
|
|
||||||
int year; ///< year [0,30827]
|
|
||||||
int month; ///< month [1,12]
|
|
||||||
int day; ///< day [1,31]
|
|
||||||
int hour; ///< hour [0,23]
|
|
||||||
int minute; ///< minute [0,59]
|
|
||||||
int second; ///< second [0,59]
|
|
||||||
int ms; ///< millisecond
|
|
||||||
int us; ///< microsecond (not under Windows)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,67 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Formatter.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief A standard string stream formatter with implicit string conversion
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A standard string stream formatter with implicit string conversion
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*
|
|
||||||
* It is constructed and initialized by a call to the Formatter() constructor.
|
|
||||||
* Is is then used by successive standard stream call "<<" to insert data into the stream.
|
|
||||||
* It is ultimately implicitly converted to std::string when required.
|
|
||||||
*
|
|
||||||
* A typical use case is to format a std::exception string message :
|
|
||||||
* - throw std::runtime_error(Formatter() << "no value for key '" << apKey << "'");
|
|
||||||
*/
|
|
||||||
class Formatter {
|
|
||||||
public:
|
|
||||||
/// @brief Constructor
|
|
||||||
Formatter(void) {}
|
|
||||||
/// @brief Non virtual destructor
|
|
||||||
~Formatter(void) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief stream inserter operator
|
|
||||||
*
|
|
||||||
* @param[in] aValue Value to be formatted and inserted into the string stream
|
|
||||||
*
|
|
||||||
* @return Current Formatter instance
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
Formatter& operator<< (const T& aValue) {
|
|
||||||
mStream << aValue;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief std::string cast operator for implicit conversion
|
|
||||||
inline operator std::string() const {
|
|
||||||
return mStream.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// @{ Non-copyable object
|
|
||||||
Formatter(const Formatter&);
|
|
||||||
void operator=(const Formatter&);
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::ostringstream mStream; ///< The underlying string stream
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Log.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief A RAII (private) log object constructed by the Logger class
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LoggerCpp/DateTime.h"
|
|
||||||
#include "LoggerCpp/Utils.h"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip> // For easy use of parametric manipulators (setfill, setprecision) by client code
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
// forward declaration
|
|
||||||
class Logger;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A RAII (private) log object constructed by the Logger class
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*
|
|
||||||
* a Log represents a full line of log, at a certain Log::Level of severity.
|
|
||||||
*
|
|
||||||
* It is constructed and initialized by a call to Logger::debug(),
|
|
||||||
* Logger::info(), ... or Logger::critic().
|
|
||||||
* Is is then used by successive stream call "<<", and is naturally terminated
|
|
||||||
* by it destructor at the end of the line, calling the Logger::output() method.
|
|
||||||
*
|
|
||||||
* It contains all required information for further formating, printing and transmitting
|
|
||||||
* by the Logger class.
|
|
||||||
*/
|
|
||||||
class Log {
|
|
||||||
friend class Logger;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Enumeration of the severity levels
|
|
||||||
*/
|
|
||||||
enum Level {
|
|
||||||
eDebug = 0,
|
|
||||||
eInfo,
|
|
||||||
eNotice,
|
|
||||||
eWarning,
|
|
||||||
eError,
|
|
||||||
eCritic
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief stream inserter operator
|
|
||||||
*
|
|
||||||
* @param[in] aValue Value to be formatted and inserted into the Log string stream
|
|
||||||
*
|
|
||||||
* @return Currents Log instance
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
Log& operator<< (const T& aValue) {
|
|
||||||
if (nullptr != mpStream) {
|
|
||||||
*mpStream << aValue;
|
|
||||||
}
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destructor : output the Log string stream
|
|
||||||
*/
|
|
||||||
~Log(void);
|
|
||||||
|
|
||||||
/// @brief Severity Level of this Log
|
|
||||||
inline Level getSeverity(void) const {
|
|
||||||
return mSeverity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Timestamp of this Log
|
|
||||||
inline const DateTime& getTime(void) const {
|
|
||||||
return mTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief The underlying string stream
|
|
||||||
inline const std::ostringstream& getStream(void) const {
|
|
||||||
return *mpStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert a Level to its string representation
|
|
||||||
*
|
|
||||||
* @param[in] aLevel Log severity Level to convert
|
|
||||||
*
|
|
||||||
* @return Severity Level description
|
|
||||||
*/
|
|
||||||
static const char* toString(Log::Level aLevel);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert a string representation of a Level to its corresponding value
|
|
||||||
*
|
|
||||||
* @param[in] apLevel Log severity string Level
|
|
||||||
*
|
|
||||||
* @return Severity Level value
|
|
||||||
*/
|
|
||||||
static Log::Level toLevel(const char* apLevel);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Construct a RAII (private) log object for the Logger class
|
|
||||||
*
|
|
||||||
* @param[in] aLogger Reference to the parent Logger
|
|
||||||
* @param[in] aSeverity Severity of this Log
|
|
||||||
*/
|
|
||||||
Log(const Logger& aLogger, Level aSeverity);
|
|
||||||
|
|
||||||
/// @{ Non-copyable object
|
|
||||||
Log(const Log&);
|
|
||||||
void operator=(const Log&);
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const Logger& mLogger; ///< Reference to the parent Logger
|
|
||||||
Level mSeverity; ///< Severity of this Log
|
|
||||||
DateTime mTime; ///< Timestamp of the output
|
|
||||||
std::ostringstream* mpStream; ///< The underlying string stream
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Logger.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief A simple thread-safe Logger class
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LoggerCpp/Log.h"
|
|
||||||
#include "LoggerCpp/Channel.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief LoggerC++ (LoggerCpp) is a simple, elegant and efficient C++ logger library.
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*/
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A simple thread-safe logger class
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*
|
|
||||||
* Logger is designed to be easy to use, light (size of a shared_ptr) and efficient.
|
|
||||||
* It can be used as a member variable, and will not consume much CPU
|
|
||||||
* if the log severity is below the Logger current Log::Level.
|
|
||||||
*
|
|
||||||
* @note A Logger object is copyable without any limitations
|
|
||||||
*/
|
|
||||||
class Logger {
|
|
||||||
friend class Log;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Initialize a Logger utility object
|
|
||||||
*
|
|
||||||
* @param[in] apChannelName String to identify origin of Log output by this Logger
|
|
||||||
*/
|
|
||||||
explicit Logger(const char* apChannelName);
|
|
||||||
/**
|
|
||||||
* @brief Non virtual destructor
|
|
||||||
*/
|
|
||||||
~Logger(void);
|
|
||||||
|
|
||||||
// A Logger is copyable with its a default copy constructor and copy operator without any problem
|
|
||||||
|
|
||||||
/// @{ Utility const method to produce Log objets, used to collect the stream to output
|
|
||||||
Log debug(void) const;
|
|
||||||
Log info(void) const;
|
|
||||||
Log notice(void) const;
|
|
||||||
Log warning(void) const;
|
|
||||||
Log error(void) const;
|
|
||||||
Log critic(void) const;
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
/// @brief Name of the underlying Channel
|
|
||||||
inline const std::string& getName(void) const {
|
|
||||||
return mChannelPtr->getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Set the current output Log::Level of the underlying Channel
|
|
||||||
inline void setLevel(Log::Level aLevel) {
|
|
||||||
mChannelPtr->setLevel(aLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Current Log::Level of the underlying Channel
|
|
||||||
inline Log::Level getLevel(void) const {
|
|
||||||
return mChannelPtr->getLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Output the Log. Used only by the Log class destructor.
|
|
||||||
*
|
|
||||||
* @param[in] aLog The Log to output
|
|
||||||
*/
|
|
||||||
void output(const Log& aLog) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Channel::Ptr mChannelPtr; ///< Shared pointer to the underlying Channel
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Manager.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief The static class that manage the registered Channel and Output objects
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LoggerCpp/Log.h"
|
|
||||||
#include "LoggerCpp/Channel.h"
|
|
||||||
#include "LoggerCpp/Output.h"
|
|
||||||
#include "LoggerCpp/Config.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The static class that manage the registered channels and outputs
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*
|
|
||||||
* The Manager keeps a map of all the named Channel objects
|
|
||||||
* and share them on demand by new Logger objects created with the same name.
|
|
||||||
*
|
|
||||||
* Thus the Manager is able to change the Log::Level of selected Channel object,
|
|
||||||
* impacting all the Logger objects using it.
|
|
||||||
*
|
|
||||||
* The Manager also keeps a list of all configured Output object to output the Log objects.
|
|
||||||
*/
|
|
||||||
struct Manager {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Create and configure the Output objects.
|
|
||||||
*
|
|
||||||
* @see setChannelConfig()
|
|
||||||
*
|
|
||||||
* @param[in] aConfigList List of Config for Output objects
|
|
||||||
*/
|
|
||||||
static void configure(const Config::Vector& aConfigList);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroy the Output objects.
|
|
||||||
*
|
|
||||||
* Clear the Output list to release the ownership.
|
|
||||||
*/
|
|
||||||
static void terminate(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Return the Channel corresponding to the provided name
|
|
||||||
*
|
|
||||||
* Create a new Channel or get the existing one.
|
|
||||||
*
|
|
||||||
* @param[in] apChannelName String to identify the underlying Channel of a Logger
|
|
||||||
*
|
|
||||||
* @return Pointer to the corresponding Channel (never nullptr)
|
|
||||||
*/
|
|
||||||
static Channel::Ptr get(const char* apChannelName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Output the Log to all the active Output objects.
|
|
||||||
*
|
|
||||||
* Dispatch the Log to OutputConsole/OutputFile/OutputVS/OutputMemory...
|
|
||||||
*
|
|
||||||
* @param[in] aChannelPtr The underlying Channel of the Log
|
|
||||||
* @param[in] aLog The Log to output
|
|
||||||
*/
|
|
||||||
static void output(const Channel::Ptr& aChannelPtr, const Log& aLog);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the default output Log::Level of any new Channel
|
|
||||||
*/
|
|
||||||
static inline void setDefaultLevel(Log::Level aLevel) {
|
|
||||||
mDefaultLevel = aLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Serialize the current Log::Level of Channel objects and return them as a Config instance
|
|
||||||
*/
|
|
||||||
static Config::Ptr getChannelConfig(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the Log::Level of Channel objects from the provided Config instance
|
|
||||||
*/
|
|
||||||
static void setChannelConfig(const Config::Ptr& aConfigPtr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set a Custom Logger
|
|
||||||
*/
|
|
||||||
static void setCustomLogger(Output *logger);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static Channel::Map mChannelMap; ///< Map of shared pointer of Channel objects
|
|
||||||
static Output::Vector mOutputList; ///< List of Output objects
|
|
||||||
static Log::Level mDefaultLevel; ///< Default Log::Level of any new Channel
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,62 +0,0 @@
|
||||||
/**
|
|
||||||
* @file OutputConsole.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Output to the standard console using fprintf() with stdout
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LoggerCpp/Output.h"
|
|
||||||
#include "LoggerCpp/Config.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Output to the standard console using fprintf() with stdout
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*/
|
|
||||||
class OutputConsole : public Output {
|
|
||||||
public:
|
|
||||||
/// @brief Constructor : no config
|
|
||||||
explicit OutputConsole(const Config::Ptr& aConfigPtr);
|
|
||||||
|
|
||||||
/// @brief Destructor
|
|
||||||
virtual ~OutputConsole();
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
/**
|
|
||||||
* @brief Convert a Level to a Win32 console color text attribute
|
|
||||||
*
|
|
||||||
* @param[in] aLevel Log severity Level to convert
|
|
||||||
*
|
|
||||||
* @return Win32 console color text attribute
|
|
||||||
*/
|
|
||||||
static unsigned short toWin32Attribute(Log::Level aLevel);
|
|
||||||
#else // _WIN32
|
|
||||||
/**
|
|
||||||
* @brief Convert a Level to an ANSI escape color code
|
|
||||||
*
|
|
||||||
* @param[in] aLevel Log severity Level to convert
|
|
||||||
*
|
|
||||||
* @return ANSI escape code for console color output
|
|
||||||
*/
|
|
||||||
static unsigned int toEscapeCode(Log::Level aLevel);
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Output the Log to the standard console using fprintf
|
|
||||||
*
|
|
||||||
* @param[in] aChannelPtr The underlying Channel of the Log
|
|
||||||
* @param[in] aLog The Log to output
|
|
||||||
*/
|
|
||||||
virtual void output(const Channel::Ptr& aChannelPtr, const Log& aLog) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,42 +0,0 @@
|
||||||
/**
|
|
||||||
* @file OutputDebug.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Output to the Visual Studio debugger using OutputDebugString()
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LoggerCpp/Output.h"
|
|
||||||
#include "LoggerCpp/Config.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Output to the Visual Studio debugger using OutputDebugString()
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*/
|
|
||||||
class OutputDebug : public Output {
|
|
||||||
public:
|
|
||||||
/// @brief Constructor : no config
|
|
||||||
explicit OutputDebug(const Config::Ptr& aConfigPtr);
|
|
||||||
|
|
||||||
/// @brief Destructor
|
|
||||||
virtual ~OutputDebug();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Output the Log to the Visual Studio debugger using OutputDebugString()
|
|
||||||
*
|
|
||||||
* @param[in] aChannelPtr The underlying Channel of the Log
|
|
||||||
* @param[in] aLog The Log to output
|
|
||||||
*/
|
|
||||||
virtual void output(const Channel::Ptr& aChannelPtr, const Log& aLog) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,84 +0,0 @@
|
||||||
/**
|
|
||||||
* @file OutputFile.h
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Output to the a file using fprintf
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LoggerCpp/Output.h"
|
|
||||||
#include "LoggerCpp/Config.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Output to the standard console using fprintf
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
*/
|
|
||||||
class OutputFile : public Output {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor : open the output file
|
|
||||||
*
|
|
||||||
* @param[in] aConfigPtr Config the output file with "filename"
|
|
||||||
*/
|
|
||||||
explicit OutputFile(const Config::Ptr& aConfigPtr);
|
|
||||||
|
|
||||||
/// @brief Destructor : close the file
|
|
||||||
virtual ~OutputFile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Output the Log to the standard console using fprintf
|
|
||||||
*
|
|
||||||
* @param[in] aChannelPtr The underlying Channel of the Log
|
|
||||||
* @param[in] aLog The Log to output
|
|
||||||
*/
|
|
||||||
virtual void output(const Channel::Ptr& aChannelPtr, const Log& aLog) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// @brief Open the log file
|
|
||||||
void open() const;
|
|
||||||
/// @brief Close the log file
|
|
||||||
void close() const;
|
|
||||||
/// @brief Rotate the log file : close, remove, rename, open
|
|
||||||
void rotate() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable FILE* mpFile; ///< @brief File pointer (mutable to be modified in the const output method)
|
|
||||||
mutable long mSize; ///< @brief Current size of the log file (mutable to be modified in the const output method)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief "max_startup_size" : Size of the file above which to create a new file instead of appending to it (at startup).
|
|
||||||
*
|
|
||||||
* Default (0) creates a new file at each startup (never append to an existing one).
|
|
||||||
*/
|
|
||||||
long mMaxStartupSize;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief "max_size" : Size of the file above which to create a new file instead of appending to it (at runtime).
|
|
||||||
*
|
|
||||||
* Default (1024*1024=1Mo) creates a new file each time the current one grow above 1Mo.
|
|
||||||
*/
|
|
||||||
long mMaxSize;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief "filename" : Name of the log file
|
|
||||||
*/
|
|
||||||
std::string mFilename;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief "filename_old" : Name of the log file renamed after max_size is reach
|
|
||||||
*/
|
|
||||||
std::string mFilenameOld;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,305 +0,0 @@
|
||||||
/**
|
|
||||||
* @file shared_ptr.hpp
|
|
||||||
* @brief shared_ptr is a minimal implementation of smart pointer, a subset of the C++11 std::shared_ptr or boost::shared_ptr.
|
|
||||||
*
|
|
||||||
* This file includes "boost/shared_ptr.hpp" if LOGGER_USE_BOOST_SHARED_PTR is defined,
|
|
||||||
* or <memory> (or <tr1/memory>) when C++11 (or experimental C++0x) is available,
|
|
||||||
* and imports the symbol "shared_ptr" inside the current namespace (ie. Log::shared_ptr).
|
|
||||||
* If no std::shared_ptr is available, it defines a minimal shared_ptr implementation.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
|
|
||||||
/// Compatibility with non-clang compilers.
|
|
||||||
#ifndef __has_feature
|
|
||||||
#define __has_feature(x) 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Try to detect the better shared_ptr to use, and then imports the symbol in the current namespace
|
|
||||||
// => if you include this "shared_ptr.hpp" file inside your own namespace you will
|
|
||||||
// get a kind of universal easy to use "shared_ptr" type
|
|
||||||
//
|
|
||||||
#ifdef LOGGER_USE_BOOST_SHARED_PTR
|
|
||||||
// Use Boost only if explicitly told
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
namespace Log {
|
|
||||||
using boost::shared_ptr;
|
|
||||||
} // namespace Log
|
|
||||||
// Detect whether the compiler supports C++11 shared_ptr or its TR1 pre-version.
|
|
||||||
#elif (defined(__GNUC__) && \
|
|
||||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
|
|
||||||
defined(__GXX_EXPERIMENTAL_CXX0X__))
|
|
||||||
// GCC 4.3 and following have std::shared_ptr support when called with -std=c++0x (or -std=c++11 starting with GCC 4.7)
|
|
||||||
#include <memory>
|
|
||||||
namespace Log {
|
|
||||||
using std::shared_ptr;
|
|
||||||
} // namespace Log
|
|
||||||
#elif (defined(__GNUC__) && (__GNUC__ == 4) && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
|
||||||
// GCC 4.0/4.1/4.2 have std::shared_ptr support when when called with -std=c++0x
|
|
||||||
#include <tr1/memory>
|
|
||||||
namespace Log {
|
|
||||||
using std::tr1::shared_ptr;
|
|
||||||
} // namespace Log
|
|
||||||
#elif defined(__clang__) && __has_feature(cxx_nullptr)
|
|
||||||
// Clang 2.9 and above ?
|
|
||||||
#include <memory>
|
|
||||||
namespace Log {
|
|
||||||
using std::shared_ptr;
|
|
||||||
} // namespace Log
|
|
||||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
|
|
||||||
// Visual Studio 2010 compile by default in C++11 mode
|
|
||||||
#include <memory>
|
|
||||||
namespace Log {
|
|
||||||
using std::shared_ptr;
|
|
||||||
} // namespace Log
|
|
||||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
|
|
||||||
// Visual Studio 2008 : beware, TR1 is provided with the Service Pack 1 only !
|
|
||||||
#include <memory>
|
|
||||||
namespace Log {
|
|
||||||
using std::tr1:shared_ptr;
|
|
||||||
} // namespace Log
|
|
||||||
#else
|
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef> // NULL
|
|
||||||
#include <algorithm> // std::swap
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
// can be replaced by other error mechanism
|
|
||||||
#define SHARED_ASSERT(x) assert(x)
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief minimal implementation of smart pointer, a subset of the C++11 std::shared_ptr or boost::shared_ptr.
|
|
||||||
*
|
|
||||||
* shared_ptr is a smart pointer retaining ownership of an object through a provided pointer,
|
|
||||||
* and sharing this ownership with a reference counter.
|
|
||||||
* It destroys the object when the last shared pointer pointing to it is destroyed or reset.
|
|
||||||
*/
|
|
||||||
template<class T>
|
|
||||||
class shared_ptr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/// The type of the managed object, aliased as member type
|
|
||||||
typedef T element_type;
|
|
||||||
|
|
||||||
/// @brief Default constructor
|
|
||||||
shared_ptr(void) throw() : // never throws
|
|
||||||
px(NULL),
|
|
||||||
pn(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
/// @brief Constructor with the provided pointer to manage
|
|
||||||
explicit shared_ptr(T* p) : // may throw std::bad_alloc
|
|
||||||
//px(p), would be unsafe as acquire() may throw, which would call release() in destructor
|
|
||||||
pn(NULL)
|
|
||||||
{
|
|
||||||
acquire(p); // may throw std::bad_alloc
|
|
||||||
}
|
|
||||||
/// @brief Constructor to share ownership. Warning : to be used for pointer_cast only ! (does not manage two separate <T> and <U> pointers)
|
|
||||||
template <class U>
|
|
||||||
shared_ptr(const shared_ptr<U>& ptr, T* p) :
|
|
||||||
//px(p), would be unsafe as acquire() may throw, which would call release() in destructor
|
|
||||||
pn(ptr.pn)
|
|
||||||
{
|
|
||||||
acquire(p); // may throw std::bad_alloc
|
|
||||||
}
|
|
||||||
/// @brief Copy constructor to convert from another pointer type
|
|
||||||
template <class U>
|
|
||||||
shared_ptr(const shared_ptr<U>& ptr) throw() : // never throws (see comment below)
|
|
||||||
//px(ptr.px),
|
|
||||||
pn(ptr.pn)
|
|
||||||
{
|
|
||||||
SHARED_ASSERT((NULL == ptr.px) || (NULL != ptr.pn)); // must be cohérent : no allocation allowed in this path
|
|
||||||
acquire(static_cast<typename shared_ptr<T>::element_type*>(ptr.px)); // will never throw std::bad_alloc
|
|
||||||
}
|
|
||||||
/// @brief Copy constructor (used by the copy-and-swap idiom)
|
|
||||||
shared_ptr(const shared_ptr& ptr) throw() : // never throws (see comment below)
|
|
||||||
//px(ptr.px),
|
|
||||||
pn(ptr.pn)
|
|
||||||
{
|
|
||||||
SHARED_ASSERT((NULL == ptr.px) || (NULL != ptr.pn)); // must be cohérent : no allocation allowed in this path
|
|
||||||
acquire(ptr.px); // will never throw std::bad_alloc
|
|
||||||
}
|
|
||||||
/// @brief Assignment operator using the copy-and-swap idiom (copy constructor and swap method)
|
|
||||||
shared_ptr& operator=(shared_ptr ptr) throw() // never throws
|
|
||||||
{
|
|
||||||
swap(ptr);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
/// @brief the destructor releases its ownership
|
|
||||||
inline ~shared_ptr(void) throw() // never throws
|
|
||||||
{
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
/// @brief this reset releases its ownership
|
|
||||||
inline void reset(void) throw() // never throws
|
|
||||||
{
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
/// @brief this reset release its ownership and re-acquire another one
|
|
||||||
void reset(T* p) throw() // may throw std::bad_alloc
|
|
||||||
{
|
|
||||||
SHARED_ASSERT((NULL == p) || (px != p)); // auto-reset not allowed
|
|
||||||
release();
|
|
||||||
acquire(p); // may throw std::bad_alloc
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Swap method for the copy-and-swap idiom (copy constructor and swap method)
|
|
||||||
void swap(shared_ptr& lhs) throw() // never throws
|
|
||||||
{
|
|
||||||
// Would be nice to enable use of ustl::swap by define
|
|
||||||
std::swap(px, lhs.px);
|
|
||||||
std::swap(pn, lhs.pn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reference counter operations :
|
|
||||||
inline operator bool() const throw() // never throws
|
|
||||||
{
|
|
||||||
return (0 < use_count());
|
|
||||||
}
|
|
||||||
inline bool unique(void) const throw() // never throws
|
|
||||||
{
|
|
||||||
return (1 == use_count());
|
|
||||||
}
|
|
||||||
long use_count(void) const throw() // never throws
|
|
||||||
{
|
|
||||||
long count = 0;
|
|
||||||
if (NULL != pn)
|
|
||||||
{
|
|
||||||
count = *pn;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// underlying pointer operations :
|
|
||||||
inline T& operator*() const throw() // never throws
|
|
||||||
{
|
|
||||||
SHARED_ASSERT(NULL != px);
|
|
||||||
return *px;
|
|
||||||
}
|
|
||||||
inline T* operator->() const throw() // never throws
|
|
||||||
{
|
|
||||||
SHARED_ASSERT(NULL != px);
|
|
||||||
return px;
|
|
||||||
}
|
|
||||||
inline T* get(void) const throw() // never throws
|
|
||||||
{
|
|
||||||
// no assert, car return NULL
|
|
||||||
return px;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// @brief acquire/share the ownership of the px pointer, initializing the reference counter
|
|
||||||
void acquire(T* p) // may throw std::bad_alloc
|
|
||||||
{
|
|
||||||
if (NULL != p)
|
|
||||||
{
|
|
||||||
if (NULL == pn)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pn = new long(1); // may throw std::bad_alloc
|
|
||||||
}
|
|
||||||
catch (std::bad_alloc&)
|
|
||||||
{
|
|
||||||
delete p;
|
|
||||||
throw; // rethrow the std::bad_alloc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++(*pn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// here it is safe to acquire the ownership of the provided raw pointer, where exception cannot be thrown any more
|
|
||||||
px = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief release the ownership of the px pointer, destroying the object when appropriate
|
|
||||||
void release(void) throw() // never throws
|
|
||||||
{
|
|
||||||
if (NULL != pn)
|
|
||||||
{
|
|
||||||
--(*pn);
|
|
||||||
if (0 == *pn)
|
|
||||||
{
|
|
||||||
delete px;
|
|
||||||
delete pn;
|
|
||||||
}
|
|
||||||
px = NULL;
|
|
||||||
pn = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// This allow pointer_cast functions to share the reference counter between different shared_ptr types
|
|
||||||
template<class U>
|
|
||||||
friend class shared_ptr;
|
|
||||||
|
|
||||||
private:
|
|
||||||
T* px; //!< Native pointer
|
|
||||||
long* pn; //!< Reference counter
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// comparaison operators
|
|
||||||
template<class T, class U> inline bool operator==(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
|
||||||
{
|
|
||||||
return (l.get() == r.get());
|
|
||||||
}
|
|
||||||
template<class T, class U> inline bool operator!=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
|
||||||
{
|
|
||||||
return (l.get() != r.get());
|
|
||||||
}
|
|
||||||
template<class T, class U> inline bool operator<=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
|
||||||
{
|
|
||||||
return (l.get() <= r.get());
|
|
||||||
}
|
|
||||||
template<class T, class U> inline bool operator<(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
|
||||||
{
|
|
||||||
return (l.get() < r.get());
|
|
||||||
}
|
|
||||||
template<class T, class U> inline bool operator>=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
|
||||||
{
|
|
||||||
return (l.get() >= r.get());
|
|
||||||
}
|
|
||||||
template<class T, class U> inline bool operator>(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
|
||||||
{
|
|
||||||
return (l.get() > r.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// static cast of shared_ptr
|
|
||||||
template<class T, class U>
|
|
||||||
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& ptr) // never throws
|
|
||||||
{
|
|
||||||
return shared_ptr<T>(ptr, static_cast<typename shared_ptr<T>::element_type*>(ptr.get()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// dynamic cast of shared_ptr
|
|
||||||
template<class T, class U>
|
|
||||||
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& ptr) // never throws
|
|
||||||
{
|
|
||||||
T* p = dynamic_cast<typename shared_ptr<T>::element_type*>(ptr.get());
|
|
||||||
if (NULL != p)
|
|
||||||
{
|
|
||||||
return shared_ptr<T>(ptr, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return shared_ptr<T>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Log
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,65 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Config.cpp
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Configuration for an Output object
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LoggerCpp/Config.h"
|
|
||||||
#include "LoggerCpp/Exception.h"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Config::Config(const char* apName) :
|
|
||||||
mName(apName) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
Config::~Config(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a string value
|
|
||||||
const char* Config::get(const char* apKey, const char* apDefaultValue) const {
|
|
||||||
const char* pValue;
|
|
||||||
Config::Values::const_iterator iValue = mValues.find(apKey);
|
|
||||||
if (mValues.end() != iValue) {
|
|
||||||
pValue = iValue->second.c_str();
|
|
||||||
} else {
|
|
||||||
pValue = apDefaultValue;
|
|
||||||
}
|
|
||||||
return pValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a string value
|
|
||||||
long Config::get(const char* apKey, long aDefaultValue) const {
|
|
||||||
long value;
|
|
||||||
Config::Values::const_iterator iValue = mValues.find(apKey);
|
|
||||||
if (mValues.end() != iValue) {
|
|
||||||
value = atol(iValue->second.c_str());
|
|
||||||
} else {
|
|
||||||
value = aDefaultValue;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the Config for a new Output
|
|
||||||
void Config::addOutput(Vector& aConfigList, const char* apOutputName) {
|
|
||||||
Log::Config::Ptr configPtr(new Log::Config(apOutputName));
|
|
||||||
aConfigList.push_back(configPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set an option for the last added Output
|
|
||||||
void Config::setOption(Vector& aConfigList, const char* apKey, const char* apValue) {
|
|
||||||
(*aConfigList.back()).setValue(apKey, apValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,69 +0,0 @@
|
||||||
/**
|
|
||||||
* @file DateTime.cpp
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Current time precise to the millisecond.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LoggerCpp/DateTime.h"
|
|
||||||
#include "LoggerCpp/Utils.h"
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
/// Constructor
|
|
||||||
DateTime::DateTime(void) :
|
|
||||||
year(0),
|
|
||||||
month(0),
|
|
||||||
day(0),
|
|
||||||
hour(0),
|
|
||||||
minute(0),
|
|
||||||
second(0),
|
|
||||||
ms(0),
|
|
||||||
us(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Set to current time
|
|
||||||
void DateTime::make(void) {
|
|
||||||
#ifdef WIN32
|
|
||||||
SYSTEMTIME now;
|
|
||||||
GetLocalTime(&now);
|
|
||||||
|
|
||||||
year = now.wYear;
|
|
||||||
month = now.wMonth;
|
|
||||||
day = now.wDay;
|
|
||||||
hour = now.wHour;
|
|
||||||
minute = now.wMinute;
|
|
||||||
second = now.wSecond;
|
|
||||||
ms = now.wMilliseconds;
|
|
||||||
us = 0;
|
|
||||||
#else
|
|
||||||
struct timeval now;
|
|
||||||
gettimeofday(&now, nullptr);
|
|
||||||
struct tm* timeinfo = localtime(&now.tv_sec);
|
|
||||||
|
|
||||||
year = timeinfo->tm_year + 1900;
|
|
||||||
month = timeinfo->tm_mon + 1;
|
|
||||||
day = timeinfo->tm_mday;
|
|
||||||
hour = timeinfo->tm_hour;
|
|
||||||
minute = timeinfo->tm_min;
|
|
||||||
second = timeinfo->tm_sec;
|
|
||||||
ms = now.tv_usec / 1000;
|
|
||||||
us = now.tv_usec % 1000;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,75 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Log.cpp
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief A RAII (private) log object constructed by the Logger class
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LoggerCpp/Log.h"
|
|
||||||
#include "LoggerCpp/Logger.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
// Construct a RAII (private) log object for the Logger class
|
|
||||||
Log::Log(const Logger& aLogger, Level aSeverity) :
|
|
||||||
mLogger(aLogger),
|
|
||||||
mSeverity(aSeverity),
|
|
||||||
mpStream(nullptr) {
|
|
||||||
// Construct a stream only if the severity of the Log is above its Logger Log::Level
|
|
||||||
if (aSeverity >= aLogger.getLevel()) {
|
|
||||||
mpStream = new(std::ostringstream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor : output the Log string stream
|
|
||||||
Log::~Log(void) {
|
|
||||||
if (nullptr != mpStream) {
|
|
||||||
mTime.make();
|
|
||||||
mLogger.output(*this);
|
|
||||||
|
|
||||||
delete mpStream;
|
|
||||||
mpStream = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a Level to its string representation
|
|
||||||
const char* Log::toString(Log::Level aLevel) {
|
|
||||||
const char* pString = nullptr;
|
|
||||||
|
|
||||||
switch (aLevel) {
|
|
||||||
case Log::eDebug: pString = "DBUG"; break;
|
|
||||||
case Log::eInfo: pString = "INFO"; break;
|
|
||||||
case Log::eNotice: pString = "NOTE"; break;
|
|
||||||
case Log::eWarning: pString = "WARN"; break;
|
|
||||||
case Log::eError: pString = "EROR"; break;
|
|
||||||
case Log::eCritic: pString = "CRIT"; break;
|
|
||||||
default: pString = "????"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a string representation of a Level to its corresponding value
|
|
||||||
Log::Level Log::toLevel(const char* apLevel) {
|
|
||||||
Log::Level level;
|
|
||||||
|
|
||||||
if (0 == strncmp(apLevel, "DBUG", 4)) level = Log::eDebug;
|
|
||||||
else if (0 == strncmp(apLevel, "INFO", 4)) level = Log::eInfo;
|
|
||||||
else if (0 == strncmp(apLevel, "NOTE", 4)) level = Log::eNotice;
|
|
||||||
else if (0 == strncmp(apLevel, "WARN", 4)) level = Log::eWarning;
|
|
||||||
else if (0 == strncmp(apLevel, "EROR", 4)) level = Log::eError;
|
|
||||||
else /* (0 == strncmp(apLevel, "CRIT", 4)*/ level = Log::eCritic; // NOLINT(whitespace/newline)
|
|
||||||
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,61 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Logger.cpp
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief A simple thread-safe Logger class
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LoggerCpp/Logger.h"
|
|
||||||
#include "LoggerCpp/Manager.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize a Logger utility object
|
|
||||||
Logger::Logger(const char* apChannelName) {
|
|
||||||
assert(nullptr != apChannelName);
|
|
||||||
|
|
||||||
mChannelPtr = Manager::get(apChannelName);
|
|
||||||
|
|
||||||
assert(mChannelPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non virtual destructor
|
|
||||||
Logger::~Logger(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utility const method to produce Log objets, used to collect the stream to output
|
|
||||||
Log Logger::debug(void) const {
|
|
||||||
return Log(*this, Log::eDebug);
|
|
||||||
}
|
|
||||||
Log Logger::info(void) const {
|
|
||||||
return Log(*this, Log::eInfo);
|
|
||||||
}
|
|
||||||
Log Logger::notice(void) const {
|
|
||||||
return Log(*this, Log::eNotice);
|
|
||||||
}
|
|
||||||
Log Logger::warning(void) const {
|
|
||||||
return Log(*this, Log::eWarning);
|
|
||||||
}
|
|
||||||
Log Logger::error(void) const {
|
|
||||||
return Log(*this, Log::eError);
|
|
||||||
}
|
|
||||||
Log Logger::critic(void) const {
|
|
||||||
return Log(*this, Log::eCritic);
|
|
||||||
}
|
|
||||||
|
|
||||||
// To be used only by the Log class
|
|
||||||
void Logger::output(const Log& aLog) const {
|
|
||||||
Manager::output(mChannelPtr, aLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
||||||
|
|
|
@ -1,140 +0,0 @@
|
||||||
/**
|
|
||||||
* @file Manager.cpp
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief The static class that manage the registered channels and outputs
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LoggerCpp/Manager.h"
|
|
||||||
#include "LoggerCpp/Exception.h"
|
|
||||||
|
|
||||||
#include "LoggerCpp/OutputConsole.h"
|
|
||||||
#include "LoggerCpp/OutputFile.h"
|
|
||||||
#ifdef WIN32
|
|
||||||
#include "LoggerCpp/OutputDebug.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
Channel::Map Manager::mChannelMap;
|
|
||||||
Output::Vector Manager::mOutputList;
|
|
||||||
Log::Level Manager::mDefaultLevel = Log::eDebug;
|
|
||||||
|
|
||||||
|
|
||||||
// Create and configure the Output objects.
|
|
||||||
void Manager::configure(const Config::Vector& aConfigList) {
|
|
||||||
// List of all Output class ; those names are in the form
|
|
||||||
// - "class Log::OutputConsole" under Visual Studio 2010
|
|
||||||
// - "N3Log13OutputConsoleE" under GCC
|
|
||||||
std::string outputConsole = typeid(OutputConsole).name();
|
|
||||||
std::string outputFile = typeid(OutputFile).name();
|
|
||||||
#ifdef WIN32
|
|
||||||
std::string outputDebug = typeid(OutputDebug).name();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Config::Vector::const_iterator iConfig;
|
|
||||||
for ( iConfig = aConfigList.begin();
|
|
||||||
iConfig != aConfigList.end();
|
|
||||||
++iConfig) {
|
|
||||||
Output::Ptr outputPtr;
|
|
||||||
const std::string& configName = (*iConfig)->getName();
|
|
||||||
|
|
||||||
// Compare the provided Output name with the known class name
|
|
||||||
if (std::string::npos != outputConsole.find(configName)) {
|
|
||||||
outputPtr.reset(new OutputConsole((*iConfig)));
|
|
||||||
} else if (std::string::npos != outputFile.find(configName)) {
|
|
||||||
outputPtr.reset(new OutputFile((*iConfig)));
|
|
||||||
#ifdef WIN32
|
|
||||||
} else if (std::string::npos != outputDebug.find(configName)) {
|
|
||||||
outputPtr.reset(new OutputDebug((*iConfig)));
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
LOGGER_THROW("Unknown Output name '" << configName << "'");
|
|
||||||
}
|
|
||||||
mOutputList.push_back(outputPtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the Output objects.
|
|
||||||
void Manager::terminate(void) {
|
|
||||||
// This effectively destroys the Output objects
|
|
||||||
mOutputList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the Channel corresponding to the provided name
|
|
||||||
Channel::Ptr Manager::get(const char* apChannelName) {
|
|
||||||
Channel::Ptr ChannelPtr;
|
|
||||||
Channel::Map::iterator iChannelPtr = mChannelMap.find(apChannelName);
|
|
||||||
|
|
||||||
if (mChannelMap.end() != iChannelPtr) {
|
|
||||||
ChannelPtr = iChannelPtr->second;
|
|
||||||
} else {
|
|
||||||
/// @todo Add a basic thread-safety security (throw if multiple threads create Loggers)
|
|
||||||
ChannelPtr.reset(new Channel(apChannelName, mDefaultLevel));
|
|
||||||
mChannelMap[apChannelName] = ChannelPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ChannelPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output the Log to all the active Output objects.
|
|
||||||
void Manager::output(const Channel::Ptr& aChannelPtr, const Log& aLog) {
|
|
||||||
Output::Vector::iterator iOutputPtr;
|
|
||||||
if (mOutputList.size() == 0) {
|
|
||||||
OutputConsole output(NULL);
|
|
||||||
output.output(aChannelPtr, aLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for ( iOutputPtr = mOutputList.begin();
|
|
||||||
iOutputPtr != mOutputList.end();
|
|
||||||
++iOutputPtr) {
|
|
||||||
(*iOutputPtr)->output(aChannelPtr, aLog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize the current Log::Level of Channel objects and return them as a Config instance
|
|
||||||
Config::Ptr Manager::getChannelConfig(void) {
|
|
||||||
Config::Ptr ConfigPtr(new Config("ChannelConfig"));
|
|
||||||
|
|
||||||
Channel::Map::const_iterator iChannel;
|
|
||||||
for (iChannel = mChannelMap.begin();
|
|
||||||
iChannel != mChannelMap.end();
|
|
||||||
++iChannel) {
|
|
||||||
ConfigPtr->setValue(iChannel->first.c_str(), Log::toString(iChannel->second->getLevel()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConfigPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the Log::Level of Channel objects from the provided Config instance
|
|
||||||
void Manager::setChannelConfig(const Config::Ptr& aConfigPtr) {
|
|
||||||
const Config::Values& ConfigValues = aConfigPtr->getValues();
|
|
||||||
|
|
||||||
Config::Values::const_iterator iValue;
|
|
||||||
for (iValue = ConfigValues.begin();
|
|
||||||
iValue != ConfigValues.end();
|
|
||||||
++iValue) {
|
|
||||||
Manager::get(iValue->first.c_str())->setLevel(Log::toLevel(iValue->second.c_str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Manager::setCustomLogger(Output *logger) {
|
|
||||||
mOutputList.clear();
|
|
||||||
Output::Ptr outputPtr;
|
|
||||||
outputPtr.reset(logger);
|
|
||||||
mOutputList.push_back(outputPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
/**
|
|
||||||
* @file OutputConsole.cpp
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Output to the standard console using fprintf() with stdout
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LoggerCpp/OutputConsole.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
OutputConsole::OutputConsole(const Config::Ptr& aConfigPtr) {
|
|
||||||
(void)aConfigPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
OutputConsole::~OutputConsole() {
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
// Convert a Level to a Win32 console color text attribute
|
|
||||||
unsigned short OutputConsole::toWin32Attribute(Log::Level aLevel) {
|
|
||||||
unsigned short code;
|
|
||||||
|
|
||||||
switch (aLevel) {
|
|
||||||
case Log::eDebug : code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; // white
|
|
||||||
case Log::eInfo : code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; break;
|
|
||||||
case Log::eNotice : code = FOREGROUND_GREEN; break; // green
|
|
||||||
case Log::eWarning : code = FOREGROUND_RED | FOREGROUND_GREEN; break; // orange
|
|
||||||
case Log::eError : code = FOREGROUND_RED; break; // red
|
|
||||||
case Log::eCritic : code = FOREGROUND_RED | FOREGROUND_INTENSITY; break; // light red
|
|
||||||
default : code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; // white
|
|
||||||
}
|
|
||||||
|
|
||||||
return (code);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // _WIN32
|
|
||||||
|
|
||||||
// Convert a Level to its ANSI escape color code
|
|
||||||
unsigned int OutputConsole::toEscapeCode(Log::Level aLevel) {
|
|
||||||
unsigned int code;
|
|
||||||
|
|
||||||
switch (aLevel) {
|
|
||||||
case Log::eDebug: code = 34; break; // 34=blue
|
|
||||||
case Log::eInfo: code = 39; break; // 39=white
|
|
||||||
case Log::eNotice: code = 32; break; // 32=green
|
|
||||||
case Log::eWarning: code = 33; break; // 33=orange
|
|
||||||
case Log::eError: code = 31; break; // 31=red
|
|
||||||
case Log::eCritic: code = 95; break; // 95=magenta
|
|
||||||
default: code = 39; break; // 39=white (reset to default)
|
|
||||||
}
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
// Output the Log to the standard console using fprintf
|
|
||||||
void OutputConsole::output(const Channel::Ptr& aChannelPtr, const Log& aLog) const {
|
|
||||||
const DateTime& time = aLog.getTime();
|
|
||||||
|
|
||||||
// uses fprintf for atomic thread-safe operation
|
|
||||||
#ifdef _WIN32
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), toWin32Attribute(aLog.getSeverity()));
|
|
||||||
fprintf(stdout, "%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u %-12s %s %s\n",
|
|
||||||
#else // _WIN32
|
|
||||||
fprintf(stdout, "\x1B[%02um%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u %-12s %s %s\x1b[39m\n",
|
|
||||||
toEscapeCode(aLog.getSeverity()),
|
|
||||||
#endif // _WIN32
|
|
||||||
time.year, time.month, time.day,
|
|
||||||
time.hour, time.minute, time.second, time.ms,
|
|
||||||
aChannelPtr->getName().c_str(), Log::toString(aLog.getSeverity()), (aLog.getStream()).str().c_str());
|
|
||||||
#ifdef _WIN32
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
|
||||||
#endif // _WIN32
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
|
@ -1,49 +0,0 @@
|
||||||
/**
|
|
||||||
* @file OutputDebug.cpp
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Output to the Visual Studio debugger using OutputDebugString()
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
|
|
||||||
#include "LoggerCpp/OutputDebug.h"
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
OutputDebug::OutputDebug(const Config::Ptr& aConfigPtr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
OutputDebug::~OutputDebug() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output the Log to the Visual Studio debugger using OutputDebugString()
|
|
||||||
void OutputDebug::output(const Channel::Ptr& aChannelPtr, const Log& aLog) const {
|
|
||||||
const DateTime& time = aLog.getTime();
|
|
||||||
char buffer[256];
|
|
||||||
|
|
||||||
// uses snprintf for atomic thread-safe operation
|
|
||||||
_snprintf(buffer, sizeof(buffer), "%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u %-12s %s %s\n",
|
|
||||||
time.year, time.month, time.day,
|
|
||||||
time.hour, time.minute, time.second, time.ms,
|
|
||||||
aChannelPtr->getName().c_str(), Log::toString(aLog.getSeverity()), (aLog.getStream()).str().c_str());
|
|
||||||
buffer[255] = '\0';
|
|
||||||
OutputDebugStringA(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
||||||
|
|
||||||
#endif // WIN32
|
|
|
@ -1,101 +0,0 @@
|
||||||
/**
|
|
||||||
* @file OutputFile.cpp
|
|
||||||
* @ingroup LoggerCpp
|
|
||||||
* @brief Output to the standard console using printf
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
|
||||||
*
|
|
||||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
|
||||||
* or copy at http://opensource.org/licenses/MIT)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LoggerCpp/OutputFile.h"
|
|
||||||
#include "LoggerCpp/Exception.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Log {
|
|
||||||
|
|
||||||
|
|
||||||
// Open the output file
|
|
||||||
OutputFile::OutputFile(const Config::Ptr& aConfigPtr) :
|
|
||||||
mpFile(nullptr) {
|
|
||||||
assert(aConfigPtr);
|
|
||||||
|
|
||||||
mMaxStartupSize = aConfigPtr->get("max_startup_size", (long)0);
|
|
||||||
mMaxSize = aConfigPtr->get("max_size", (long)1024*1024);
|
|
||||||
mFilename = aConfigPtr->get("filename", "log.txt");
|
|
||||||
mFilenameOld = aConfigPtr->get("filename_old", "log.old.txt");
|
|
||||||
|
|
||||||
// Test the size of the existing log file, rename it and open a new one if needed
|
|
||||||
struct stat statFile;
|
|
||||||
int ret = stat(mFilename.c_str(), &statFile);
|
|
||||||
if (0 == ret) {
|
|
||||||
mSize = statFile.st_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSize > mMaxStartupSize) {
|
|
||||||
rotate();
|
|
||||||
} else {
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the file
|
|
||||||
OutputFile::~OutputFile() {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the file
|
|
||||||
void OutputFile::open() const {
|
|
||||||
mpFile = fopen(mFilename.c_str(), "ab");
|
|
||||||
if (nullptr == mpFile) {
|
|
||||||
LOGGER_THROW("file \"" << mFilename << "\" not opened");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the file if it is opened
|
|
||||||
void OutputFile::close() const {
|
|
||||||
if (nullptr != mpFile) {
|
|
||||||
fclose(mpFile);
|
|
||||||
mpFile = nullptr;
|
|
||||||
mSize = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate a file : close, remove, rename, open
|
|
||||||
void OutputFile::rotate() const {
|
|
||||||
close();
|
|
||||||
|
|
||||||
remove(mFilenameOld.c_str());
|
|
||||||
rename(mFilename.c_str(), mFilenameOld.c_str());
|
|
||||||
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output the Log to the standard console using printf
|
|
||||||
void OutputFile::output(const Channel::Ptr& aChannelPtr, const Log& aLog) const {
|
|
||||||
const DateTime& time = aLog.getTime();
|
|
||||||
|
|
||||||
if (mSize > mMaxSize) {
|
|
||||||
rotate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nullptr != mpFile) {
|
|
||||||
// uses fprintf for atomic thread-safe operation
|
|
||||||
int nbWritten = fprintf(mpFile, "%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u %-12s %s %s\n",
|
|
||||||
time.year, time.month, time.day,
|
|
||||||
time.hour, time.minute, time.second, time.ms,
|
|
||||||
aChannelPtr->getName().c_str(), Log::toString(aLog.getSeverity()),
|
|
||||||
(aLog.getStream()).str().c_str());
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
mSize += nbWritten;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Log
|
|
89
fl/LoggerCpp/Channel.h
Normal file
89
fl/LoggerCpp/Channel.h
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/**
|
||||||
|
* @file Channel.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief The named channel shared by Logger objects using the same name
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LoggerCpp/Log.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// The following includes "boost/shared_ptr.hpp" if LOGGER_USE_BOOST_SHARED_PTR is defined,
|
||||||
|
// or <memory> (or <tr1/memory>) when C++11 (or experimental C++0x) is available,
|
||||||
|
// or a custom minimal shared_ptr implementation,
|
||||||
|
// and imports the "shared_ptr" symbol inside the Log namespace (ie. Log::shared_ptr)
|
||||||
|
#include "LoggerCpp/shared_ptr.hpp"
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The named channel shared by Logger objects using the same name
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*
|
||||||
|
* A Channel is the underlying object used by one or many Logger objects to
|
||||||
|
* associate a named prefix and an output Log::Level.
|
||||||
|
* Sharing a same Channel between multiple Logger enable changing the
|
||||||
|
* Level of many Logger objects at once.
|
||||||
|
*/
|
||||||
|
class Channel {
|
||||||
|
public:
|
||||||
|
/// @brief Shared Pointer to a Channel object
|
||||||
|
typedef shared_ptr<Channel> Ptr;
|
||||||
|
/// @brief Map of shared pointer of Channel objects
|
||||||
|
typedef std::map<std::string, Ptr> Map;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initialize a named Channel
|
||||||
|
*
|
||||||
|
* @param[in] apChannelName String to identify origin of Log output by this Channel
|
||||||
|
* @param[in] aChannelLevel The default minimum Log::Level of severity from which to output Log
|
||||||
|
*/
|
||||||
|
Channel(const char* apChannelName, Log::Level aChannelLevel) :
|
||||||
|
mName(apChannelName),
|
||||||
|
mLevel(aChannelLevel)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/// @brief Non virtual destructor
|
||||||
|
~Channel(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Name of the Channel
|
||||||
|
inline const std::string& getName(void) const {
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Set the current output Log::Level of the Channel
|
||||||
|
inline void setLevel(Log::Level aLevel) {
|
||||||
|
mLevel = aLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Current Log::Level of the Channel
|
||||||
|
inline Log::Level getLevel(void) const {
|
||||||
|
return mLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// @{ Non-copyable object
|
||||||
|
Channel(Channel&);
|
||||||
|
void operator=(Channel&);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string mName; ///< Name of the Channel
|
||||||
|
Log::Level mLevel; ///< Current Log::Level of the Channel
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Log
|
125
fl/LoggerCpp/Config.h
Normal file
125
fl/LoggerCpp/Config.h
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/**
|
||||||
|
* @file Config.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Configuration for an Output object
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// The following includes "boost/shared_ptr.hpp" if LOGGER_USE_BOOST_SHARED_PTR is defined,
|
||||||
|
// or <memory> (or <tr1/memory>) when C++11 (or experimental C++0x) is available,
|
||||||
|
// or a custom minimal shared_ptr implementation,
|
||||||
|
// and imports the "shared_ptr" symbol inside the Log namespace (ie. Log::shared_ptr)
|
||||||
|
#include "LoggerCpp/shared_ptr.hpp"
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
// forward declaration
|
||||||
|
class Logger;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configuration for an Output object
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*
|
||||||
|
* A Config object is an associative container of strings key and values,
|
||||||
|
* with easy to use helper manipulation functions.
|
||||||
|
*/
|
||||||
|
class Config {
|
||||||
|
public:
|
||||||
|
/// @brief Shared Pointer to a Config object
|
||||||
|
typedef shared_ptr<Config> Ptr;
|
||||||
|
/// @brief List of Config objects
|
||||||
|
typedef std::vector<Ptr> Vector;
|
||||||
|
/// @brief Map of string values
|
||||||
|
typedef std::map<std::string, std::string> Values;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*
|
||||||
|
* @param[in] apName Name of the Config object
|
||||||
|
*/
|
||||||
|
explicit Config(const char* apName);
|
||||||
|
|
||||||
|
/// @brief Non virtual destructor
|
||||||
|
~Config(void);
|
||||||
|
|
||||||
|
/// @brief Get the name of this Config object
|
||||||
|
inline const std::string& getName(void) const {
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Get the string values of this Config object
|
||||||
|
inline const Values& getValues(void) const {
|
||||||
|
return mValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set a string value
|
||||||
|
*
|
||||||
|
* @param[in] apKey String key identifying the string value
|
||||||
|
* @param[in] apValue String value associated to the given key
|
||||||
|
*/
|
||||||
|
inline void setValue(const char* apKey, const char* apValue) {
|
||||||
|
mValues[apKey] = apValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a string value, or return the provided default one
|
||||||
|
*
|
||||||
|
* @param[in] apKey String key identifying the string value
|
||||||
|
* @param[in] apDefaultValue String default value
|
||||||
|
*
|
||||||
|
* @return String value associated to the given key
|
||||||
|
*/
|
||||||
|
const char* get(const char* apKey, const char* apDefaultValue) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a long value, or return the provided default one
|
||||||
|
*
|
||||||
|
* @param[in] apKey String key identifying the string value
|
||||||
|
* @param[in] aDefaultValue Long default value
|
||||||
|
*
|
||||||
|
* @return Long value associated to the given key
|
||||||
|
*/
|
||||||
|
long get(const char* apKey, const long aDefaultValue) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Create the Config for a new Output
|
||||||
|
*
|
||||||
|
* @param[in,out] aConfigList Config list to complete with a new Output
|
||||||
|
* @param[in] apOutputName Name of the new Output
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void addOutput(Vector& aConfigList, const char* apOutputName);
|
||||||
|
/**
|
||||||
|
* @brief Set an option for the last added Output
|
||||||
|
*
|
||||||
|
* @param[in,out] aConfigList Config list to complete with a new option value
|
||||||
|
* @param[in] apKey String key identifying the string value
|
||||||
|
* @param[in] apValue String value associated to the given key
|
||||||
|
*/
|
||||||
|
static void setOption(Vector& aConfigList, const char* apKey, const char* apValue);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string mName; ///< Name of the Config
|
||||||
|
Values mValues; ///< Map of string values
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Log
|
||||||
|
|
50
fl/LoggerCpp/DateTime.h
Normal file
50
fl/LoggerCpp/DateTime.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
* @file DateTime.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Current time precise to the millisecond.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Current time precise to the millisecond.
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*
|
||||||
|
* Using a struct to enable easy direct access to public members.
|
||||||
|
*
|
||||||
|
* Under Windows, the time is given to the millisecond.
|
||||||
|
* Under Linux, the time is given to the microsecond.
|
||||||
|
*/
|
||||||
|
struct DateTime {
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*/
|
||||||
|
DateTime(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set to current time
|
||||||
|
*/
|
||||||
|
void make(void);
|
||||||
|
|
||||||
|
int year; ///< year [0,30827]
|
||||||
|
int month; ///< month [1,12]
|
||||||
|
int day; ///< day [1,31]
|
||||||
|
int hour; ///< hour [0,23]
|
||||||
|
int minute; ///< minute [0,59]
|
||||||
|
int second; ///< second [0,59]
|
||||||
|
int ms; ///< millisecond
|
||||||
|
int us; ///< microsecond (not under Windows)
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Log
|
|
@ -29,38 +29,40 @@
|
||||||
#pragma warning(disable:4290)
|
#pragma warning(disable:4290)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
|
||||||
namespace Log {
|
namespace Log {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Encapsulation of an error message based on std::runtime_error.
|
* @brief Encapsulation of an error message based on std::runtime_error.
|
||||||
* @ingroup LoggerCpp
|
* @ingroup LoggerCpp
|
||||||
*/
|
*/
|
||||||
class Exception : public std::runtime_error {
|
class Exception : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Encapsulation of an error message based on std::runtime_error.
|
* @brief Encapsulation of an error message based on std::runtime_error.
|
||||||
*
|
*
|
||||||
* @param[in] aErrorMessage The string message describing the error
|
* @param[in] aErrorMessage The string message describing the error
|
||||||
*/
|
*/
|
||||||
explicit Exception(const std::string& aErrorMessage) :
|
explicit Exception(const std::string& aErrorMessage) :
|
||||||
std::runtime_error(aErrorMessage)
|
std::runtime_error(aErrorMessage)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// @brief Stringify 1/2 : convert an integer to a string (using the following macro)
|
/// @brief Stringify 1/2 : convert an integer to a string (using the following macro)
|
||||||
#define TOSTRING(x) _XSTRING(x)
|
#define TOSTRING(x) _XSTRING(x)
|
||||||
/// @brief Stringify 2/2 : convert an integer to a string (inner macro)
|
/// @brief Stringify 2/2 : convert an integer to a string (inner macro)
|
||||||
#define _XSTRING(x) #x
|
#define _XSTRING(x) #x
|
||||||
|
|
||||||
#ifdef __FUNCTION__
|
#ifdef __FUNCTION__
|
||||||
/// @brief Define __func__ under Windows, to use the same name as with GCC
|
/// @brief Define __func__ under Windows, to use the same name as with GCC
|
||||||
#define __func__ __FUNCTION__
|
#define __func__ __FUNCTION__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief Helper macro to throw an Exception with file/line/function information, using the string stream Formatter
|
/// @brief Helper macro to throw an Exception with file/line/function information, using the string stream Formatter
|
||||||
#define LOGGER_THROW(x) throw Exception(Formatter() << __FILE__ << ":" << TOSTRING(__LINE__) << ": " << __func__ << "(): " << x)
|
#define LOGGER_THROW(x) throw Exception(Formatter() << __FILE__ << ":" << TOSTRING(__LINE__) << ": " << __func__ << "(): " << x)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Log
|
} // namespace Log
|
69
fl/LoggerCpp/Formatter.h
Normal file
69
fl/LoggerCpp/Formatter.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* @file Formatter.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief A standard string stream formatter with implicit string conversion
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A standard string stream formatter with implicit string conversion
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*
|
||||||
|
* It is constructed and initialized by a call to the Formatter() constructor.
|
||||||
|
* Is is then used by successive standard stream call "<<" to insert data into the stream.
|
||||||
|
* It is ultimately implicitly converted to std::string when required.
|
||||||
|
*
|
||||||
|
* A typical use case is to format a std::exception string message :
|
||||||
|
* - throw std::runtime_error(Formatter() << "no value for key '" << apKey << "'");
|
||||||
|
*/
|
||||||
|
class Formatter {
|
||||||
|
public:
|
||||||
|
/// @brief Constructor
|
||||||
|
Formatter(void) {}
|
||||||
|
/// @brief Non virtual destructor
|
||||||
|
~Formatter(void) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief stream inserter operator
|
||||||
|
*
|
||||||
|
* @param[in] aValue Value to be formatted and inserted into the string stream
|
||||||
|
*
|
||||||
|
* @return Current Formatter instance
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
Formatter& operator<< (const T& aValue) {
|
||||||
|
mStream << aValue;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief std::string cast operator for implicit conversion
|
||||||
|
inline operator std::string() const {
|
||||||
|
return mStream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// @{ Non-copyable object
|
||||||
|
Formatter(const Formatter&);
|
||||||
|
void operator=(const Formatter&);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ostringstream mStream; ///< The underlying string stream
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Log
|
||||||
|
|
135
fl/LoggerCpp/Log.h
Normal file
135
fl/LoggerCpp/Log.h
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/**
|
||||||
|
* @file Log.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief A RAII (private) log object constructed by the Logger class
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LoggerCpp/DateTime.h"
|
||||||
|
#include "LoggerCpp/Utils.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip> // For easy use of parametric manipulators (setfill, setprecision) by client code
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
// forward declaration
|
||||||
|
class Logger;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A RAII (private) log object constructed by the Logger class
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*
|
||||||
|
* a Log represents a full line of log, at a certain Log::Level of severity.
|
||||||
|
*
|
||||||
|
* It is constructed and initialized by a call to Logger::debug(),
|
||||||
|
* Logger::info(), ... or Logger::critic().
|
||||||
|
* Is is then used by successive stream call "<<", and is naturally terminated
|
||||||
|
* by it destructor at the end of the line, calling the Logger::output() method.
|
||||||
|
*
|
||||||
|
* It contains all required information for further formating, printing and transmitting
|
||||||
|
* by the Logger class.
|
||||||
|
*/
|
||||||
|
class Log {
|
||||||
|
friend class Logger;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Enumeration of the severity levels
|
||||||
|
*/
|
||||||
|
enum Level {
|
||||||
|
eDebug = 0,
|
||||||
|
eInfo,
|
||||||
|
eNotice,
|
||||||
|
eWarning,
|
||||||
|
eError,
|
||||||
|
eCritic
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief stream inserter operator
|
||||||
|
*
|
||||||
|
* @param[in] aValue Value to be formatted and inserted into the Log string stream
|
||||||
|
*
|
||||||
|
* @return Currents Log instance
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
Log& operator<< (const T& aValue) {
|
||||||
|
if (nullptr != mpStream) {
|
||||||
|
*mpStream << aValue;
|
||||||
|
}
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor : output the Log string stream
|
||||||
|
*/
|
||||||
|
~Log(void);
|
||||||
|
|
||||||
|
/// @brief Severity Level of this Log
|
||||||
|
inline Level getSeverity(void) const {
|
||||||
|
return mSeverity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Timestamp of this Log
|
||||||
|
inline const DateTime& getTime(void) const {
|
||||||
|
return mTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief The underlying string stream
|
||||||
|
inline const std::ostringstream& getStream(void) const {
|
||||||
|
return *mpStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert a Level to its string representation
|
||||||
|
*
|
||||||
|
* @param[in] aLevel Log severity Level to convert
|
||||||
|
*
|
||||||
|
* @return Severity Level description
|
||||||
|
*/
|
||||||
|
static const char* toString(Log::Level aLevel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert a string representation of a Level to its corresponding value
|
||||||
|
*
|
||||||
|
* @param[in] apLevel Log severity string Level
|
||||||
|
*
|
||||||
|
* @return Severity Level value
|
||||||
|
*/
|
||||||
|
static Log::Level toLevel(const char* apLevel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Construct a RAII (private) log object for the Logger class
|
||||||
|
*
|
||||||
|
* @param[in] aLogger Reference to the parent Logger
|
||||||
|
* @param[in] aSeverity Severity of this Log
|
||||||
|
*/
|
||||||
|
Log(const Logger& aLogger, Level aSeverity);
|
||||||
|
|
||||||
|
/// @{ Non-copyable object
|
||||||
|
Log(const Log&);
|
||||||
|
void operator=(const Log&);
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Logger& mLogger; ///< Reference to the parent Logger
|
||||||
|
Level mSeverity; ///< Severity of this Log
|
||||||
|
DateTime mTime; ///< Timestamp of the output
|
||||||
|
std::ostringstream* mpStream; ///< The underlying string stream
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Log
|
||||||
|
|
93
fl/LoggerCpp/Logger.h
Normal file
93
fl/LoggerCpp/Logger.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* @file Logger.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief A simple thread-safe Logger class
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LoggerCpp/Log.h"
|
||||||
|
#include "LoggerCpp/Channel.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief LoggerC++ (LoggerCpp) is a simple, elegant and efficient C++ logger library.
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*/
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A simple thread-safe logger class
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*
|
||||||
|
* Logger is designed to be easy to use, light (size of a shared_ptr) and efficient.
|
||||||
|
* It can be used as a member variable, and will not consume much CPU
|
||||||
|
* if the log severity is below the Logger current Log::Level.
|
||||||
|
*
|
||||||
|
* @note A Logger object is copyable without any limitations
|
||||||
|
*/
|
||||||
|
class Logger {
|
||||||
|
friend class Log;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initialize a Logger utility object
|
||||||
|
*
|
||||||
|
* @param[in] apChannelName String to identify origin of Log output by this Logger
|
||||||
|
*/
|
||||||
|
explicit Logger(const char* apChannelName);
|
||||||
|
/**
|
||||||
|
* @brief Non virtual destructor
|
||||||
|
*/
|
||||||
|
~Logger(void);
|
||||||
|
|
||||||
|
// A Logger is copyable with its a default copy constructor and copy operator without any problem
|
||||||
|
|
||||||
|
/// @{ Utility const method to produce Log objets, used to collect the stream to output
|
||||||
|
Log debug(void) const;
|
||||||
|
Log info(void) const;
|
||||||
|
Log notice(void) const;
|
||||||
|
Log warning(void) const;
|
||||||
|
Log error(void) const;
|
||||||
|
Log critic(void) const;
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// @brief Name of the underlying Channel
|
||||||
|
inline const std::string& getName(void) const {
|
||||||
|
return mChannelPtr->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Set the current output Log::Level of the underlying Channel
|
||||||
|
inline void setLevel(Log::Level aLevel) {
|
||||||
|
mChannelPtr->setLevel(aLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Current Log::Level of the underlying Channel
|
||||||
|
inline Log::Level getLevel(void) const {
|
||||||
|
return mChannelPtr->getLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Output the Log. Used only by the Log class destructor.
|
||||||
|
*
|
||||||
|
* @param[in] aLog The Log to output
|
||||||
|
*/
|
||||||
|
void output(const Log& aLog) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Channel::Ptr mChannelPtr; ///< Shared pointer to the underlying Channel
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Log
|
||||||
|
|
104
fl/LoggerCpp/Manager.h
Normal file
104
fl/LoggerCpp/Manager.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
* @file Manager.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief The static class that manage the registered Channel and Output objects
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LoggerCpp/Log.h"
|
||||||
|
#include "LoggerCpp/Channel.h"
|
||||||
|
#include "LoggerCpp/Output.h"
|
||||||
|
#include "LoggerCpp/Config.h"
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The static class that manage the registered channels and outputs
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*
|
||||||
|
* The Manager keeps a map of all the named Channel objects
|
||||||
|
* and share them on demand by new Logger objects created with the same name.
|
||||||
|
*
|
||||||
|
* Thus the Manager is able to change the Log::Level of selected Channel object,
|
||||||
|
* impacting all the Logger objects using it.
|
||||||
|
*
|
||||||
|
* The Manager also keeps a list of all configured Output object to output the Log objects.
|
||||||
|
*/
|
||||||
|
struct Manager {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Create and configure the Output objects.
|
||||||
|
*
|
||||||
|
* @see setChannelConfig()
|
||||||
|
*
|
||||||
|
* @param[in] aConfigList List of Config for Output objects
|
||||||
|
*/
|
||||||
|
static void configure(const Config::Vector& aConfigList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy the Output objects.
|
||||||
|
*
|
||||||
|
* Clear the Output list to release the ownership.
|
||||||
|
*/
|
||||||
|
static void terminate(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the Channel corresponding to the provided name
|
||||||
|
*
|
||||||
|
* Create a new Channel or get the existing one.
|
||||||
|
*
|
||||||
|
* @param[in] apChannelName String to identify the underlying Channel of a Logger
|
||||||
|
*
|
||||||
|
* @return Pointer to the corresponding Channel (never nullptr)
|
||||||
|
*/
|
||||||
|
static Channel::Ptr get(const char* apChannelName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output the Log to all the active Output objects.
|
||||||
|
*
|
||||||
|
* Dispatch the Log to OutputConsole/OutputFile/OutputVS/OutputMemory...
|
||||||
|
*
|
||||||
|
* @param[in] aChannelPtr The underlying Channel of the Log
|
||||||
|
* @param[in] aLog The Log to output
|
||||||
|
*/
|
||||||
|
static void output(const Channel::Ptr& aChannelPtr, const Log& aLog);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the default output Log::Level of any new Channel
|
||||||
|
*/
|
||||||
|
static inline void setDefaultLevel(Log::Level aLevel) {
|
||||||
|
mDefaultLevel = aLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Serialize the current Log::Level of Channel objects and return them as a Config instance
|
||||||
|
*/
|
||||||
|
static Config::Ptr getChannelConfig(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the Log::Level of Channel objects from the provided Config instance
|
||||||
|
*/
|
||||||
|
static void setChannelConfig(const Config::Ptr& aConfigPtr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set a Custom Logger
|
||||||
|
*/
|
||||||
|
static void setCustomLogger(Output *logger);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Channel::Map mChannelMap; ///< Map of shared pointer of Channel objects
|
||||||
|
static Output::Vector mOutputList; ///< List of Output objects
|
||||||
|
static Log::Level mDefaultLevel; ///< Default Log::Level of any new Channel
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Log
|
|
@ -21,41 +21,41 @@
|
||||||
// and imports the "shared_ptr" symbol inside the Log namespace (ie. Log::shared_ptr)
|
// and imports the "shared_ptr" symbol inside the Log namespace (ie. Log::shared_ptr)
|
||||||
#include "LoggerCpp/shared_ptr.hpp"
|
#include "LoggerCpp/shared_ptr.hpp"
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
namespace Log {
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
// Forward declaration
|
// Forward declaration
|
||||||
class Log;
|
class Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Interface of an Output
|
* @brief Interface of an Output
|
||||||
* @ingroup LoggerCpp
|
* @ingroup LoggerCpp
|
||||||
*/
|
*/
|
||||||
class Output {
|
class Output {
|
||||||
public:
|
public:
|
||||||
/// @brief Virtual destructor
|
/// @brief Virtual destructor
|
||||||
virtual ~Output() {}
|
virtual ~Output() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @brief Shared Pointer to an Output
|
/// @brief Shared Pointer to an Output
|
||||||
typedef shared_ptr<Output> Ptr;
|
typedef shared_ptr<Output> Ptr;
|
||||||
/// @brief List of Output objects
|
/// @brief List of Output objects
|
||||||
typedef std::vector<Ptr> Vector;
|
typedef std::vector<Ptr> Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Output the Log
|
* @brief Output the Log
|
||||||
*
|
*
|
||||||
* @param[in] aChannelPtr The underlying Channel of the Log
|
* @param[in] aChannelPtr The underlying Channel of the Log
|
||||||
* @param[in] aLog The Log to output
|
* @param[in] aLog The Log to output
|
||||||
*/
|
*/
|
||||||
virtual void output(const Channel::Ptr& aChannelPtr, const Log& aLog) const = 0;
|
virtual void output(const Channel::Ptr& aChannelPtr, const Log& aLog) const = 0;
|
||||||
|
|
||||||
/// @brief Return the type name of the Output object
|
|
||||||
inline const char* name() const {
|
|
||||||
return typeid(this).name();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/// @brief Return the type name of the Output object
|
||||||
|
inline const char* name() const {
|
||||||
|
return typeid(this).name();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
} // namespace Log
|
} // namespace Log
|
62
fl/LoggerCpp/OutputConsole.h
Normal file
62
fl/LoggerCpp/OutputConsole.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* @file OutputConsole.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Output to the standard console using fprintf() with stdout
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LoggerCpp/Output.h"
|
||||||
|
#include "LoggerCpp/Config.h"
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output to the standard console using fprintf() with stdout
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*/
|
||||||
|
class OutputConsole : public Output {
|
||||||
|
public:
|
||||||
|
/// @brief Constructor : no config
|
||||||
|
explicit OutputConsole(const Config::Ptr& aConfigPtr);
|
||||||
|
|
||||||
|
/// @brief Destructor
|
||||||
|
virtual ~OutputConsole();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/**
|
||||||
|
* @brief Convert a Level to a Win32 console color text attribute
|
||||||
|
*
|
||||||
|
* @param[in] aLevel Log severity Level to convert
|
||||||
|
*
|
||||||
|
* @return Win32 console color text attribute
|
||||||
|
*/
|
||||||
|
static unsigned short toWin32Attribute(Log::Level aLevel);
|
||||||
|
#else // _WIN32
|
||||||
|
/**
|
||||||
|
* @brief Convert a Level to an ANSI escape color code
|
||||||
|
*
|
||||||
|
* @param[in] aLevel Log severity Level to convert
|
||||||
|
*
|
||||||
|
* @return ANSI escape code for console color output
|
||||||
|
*/
|
||||||
|
static unsigned int toEscapeCode(Log::Level aLevel);
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output the Log to the standard console using fprintf
|
||||||
|
*
|
||||||
|
* @param[in] aChannelPtr The underlying Channel of the Log
|
||||||
|
* @param[in] aLog The Log to output
|
||||||
|
*/
|
||||||
|
virtual void output(const Channel::Ptr& aChannelPtr, const Log& aLog) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Log
|
43
fl/LoggerCpp/OutputDebug.h
Normal file
43
fl/LoggerCpp/OutputDebug.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @file OutputDebug.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Output to the Visual Studio debugger using OutputDebugString()
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LoggerCpp/Output.h"
|
||||||
|
#include "LoggerCpp/Config.h"
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output to the Visual Studio debugger using OutputDebugString()
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*/
|
||||||
|
class OutputDebug : public Output {
|
||||||
|
public:
|
||||||
|
/// @brief Constructor : no config
|
||||||
|
explicit OutputDebug(const Config::Ptr& aConfigPtr);
|
||||||
|
|
||||||
|
/// @brief Destructor
|
||||||
|
virtual ~OutputDebug();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output the Log to the Visual Studio debugger using OutputDebugString()
|
||||||
|
*
|
||||||
|
* @param[in] aChannelPtr The underlying Channel of the Log
|
||||||
|
* @param[in] aLog The Log to output
|
||||||
|
*/
|
||||||
|
virtual void output(const Channel::Ptr& aChannelPtr, const Log& aLog) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Log
|
84
fl/LoggerCpp/OutputFile.h
Normal file
84
fl/LoggerCpp/OutputFile.h
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/**
|
||||||
|
* @file OutputFile.h
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Output to the a file using fprintf
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LoggerCpp/Output.h"
|
||||||
|
#include "LoggerCpp/Config.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output to the standard console using fprintf
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
*/
|
||||||
|
class OutputFile : public Output {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor : open the output file
|
||||||
|
*
|
||||||
|
* @param[in] aConfigPtr Config the output file with "filename"
|
||||||
|
*/
|
||||||
|
explicit OutputFile(const Config::Ptr& aConfigPtr);
|
||||||
|
|
||||||
|
/// @brief Destructor : close the file
|
||||||
|
virtual ~OutputFile();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output the Log to the standard console using fprintf
|
||||||
|
*
|
||||||
|
* @param[in] aChannelPtr The underlying Channel of the Log
|
||||||
|
* @param[in] aLog The Log to output
|
||||||
|
*/
|
||||||
|
virtual void output(const Channel::Ptr& aChannelPtr, const Log& aLog) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// @brief Open the log file
|
||||||
|
void open() const;
|
||||||
|
/// @brief Close the log file
|
||||||
|
void close() const;
|
||||||
|
/// @brief Rotate the log file : close, remove, rename, open
|
||||||
|
void rotate() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable FILE* mpFile; ///< @brief File pointer (mutable to be modified in the const output method)
|
||||||
|
mutable long mSize; ///< @brief Current size of the log file (mutable to be modified in the const output method)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief "max_startup_size" : Size of the file above which to create a new file instead of appending to it (at startup).
|
||||||
|
*
|
||||||
|
* Default (0) creates a new file at each startup (never append to an existing one).
|
||||||
|
*/
|
||||||
|
long mMaxStartupSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief "max_size" : Size of the file above which to create a new file instead of appending to it (at runtime).
|
||||||
|
*
|
||||||
|
* Default (1024*1024=1Mo) creates a new file each time the current one grow above 1Mo.
|
||||||
|
*/
|
||||||
|
long mMaxSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief "filename" : Name of the log file
|
||||||
|
*/
|
||||||
|
std::string mFilename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief "filename_old" : Name of the log file renamed after max_size is reach
|
||||||
|
*/
|
||||||
|
std::string mFilenameOld;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Log
|
317
fl/LoggerCpp/shared_ptr.hpp
Normal file
317
fl/LoggerCpp/shared_ptr.hpp
Normal file
|
@ -0,0 +1,317 @@
|
||||||
|
/**
|
||||||
|
* @file shared_ptr.hpp
|
||||||
|
* @brief shared_ptr is a minimal implementation of smart pointer, a subset of the C++11 std::shared_ptr or boost::shared_ptr.
|
||||||
|
*
|
||||||
|
* This file includes "boost/shared_ptr.hpp" if LOGGER_USE_BOOST_SHARED_PTR is defined,
|
||||||
|
* or <memory> (or <tr1/memory>) when C++11 (or experimental C++0x) is available,
|
||||||
|
* and imports the symbol "shared_ptr" inside the current namespace (ie. Log::shared_ptr).
|
||||||
|
* If no std::shared_ptr is available, it defines a minimal shared_ptr implementation.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
/// Compatibility with non-clang compilers.
|
||||||
|
#ifndef __has_feature
|
||||||
|
#define __has_feature(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Try to detect the better shared_ptr to use, and then imports the symbol in the current namespace
|
||||||
|
// => if you include this "shared_ptr.hpp" file inside your own namespace you will
|
||||||
|
// get a kind of universal easy to use "shared_ptr" type
|
||||||
|
//
|
||||||
|
#ifdef LOGGER_USE_BOOST_SHARED_PTR
|
||||||
|
// Use Boost only if explicitly told
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
using boost::shared_ptr;
|
||||||
|
} // namespace Log
|
||||||
|
}
|
||||||
|
// Detect whether the compiler supports C++11 shared_ptr or its TR1 pre-version.
|
||||||
|
#elif (defined(__GNUC__) && \
|
||||||
|
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
|
||||||
|
defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||||
|
// GCC 4.3 and following have std::shared_ptr support when called with -std=c++0x (or -std=c++11 starting with GCC 4.7)
|
||||||
|
#include <memory>
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
using std::shared_ptr;
|
||||||
|
} // namespace Log
|
||||||
|
}
|
||||||
|
#elif (defined(__GNUC__) && (__GNUC__ == 4) && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||||
|
// GCC 4.0/4.1/4.2 have std::shared_ptr support when when called with -std=c++0x
|
||||||
|
#include <tr1/memory>
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
using std::tr1::shared_ptr;
|
||||||
|
} // namespace Log
|
||||||
|
}
|
||||||
|
#elif defined(__clang__) && __has_feature(cxx_nullptr)
|
||||||
|
// Clang 2.9 and above ?
|
||||||
|
#include <memory>
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
using std::shared_ptr;
|
||||||
|
} // namespace Log
|
||||||
|
}
|
||||||
|
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||||
|
// Visual Studio 2010 compile by default in C++11 mode
|
||||||
|
#include <memory>
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
using std::shared_ptr;
|
||||||
|
} // namespace Log
|
||||||
|
}
|
||||||
|
#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||||
|
// Visual Studio 2008 : beware, TR1 is provided with the Service Pack 1 only !
|
||||||
|
#include <memory>
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
using std::tr1:shared_ptr;
|
||||||
|
} // namespace Log
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstddef> // NULL
|
||||||
|
#include <algorithm> // std::swap
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// can be replaced by other error mechanism
|
||||||
|
#define SHARED_ASSERT(x) assert(x)
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief minimal implementation of smart pointer, a subset of the C++11 std::shared_ptr or boost::shared_ptr.
|
||||||
|
*
|
||||||
|
* shared_ptr is a smart pointer retaining ownership of an object through a provided pointer,
|
||||||
|
* and sharing this ownership with a reference counter.
|
||||||
|
* It destroys the object when the last shared pointer pointing to it is destroyed or reset.
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
class shared_ptr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the managed object, aliased as member type
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
/// @brief Default constructor
|
||||||
|
shared_ptr(void) throw() : // never throws
|
||||||
|
px(NULL),
|
||||||
|
pn(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/// @brief Constructor with the provided pointer to manage
|
||||||
|
explicit shared_ptr(T* p) : // may throw std::bad_alloc
|
||||||
|
//px(p), would be unsafe as acquire() may throw, which would call release() in destructor
|
||||||
|
pn(NULL)
|
||||||
|
{
|
||||||
|
acquire(p); // may throw std::bad_alloc
|
||||||
|
}
|
||||||
|
/// @brief Constructor to share ownership. Warning : to be used for pointer_cast only ! (does not manage two separate <T> and <U> pointers)
|
||||||
|
template <class U>
|
||||||
|
shared_ptr(const shared_ptr<U>& ptr, T* p) :
|
||||||
|
//px(p), would be unsafe as acquire() may throw, which would call release() in destructor
|
||||||
|
pn(ptr.pn)
|
||||||
|
{
|
||||||
|
acquire(p); // may throw std::bad_alloc
|
||||||
|
}
|
||||||
|
/// @brief Copy constructor to convert from another pointer type
|
||||||
|
template <class U>
|
||||||
|
shared_ptr(const shared_ptr<U>& ptr) throw() : // never throws (see comment below)
|
||||||
|
//px(ptr.px),
|
||||||
|
pn(ptr.pn)
|
||||||
|
{
|
||||||
|
SHARED_ASSERT((NULL == ptr.px) || (NULL != ptr.pn)); // must be cohérent : no allocation allowed in this path
|
||||||
|
acquire(static_cast<typename shared_ptr<T>::element_type*>(ptr.px)); // will never throw std::bad_alloc
|
||||||
|
}
|
||||||
|
/// @brief Copy constructor (used by the copy-and-swap idiom)
|
||||||
|
shared_ptr(const shared_ptr& ptr) throw() : // never throws (see comment below)
|
||||||
|
//px(ptr.px),
|
||||||
|
pn(ptr.pn)
|
||||||
|
{
|
||||||
|
SHARED_ASSERT((NULL == ptr.px) || (NULL != ptr.pn)); // must be cohérent : no allocation allowed in this path
|
||||||
|
acquire(ptr.px); // will never throw std::bad_alloc
|
||||||
|
}
|
||||||
|
/// @brief Assignment operator using the copy-and-swap idiom (copy constructor and swap method)
|
||||||
|
shared_ptr& operator=(shared_ptr ptr) throw() // never throws
|
||||||
|
{
|
||||||
|
swap(ptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/// @brief the destructor releases its ownership
|
||||||
|
inline ~shared_ptr(void) throw() // never throws
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
/// @brief this reset releases its ownership
|
||||||
|
inline void reset(void) throw() // never throws
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
/// @brief this reset release its ownership and re-acquire another one
|
||||||
|
void reset(T* p) throw() // may throw std::bad_alloc
|
||||||
|
{
|
||||||
|
SHARED_ASSERT((NULL == p) || (px != p)); // auto-reset not allowed
|
||||||
|
release();
|
||||||
|
acquire(p); // may throw std::bad_alloc
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Swap method for the copy-and-swap idiom (copy constructor and swap method)
|
||||||
|
void swap(shared_ptr& lhs) throw() // never throws
|
||||||
|
{
|
||||||
|
// Would be nice to enable use of ustl::swap by define
|
||||||
|
std::swap(px, lhs.px);
|
||||||
|
std::swap(pn, lhs.pn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reference counter operations :
|
||||||
|
inline operator bool() const throw() // never throws
|
||||||
|
{
|
||||||
|
return (0 < use_count());
|
||||||
|
}
|
||||||
|
inline bool unique(void) const throw() // never throws
|
||||||
|
{
|
||||||
|
return (1 == use_count());
|
||||||
|
}
|
||||||
|
long use_count(void) const throw() // never throws
|
||||||
|
{
|
||||||
|
long count = 0;
|
||||||
|
if (NULL != pn)
|
||||||
|
{
|
||||||
|
count = *pn;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// underlying pointer operations :
|
||||||
|
inline T& operator*() const throw() // never throws
|
||||||
|
{
|
||||||
|
SHARED_ASSERT(NULL != px);
|
||||||
|
return *px;
|
||||||
|
}
|
||||||
|
inline T* operator->() const throw() // never throws
|
||||||
|
{
|
||||||
|
SHARED_ASSERT(NULL != px);
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
inline T* get(void) const throw() // never throws
|
||||||
|
{
|
||||||
|
// no assert, car return NULL
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// @brief acquire/share the ownership of the px pointer, initializing the reference counter
|
||||||
|
void acquire(T* p) // may throw std::bad_alloc
|
||||||
|
{
|
||||||
|
if (NULL != p)
|
||||||
|
{
|
||||||
|
if (NULL == pn)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pn = new long(1); // may throw std::bad_alloc
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
delete p;
|
||||||
|
throw; // rethrow the std::bad_alloc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++(*pn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// here it is safe to acquire the ownership of the provided raw pointer, where exception cannot be thrown any more
|
||||||
|
px = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief release the ownership of the px pointer, destroying the object when appropriate
|
||||||
|
void release(void) throw() // never throws
|
||||||
|
{
|
||||||
|
if (NULL != pn)
|
||||||
|
{
|
||||||
|
--(*pn);
|
||||||
|
if (0 == *pn)
|
||||||
|
{
|
||||||
|
delete px;
|
||||||
|
delete pn;
|
||||||
|
}
|
||||||
|
px = NULL;
|
||||||
|
pn = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This allow pointer_cast functions to share the reference counter between different shared_ptr types
|
||||||
|
template<class U>
|
||||||
|
friend class shared_ptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* px; //!< Native pointer
|
||||||
|
long* pn; //!< Reference counter
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// comparaison operators
|
||||||
|
template<class T, class U> inline bool operator==(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
||||||
|
{
|
||||||
|
return (l.get() == r.get());
|
||||||
|
}
|
||||||
|
template<class T, class U> inline bool operator!=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
||||||
|
{
|
||||||
|
return (l.get() != r.get());
|
||||||
|
}
|
||||||
|
template<class T, class U> inline bool operator<=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
||||||
|
{
|
||||||
|
return (l.get() <= r.get());
|
||||||
|
}
|
||||||
|
template<class T, class U> inline bool operator<(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
||||||
|
{
|
||||||
|
return (l.get() < r.get());
|
||||||
|
}
|
||||||
|
template<class T, class U> inline bool operator>=(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
||||||
|
{
|
||||||
|
return (l.get() >= r.get());
|
||||||
|
}
|
||||||
|
template<class T, class U> inline bool operator>(const shared_ptr<T>& l, const shared_ptr<U>& r) throw() // never throws
|
||||||
|
{
|
||||||
|
return (l.get() > r.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// static cast of shared_ptr
|
||||||
|
template<class T, class U>
|
||||||
|
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& ptr) // never throws
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(ptr, static_cast<typename shared_ptr<T>::element_type*>(ptr.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// dynamic cast of shared_ptr
|
||||||
|
template<class T, class U>
|
||||||
|
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& ptr) // never throws
|
||||||
|
{
|
||||||
|
T* p = dynamic_cast<typename shared_ptr<T>::element_type*>(ptr.get());
|
||||||
|
if (NULL != p)
|
||||||
|
{
|
||||||
|
return shared_ptr<T>(ptr, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return shared_ptr<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Log
|
||||||
|
|
||||||
|
#endif
|
65
src/LoggerCpp/Config.cpp
Normal file
65
src/LoggerCpp/Config.cpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/**
|
||||||
|
* @file Config.cpp
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Configuration for an Output object
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LoggerCpp/Config.h"
|
||||||
|
#include "LoggerCpp/Exception.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Config::Config(const char* apName) :
|
||||||
|
mName(apName) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
Config::~Config(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a string value
|
||||||
|
const char* Config::get(const char* apKey, const char* apDefaultValue) const {
|
||||||
|
const char* pValue;
|
||||||
|
Config::Values::const_iterator iValue = mValues.find(apKey);
|
||||||
|
if (mValues.end() != iValue) {
|
||||||
|
pValue = iValue->second.c_str();
|
||||||
|
} else {
|
||||||
|
pValue = apDefaultValue;
|
||||||
|
}
|
||||||
|
return pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a string value
|
||||||
|
long Config::get(const char* apKey, long aDefaultValue) const {
|
||||||
|
long value;
|
||||||
|
Config::Values::const_iterator iValue = mValues.find(apKey);
|
||||||
|
if (mValues.end() != iValue) {
|
||||||
|
value = atol(iValue->second.c_str());
|
||||||
|
} else {
|
||||||
|
value = aDefaultValue;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the Config for a new Output
|
||||||
|
void Config::addOutput(Vector& aConfigList, const char* apOutputName) {
|
||||||
|
Log::Config::Ptr configPtr(new Log::Config(apOutputName));
|
||||||
|
aConfigList.push_back(configPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set an option for the last added Output
|
||||||
|
void Config::setOption(Vector& aConfigList, const char* apKey, const char* apValue) {
|
||||||
|
(*aConfigList.back()).setValue(apKey, apValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Log
|
70
src/LoggerCpp/DateTime.cpp
Normal file
70
src/LoggerCpp/DateTime.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* @file DateTime.cpp
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Current time precise to the millisecond.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LoggerCpp/DateTime.h"
|
||||||
|
#include "LoggerCpp/Utils.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
DateTime::DateTime(void) :
|
||||||
|
year(0),
|
||||||
|
month(0),
|
||||||
|
day(0),
|
||||||
|
hour(0),
|
||||||
|
minute(0),
|
||||||
|
second(0),
|
||||||
|
ms(0),
|
||||||
|
us(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Set to current time
|
||||||
|
void DateTime::make(void) {
|
||||||
|
#ifdef WIN32
|
||||||
|
SYSTEMTIME now;
|
||||||
|
GetLocalTime(&now);
|
||||||
|
|
||||||
|
year = now.wYear;
|
||||||
|
month = now.wMonth;
|
||||||
|
day = now.wDay;
|
||||||
|
hour = now.wHour;
|
||||||
|
minute = now.wMinute;
|
||||||
|
second = now.wSecond;
|
||||||
|
ms = now.wMilliseconds;
|
||||||
|
us = 0;
|
||||||
|
#else
|
||||||
|
struct timeval now;
|
||||||
|
gettimeofday(&now, nullptr);
|
||||||
|
struct tm* timeinfo = localtime(&now.tv_sec);
|
||||||
|
|
||||||
|
year = timeinfo->tm_year + 1900;
|
||||||
|
month = timeinfo->tm_mon + 1;
|
||||||
|
day = timeinfo->tm_mday;
|
||||||
|
hour = timeinfo->tm_hour;
|
||||||
|
minute = timeinfo->tm_min;
|
||||||
|
second = timeinfo->tm_sec;
|
||||||
|
ms = now.tv_usec / 1000;
|
||||||
|
us = now.tv_usec % 1000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Log
|
75
src/LoggerCpp/Log.cpp
Normal file
75
src/LoggerCpp/Log.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/**
|
||||||
|
* @file Log.cpp
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief A RAII (private) log object constructed by the Logger class
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LoggerCpp/Log.h"
|
||||||
|
#include "LoggerCpp/Logger.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
// Construct a RAII (private) log object for the Logger class
|
||||||
|
Log::Log(const Logger& aLogger, Level aSeverity) :
|
||||||
|
mLogger(aLogger),
|
||||||
|
mSeverity(aSeverity),
|
||||||
|
mpStream(nullptr) {
|
||||||
|
// Construct a stream only if the severity of the Log is above its Logger Log::Level
|
||||||
|
if (aSeverity >= aLogger.getLevel()) {
|
||||||
|
mpStream = new(std::ostringstream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor : output the Log string stream
|
||||||
|
Log::~Log(void) {
|
||||||
|
if (nullptr != mpStream) {
|
||||||
|
mTime.make();
|
||||||
|
mLogger.output(*this);
|
||||||
|
|
||||||
|
delete mpStream;
|
||||||
|
mpStream = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a Level to its string representation
|
||||||
|
const char* Log::toString(Log::Level aLevel) {
|
||||||
|
const char* pString = nullptr;
|
||||||
|
|
||||||
|
switch (aLevel) {
|
||||||
|
case Log::eDebug: pString = "DBUG"; break;
|
||||||
|
case Log::eInfo: pString = "INFO"; break;
|
||||||
|
case Log::eNotice: pString = "NOTE"; break;
|
||||||
|
case Log::eWarning: pString = "WARN"; break;
|
||||||
|
case Log::eError: pString = "EROR"; break;
|
||||||
|
case Log::eCritic: pString = "CRIT"; break;
|
||||||
|
default: pString = "????"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a string representation of a Level to its corresponding value
|
||||||
|
Log::Level Log::toLevel(const char* apLevel) {
|
||||||
|
Log::Level level;
|
||||||
|
|
||||||
|
if (0 == strncmp(apLevel, "DBUG", 4)) level = Log::eDebug;
|
||||||
|
else if (0 == strncmp(apLevel, "INFO", 4)) level = Log::eInfo;
|
||||||
|
else if (0 == strncmp(apLevel, "NOTE", 4)) level = Log::eNotice;
|
||||||
|
else if (0 == strncmp(apLevel, "WARN", 4)) level = Log::eWarning;
|
||||||
|
else if (0 == strncmp(apLevel, "EROR", 4)) level = Log::eError;
|
||||||
|
else /* (0 == strncmp(apLevel, "CRIT", 4)*/ level = Log::eCritic; // NOLINT(whitespace/newline)
|
||||||
|
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Log
|
61
src/LoggerCpp/Logger.cpp
Normal file
61
src/LoggerCpp/Logger.cpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* @file Logger.cpp
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief A simple thread-safe Logger class
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LoggerCpp/Logger.h"
|
||||||
|
#include "LoggerCpp/Manager.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize a Logger utility object
|
||||||
|
Logger::Logger(const char* apChannelName) {
|
||||||
|
assert(nullptr != apChannelName);
|
||||||
|
|
||||||
|
mChannelPtr = Manager::get(apChannelName);
|
||||||
|
|
||||||
|
assert(mChannelPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non virtual destructor
|
||||||
|
Logger::~Logger(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility const method to produce Log objets, used to collect the stream to output
|
||||||
|
Log Logger::debug(void) const {
|
||||||
|
return Log(*this, Log::eDebug);
|
||||||
|
}
|
||||||
|
Log Logger::info(void) const {
|
||||||
|
return Log(*this, Log::eInfo);
|
||||||
|
}
|
||||||
|
Log Logger::notice(void) const {
|
||||||
|
return Log(*this, Log::eNotice);
|
||||||
|
}
|
||||||
|
Log Logger::warning(void) const {
|
||||||
|
return Log(*this, Log::eWarning);
|
||||||
|
}
|
||||||
|
Log Logger::error(void) const {
|
||||||
|
return Log(*this, Log::eError);
|
||||||
|
}
|
||||||
|
Log Logger::critic(void) const {
|
||||||
|
return Log(*this, Log::eCritic);
|
||||||
|
}
|
||||||
|
|
||||||
|
// To be used only by the Log class
|
||||||
|
void Logger::output(const Log& aLog) const {
|
||||||
|
Manager::output(mChannelPtr, aLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Log
|
||||||
|
|
140
src/LoggerCpp/Manager.cpp
Normal file
140
src/LoggerCpp/Manager.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/**
|
||||||
|
* @file Manager.cpp
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief The static class that manage the registered channels and outputs
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LoggerCpp/Manager.h"
|
||||||
|
#include "LoggerCpp/Exception.h"
|
||||||
|
|
||||||
|
#include "LoggerCpp/OutputConsole.h"
|
||||||
|
#include "LoggerCpp/OutputFile.h"
|
||||||
|
#ifdef WIN32
|
||||||
|
#include "LoggerCpp/OutputDebug.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
Channel::Map Manager::mChannelMap;
|
||||||
|
Output::Vector Manager::mOutputList;
|
||||||
|
Log::Level Manager::mDefaultLevel = Log::eDebug;
|
||||||
|
|
||||||
|
|
||||||
|
// Create and configure the Output objects.
|
||||||
|
void Manager::configure(const Config::Vector& aConfigList) {
|
||||||
|
// List of all Output class ; those names are in the form
|
||||||
|
// - "class Log::OutputConsole" under Visual Studio 2010
|
||||||
|
// - "N3Log13OutputConsoleE" under GCC
|
||||||
|
std::string outputConsole = typeid(OutputConsole).name();
|
||||||
|
std::string outputFile = typeid(OutputFile).name();
|
||||||
|
#ifdef WIN32
|
||||||
|
std::string outputDebug = typeid(OutputDebug).name();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Config::Vector::const_iterator iConfig;
|
||||||
|
for ( iConfig = aConfigList.begin();
|
||||||
|
iConfig != aConfigList.end();
|
||||||
|
++iConfig) {
|
||||||
|
Output::Ptr outputPtr;
|
||||||
|
const std::string& configName = (*iConfig)->getName();
|
||||||
|
|
||||||
|
// Compare the provided Output name with the known class name
|
||||||
|
if (std::string::npos != outputConsole.find(configName)) {
|
||||||
|
outputPtr.reset(new OutputConsole((*iConfig)));
|
||||||
|
} else if (std::string::npos != outputFile.find(configName)) {
|
||||||
|
outputPtr.reset(new OutputFile((*iConfig)));
|
||||||
|
#ifdef WIN32
|
||||||
|
} else if (std::string::npos != outputDebug.find(configName)) {
|
||||||
|
outputPtr.reset(new OutputDebug((*iConfig)));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
LOGGER_THROW("Unknown Output name '" << configName << "'");
|
||||||
|
}
|
||||||
|
mOutputList.push_back(outputPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the Output objects.
|
||||||
|
void Manager::terminate(void) {
|
||||||
|
// This effectively destroys the Output objects
|
||||||
|
mOutputList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the Channel corresponding to the provided name
|
||||||
|
Channel::Ptr Manager::get(const char* apChannelName) {
|
||||||
|
Channel::Ptr ChannelPtr;
|
||||||
|
Channel::Map::iterator iChannelPtr = mChannelMap.find(apChannelName);
|
||||||
|
|
||||||
|
if (mChannelMap.end() != iChannelPtr) {
|
||||||
|
ChannelPtr = iChannelPtr->second;
|
||||||
|
} else {
|
||||||
|
/// @todo Add a basic thread-safety security (throw if multiple threads create Loggers)
|
||||||
|
ChannelPtr.reset(new Channel(apChannelName, mDefaultLevel));
|
||||||
|
mChannelMap[apChannelName] = ChannelPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChannelPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output the Log to all the active Output objects.
|
||||||
|
void Manager::output(const Channel::Ptr& aChannelPtr, const Log& aLog) {
|
||||||
|
Output::Vector::iterator iOutputPtr;
|
||||||
|
if (mOutputList.size() == 0) {
|
||||||
|
OutputConsole output(NULL);
|
||||||
|
output.output(aChannelPtr, aLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for ( iOutputPtr = mOutputList.begin();
|
||||||
|
iOutputPtr != mOutputList.end();
|
||||||
|
++iOutputPtr) {
|
||||||
|
(*iOutputPtr)->output(aChannelPtr, aLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize the current Log::Level of Channel objects and return them as a Config instance
|
||||||
|
Config::Ptr Manager::getChannelConfig(void) {
|
||||||
|
Config::Ptr ConfigPtr(new Config("ChannelConfig"));
|
||||||
|
|
||||||
|
Channel::Map::const_iterator iChannel;
|
||||||
|
for (iChannel = mChannelMap.begin();
|
||||||
|
iChannel != mChannelMap.end();
|
||||||
|
++iChannel) {
|
||||||
|
ConfigPtr->setValue(iChannel->first.c_str(), Log::toString(iChannel->second->getLevel()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConfigPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the Log::Level of Channel objects from the provided Config instance
|
||||||
|
void Manager::setChannelConfig(const Config::Ptr& aConfigPtr) {
|
||||||
|
const Config::Values& ConfigValues = aConfigPtr->getValues();
|
||||||
|
|
||||||
|
Config::Values::const_iterator iValue;
|
||||||
|
for (iValue = ConfigValues.begin();
|
||||||
|
iValue != ConfigValues.end();
|
||||||
|
++iValue) {
|
||||||
|
Manager::get(iValue->first.c_str())->setLevel(Log::toLevel(iValue->second.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::setCustomLogger(Output *logger) {
|
||||||
|
mOutputList.clear();
|
||||||
|
Output::Ptr outputPtr;
|
||||||
|
outputPtr.reset(logger);
|
||||||
|
mOutputList.push_back(outputPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Log
|
||||||
|
|
94
src/LoggerCpp/OutputConsole.cpp
Normal file
94
src/LoggerCpp/OutputConsole.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/**
|
||||||
|
* @file OutputConsole.cpp
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Output to the standard console using fprintf() with stdout
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LoggerCpp/OutputConsole.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
OutputConsole::OutputConsole(const Config::Ptr& aConfigPtr) {
|
||||||
|
(void)aConfigPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
OutputConsole::~OutputConsole() {
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
// Convert a Level to a Win32 console color text attribute
|
||||||
|
unsigned short OutputConsole::toWin32Attribute(Log::Level aLevel) {
|
||||||
|
unsigned short code;
|
||||||
|
|
||||||
|
switch (aLevel) {
|
||||||
|
case Log::eDebug : code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; // white
|
||||||
|
case Log::eInfo : code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; break;
|
||||||
|
case Log::eNotice : code = FOREGROUND_GREEN; break; // green
|
||||||
|
case Log::eWarning : code = FOREGROUND_RED | FOREGROUND_GREEN; break; // orange
|
||||||
|
case Log::eError : code = FOREGROUND_RED; break; // red
|
||||||
|
case Log::eCritic : code = FOREGROUND_RED | FOREGROUND_INTENSITY; break; // light red
|
||||||
|
default : code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; // white
|
||||||
|
}
|
||||||
|
|
||||||
|
return (code);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // _WIN32
|
||||||
|
|
||||||
|
// Convert a Level to its ANSI escape color code
|
||||||
|
unsigned int OutputConsole::toEscapeCode(Log::Level aLevel) {
|
||||||
|
unsigned int code;
|
||||||
|
|
||||||
|
switch (aLevel) {
|
||||||
|
case Log::eDebug: code = 34; break; // 34=blue
|
||||||
|
case Log::eInfo: code = 39; break; // 39=white
|
||||||
|
case Log::eNotice: code = 32; break; // 32=green
|
||||||
|
case Log::eWarning: code = 33; break; // 33=orange
|
||||||
|
case Log::eError: code = 31; break; // 31=red
|
||||||
|
case Log::eCritic: code = 95; break; // 95=magenta
|
||||||
|
default: code = 39; break; // 39=white (reset to default)
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
// Output the Log to the standard console using fprintf
|
||||||
|
void OutputConsole::output(const Channel::Ptr& aChannelPtr, const Log& aLog) const {
|
||||||
|
const DateTime& time = aLog.getTime();
|
||||||
|
|
||||||
|
// uses fprintf for atomic thread-safe operation
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), toWin32Attribute(aLog.getSeverity()));
|
||||||
|
fprintf(stdout, "%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u %-12s %s %s\n",
|
||||||
|
#else // _WIN32
|
||||||
|
fprintf(stdout, "\x1B[%02um%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u %-12s %s %s\x1b[39m\n",
|
||||||
|
toEscapeCode(aLog.getSeverity()),
|
||||||
|
#endif // _WIN32
|
||||||
|
time.year, time.month, time.day,
|
||||||
|
time.hour, time.minute, time.second, time.ms,
|
||||||
|
aChannelPtr->getName().c_str(), Log::toString(aLog.getSeverity()), (aLog.getStream()).str().c_str());
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||||
|
#endif // _WIN32
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Log
|
49
src/LoggerCpp/OutputDebug.cpp
Normal file
49
src/LoggerCpp/OutputDebug.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* @file OutputDebug.cpp
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Output to the Visual Studio debugger using OutputDebugString()
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#include "LoggerCpp/OutputDebug.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
OutputDebug::OutputDebug(const Config::Ptr& aConfigPtr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
OutputDebug::~OutputDebug() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output the Log to the Visual Studio debugger using OutputDebugString()
|
||||||
|
void OutputDebug::output(const Channel::Ptr& aChannelPtr, const Log& aLog) const {
|
||||||
|
const DateTime& time = aLog.getTime();
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
// uses snprintf for atomic thread-safe operation
|
||||||
|
_snprintf(buffer, sizeof(buffer), "%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u %-12s %s %s\n",
|
||||||
|
time.year, time.month, time.day,
|
||||||
|
time.hour, time.minute, time.second, time.ms,
|
||||||
|
aChannelPtr->getName().c_str(), Log::toString(aLog.getSeverity()), (aLog.getStream()).str().c_str());
|
||||||
|
buffer[255] = '\0';
|
||||||
|
OutputDebugStringA(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Log
|
||||||
|
}
|
||||||
|
#endif // WIN32
|
101
src/LoggerCpp/OutputFile.cpp
Normal file
101
src/LoggerCpp/OutputFile.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/**
|
||||||
|
* @file OutputFile.cpp
|
||||||
|
* @ingroup LoggerCpp
|
||||||
|
* @brief Output to the standard console using printf
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||||
|
* or copy at http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LoggerCpp/OutputFile.h"
|
||||||
|
#include "LoggerCpp/Exception.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
namespace fl {
|
||||||
|
namespace Log {
|
||||||
|
|
||||||
|
|
||||||
|
// Open the output file
|
||||||
|
OutputFile::OutputFile(const Config::Ptr& aConfigPtr) :
|
||||||
|
mpFile(nullptr) {
|
||||||
|
assert(aConfigPtr);
|
||||||
|
|
||||||
|
mMaxStartupSize = aConfigPtr->get("max_startup_size", (long)0);
|
||||||
|
mMaxSize = aConfigPtr->get("max_size", (long)1024*1024);
|
||||||
|
mFilename = aConfigPtr->get("filename", "log.txt");
|
||||||
|
mFilenameOld = aConfigPtr->get("filename_old", "log.old.txt");
|
||||||
|
|
||||||
|
// Test the size of the existing log file, rename it and open a new one if needed
|
||||||
|
struct stat statFile;
|
||||||
|
int ret = stat(mFilename.c_str(), &statFile);
|
||||||
|
if (0 == ret) {
|
||||||
|
mSize = statFile.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSize > mMaxStartupSize) {
|
||||||
|
rotate();
|
||||||
|
} else {
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the file
|
||||||
|
OutputFile::~OutputFile() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file
|
||||||
|
void OutputFile::open() const {
|
||||||
|
mpFile = fopen(mFilename.c_str(), "ab");
|
||||||
|
if (nullptr == mpFile) {
|
||||||
|
LOGGER_THROW("file \"" << mFilename << "\" not opened");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the file if it is opened
|
||||||
|
void OutputFile::close() const {
|
||||||
|
if (nullptr != mpFile) {
|
||||||
|
fclose(mpFile);
|
||||||
|
mpFile = nullptr;
|
||||||
|
mSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate a file : close, remove, rename, open
|
||||||
|
void OutputFile::rotate() const {
|
||||||
|
close();
|
||||||
|
|
||||||
|
remove(mFilenameOld.c_str());
|
||||||
|
rename(mFilename.c_str(), mFilenameOld.c_str());
|
||||||
|
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output the Log to the standard console using printf
|
||||||
|
void OutputFile::output(const Channel::Ptr& aChannelPtr, const Log& aLog) const {
|
||||||
|
const DateTime& time = aLog.getTime();
|
||||||
|
|
||||||
|
if (mSize > mMaxSize) {
|
||||||
|
rotate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != mpFile) {
|
||||||
|
// uses fprintf for atomic thread-safe operation
|
||||||
|
int nbWritten = fprintf(mpFile, "%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u %-12s %s %s\n",
|
||||||
|
time.year, time.month, time.day,
|
||||||
|
time.hour, time.minute, time.second, time.ms,
|
||||||
|
aChannelPtr->getName().c_str(), Log::toString(aLog.getSeverity()),
|
||||||
|
(aLog.getStream()).str().c_str());
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
mSize += nbWritten;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Log
|
Loading…
Add table
Reference in a new issue