mirror of
https://github.com/Fishwaldo/Fuzzylite.git
synced 2025-03-15 19:31:36 +00:00
add a Logging Library for FuzzyLite
This commit is contained in:
parent
b7e09d7ed9
commit
03d2d833d5
34 changed files with 4584 additions and 56 deletions
|
@ -54,7 +54,7 @@ add_definitions(-DFL_BUILD_PATH="${CMAKE_SOURCE_DIR}") #used to determine FL__FI
|
|||
set(FL_LIBS)
|
||||
|
||||
if(UNIX)
|
||||
set(CMAKE_CXX_FLAGS "-Werror -Wall -Wextra")
|
||||
set(CMAKE_CXX_FLAGS "-Werror -Wall -Wextra -fPIC")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
if(NOT APPLE)
|
||||
|
@ -77,6 +77,8 @@ if(NOT FL_BACKTRACE)
|
|||
endif()
|
||||
|
||||
include_directories(.)
|
||||
include_directories ("${PROJECT_SOURCE_DIR}/LoggerCpp/include/")
|
||||
add_definitions (-std=c++0x) # -std=c++11
|
||||
|
||||
file(STRINGS FL_HEADERS fl-headers)
|
||||
file(STRINGS FL_SOURCES fl-sources)
|
||||
|
@ -87,16 +89,45 @@ string(REGEX REPLACE "\n" " " ${fl-sources} ${fl-sources})
|
|||
message("${exepath}")
|
||||
|
||||
|
||||
# add sources of the logger library as a "LoggerCpp" library
|
||||
add_library (LoggerCpp STATIC
|
||||
LoggerCpp/include/LoggerCpp/Channel.h
|
||||
LoggerCpp/include/LoggerCpp/Config.h
|
||||
LoggerCpp/include/LoggerCpp/DateTime.h
|
||||
LoggerCpp/include/LoggerCpp/Exception.h
|
||||
LoggerCpp/include/LoggerCpp/Formatter.h
|
||||
LoggerCpp/include/LoggerCpp/Log.h
|
||||
LoggerCpp/include/LoggerCpp/Logger.h
|
||||
LoggerCpp/include/LoggerCpp/LoggerCpp.h
|
||||
LoggerCpp/include/LoggerCpp/Manager.h
|
||||
LoggerCpp/include/LoggerCpp/Output.h
|
||||
LoggerCpp/include/LoggerCpp/OutputConsole.h
|
||||
LoggerCpp/include/LoggerCpp/OutputDebug.h
|
||||
LoggerCpp/include/LoggerCpp/OutputFile.h
|
||||
LoggerCpp/include/LoggerCpp/shared_ptr.hpp
|
||||
LoggerCpp/include/LoggerCpp/Utils.h
|
||||
LoggerCpp/src/Config.cpp
|
||||
LoggerCpp/src/DateTime.cpp
|
||||
LoggerCpp/src/Log.cpp
|
||||
LoggerCpp/src/Logger.cpp
|
||||
LoggerCpp/src/Manager.cpp
|
||||
LoggerCpp/src/OutputConsole.cpp
|
||||
LoggerCpp/src/OutputDebug.cpp
|
||||
LoggerCpp/src/OutputFile.cpp
|
||||
)
|
||||
#set_target_properties(LoggerCpp PROPERTIES COMPILE_FLAGS -fvisibility=hidden)
|
||||
|
||||
|
||||
set(CMAKE_DEBUG_POSTFIX -dbg)
|
||||
|
||||
add_library(fl-shared SHARED ${fl-headers} ${fl-sources})
|
||||
set_target_properties(fl-shared PROPERTIES OUTPUT_NAME fuzzylite)
|
||||
set_target_properties(fl-shared PROPERTIES VERSION ${FL_VERSION} SOVERSION ${FL_VERSION})
|
||||
target_link_libraries(fl-shared ${FL_LIBS})
|
||||
target_link_libraries(fl-shared ${FL_LIBS} LoggerCpp)
|
||||
|
||||
add_library(fl-static STATIC ${fl-headers} ${fl-sources})
|
||||
set_target_properties(fl-static PROPERTIES OUTPUT_NAME fuzzylite-static)
|
||||
target_link_libraries(fl-static ${FL_LIBS})
|
||||
#add_library(fl-static STATIC ${fl-headers} ${fl-sources})
|
||||
#set_target_properties(fl-static PROPERTIES OUTPUT_NAME fuzzylite-static)
|
||||
#target_link_libraries(fl-static ${FL_LIBS} LoggerCpp)
|
||||
|
||||
add_executable(fl-bin fl/Console.h src/Console.cpp src/main.cpp)
|
||||
set_target_properties(fl-bin PROPERTIES OUTPUT_NAME fuzzylite)
|
||||
|
@ -106,7 +137,7 @@ target_link_libraries(fl-bin fl-shared ${FL_LIBS})
|
|||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS fl-bin fl-shared fl-static
|
||||
install(TARGETS fl-bin fl-shared
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
|
|
27
LoggerCpp/.gitignore
vendored
Normal file
27
LoggerCpp/.gitignore
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
Debug
|
||||
Release
|
||||
build
|
||||
lib
|
||||
doc
|
||||
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
*.cmake
|
||||
*.dir
|
||||
|
||||
*.sln
|
||||
*.vcproj*
|
||||
*.vcxproj*
|
||||
*.ncb
|
||||
*.suo
|
||||
*.user
|
||||
*sdf
|
||||
*ipch
|
||||
*.make
|
||||
Makefile
|
||||
.settings
|
||||
|
||||
*~
|
||||
|
||||
log*.txt
|
||||
core
|
106
LoggerCpp/CMakeLists.txt
Normal file
106
LoggerCpp/CMakeLists.txt
Normal file
|
@ -0,0 +1,106 @@
|
|||
# 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
Normal file
1874
LoggerCpp/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
20
LoggerCpp/LICENSE.txt
Normal file
20
LoggerCpp/LICENSE.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Sebastien Rombauts (sebastien.rombauts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
138
LoggerCpp/README.md
Normal file
138
LoggerCpp/README.md
Normal file
|
@ -0,0 +1,138 @@
|
|||
LoggerC++
|
||||
---------
|
||||
|
||||

|
||||
|
||||
LoggerC++ (LoggerCpp) is a simple, elegant and efficient C++ logger library.
|
||||
|
||||
### The goals of LoggerC++ are:
|
||||
|
||||
- to keep dependencies to a minimum (STL and shared_ptr)
|
||||
- to be portable
|
||||
- to minimize cpu utilisation when no log are outputed
|
||||
- to be thread-safe (output logs in same channel accross multiple threads)
|
||||
- to be well documented with Doxygen tags
|
||||
- to use a permissive MIT license, similar to BSD or Boost, for proprietary/commercial usage
|
||||
|
||||
### Limitations:
|
||||
|
||||
Thread-safety is only for Log outputs.
|
||||
You shall not dynamically create and destroy Logger objects in multiple threads.
|
||||
Instead, build them all at startup in you main thread, before other thread startup.
|
||||
Then you are allowed to use them all in parallel.
|
||||
|
||||
### Suported platforms:
|
||||
|
||||
Developements and tests are done under the following OSs :
|
||||
- Debian 7 (testing)
|
||||
- Ubuntu 12.10
|
||||
- Windows XP/7/8
|
||||
And following IDEs/Compilers
|
||||
- GCC 4.7.x with a provided Makefile
|
||||
- Eclipse CDT under Linux, using the provided Makefile
|
||||
- Visual Studio Express 2008/2010/2012 for testing compatibility purpose
|
||||
|
||||
### Dependencies:
|
||||
|
||||
- a STL implementation with RTTI (even an old one, like the one provided with VC6 should work).
|
||||
- optionnaly: the C++ 11 std::shared_ptr or boost::shared_ptr (a minimal shared_ptr implementation is provided).
|
||||
|
||||
### Installation
|
||||
|
||||
To use this C++ Logger, you need to include the sources files into your project codebase.
|
||||
|
||||
### License
|
||||
|
||||
Copyright (c) 2013 Sébastien Rombauts (sebastien.rombauts@gmail.com)
|
||||
|
||||
Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||
or copy at http://opensource.org/licenses/MIT)
|
||||
|
||||
## Getting started
|
||||
### Principles
|
||||
|
||||
- Add a small named Logger object to your code to output logs prefixed by the given name.
|
||||
A Logger is as small as a shared_ptr, typicaly 8 bytes.
|
||||
Use it as a member variable to your class, or as a free variable.
|
||||
- Build a Log with standard stream manipulations (like with std::cout)
|
||||
but in a thread-safe manner: the Log is outputed atomically at the end of the line.
|
||||
- Use one of the 6 Log Level, ranging from Debug to Critic in a standard fashion.
|
||||
- Set the Channel Level of the Logger to dynamicaly filter Log to be outputed
|
||||
- Multiple Logger objects with the same name will share the same underlying named Channel.
|
||||
Any of theses Logger can manipulate the Channel output Level.
|
||||
- Configure the availlable Output objects, for console, file or MSVC Debugger output.
|
||||
|
||||
### First sample demonstrates how to create a Logger and print some logs:
|
||||
|
||||
```C++
|
||||
int main ()
|
||||
{
|
||||
// Configure the default severity Level of new Channel objects
|
||||
Log::Manager::setDefaultLevel(Log::Log::eNotice);
|
||||
|
||||
// Setup the list of Config for 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, "max_size", "10000");
|
||||
// and configure the Log Manager (create the Output objects)
|
||||
Log::Manager::configure(configList);
|
||||
|
||||
// Create a Logger object, using a "Main.Example" Channel
|
||||
Log::Logger logger("Main.Example");
|
||||
|
||||
// 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";
|
||||
|
||||
// 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);
|
||||
```
|
||||
|
||||
## How to contribute
|
||||
### GitHub website
|
||||
The most efficient way to help and contribute to this wrapper project is to
|
||||
use the tools provided by GitHub:
|
||||
- please fill bug reports and feature requests here: https://github.com/SRombauts/LoggerCpp/issues
|
||||
- fork the repository, make some small changes and submit them with pull-request
|
||||
|
||||
### Contact
|
||||
You can also email me directly, I will answer any questions and requests.
|
||||
|
||||
### Coding Style Guidelines
|
||||
The source code use the CamelCase naming style variant where :
|
||||
- type names (class, struct, typedef, enums...) begins with a capital letter
|
||||
- files (.cpp/.h) are named like the class they contains
|
||||
- function and variable names begins with a lower case letter
|
||||
- member variables begins with a 'm', function arguments begins with a 'a', boolean with a 'b', pointers with a 'p'
|
||||
- each file, class, method and member variable is documented using Doxygen tags
|
||||
See also http://www.appinf.com/download/CppCodingStyleGuide.pdf for good guidelines
|
||||
|
||||
### Continuous Integration
|
||||
|
||||
This project is continuously tested under Ubuntu Linux with the gcc and clang compilers
|
||||
using the Travis CI community service with the above CMake building and testing procedure.
|
||||
|
||||
Detailed results can be seen online: https://travis-ci.org/SRombauts/LoggerCpp
|
21
LoggerCpp/TODO.txt
Normal file
21
LoggerCpp/TODO.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
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
|
147
LoggerCpp/examples/Main.cpp
Normal file
147
LoggerCpp/examples/Main.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
* @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;
|
||||
}
|
87
LoggerCpp/include/LoggerCpp/Channel.h
Normal file
87
LoggerCpp/include/LoggerCpp/Channel.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* @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
|
123
LoggerCpp/include/LoggerCpp/Config.h
Normal file
123
LoggerCpp/include/LoggerCpp/Config.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* @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
|
||||
|
48
LoggerCpp/include/LoggerCpp/DateTime.h
Normal file
48
LoggerCpp/include/LoggerCpp/DateTime.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* @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
|
66
LoggerCpp/include/LoggerCpp/Exception.h
Normal file
66
LoggerCpp/include/LoggerCpp/Exception.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file Exception.h
|
||||
* @ingroup LoggerCpp
|
||||
* @brief Encapsulation of an error message on a std::runtime_error.
|
||||
*
|
||||
* Copyright (c) 2012-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/Formatter.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
|
||||
/// assert() is used in destructors, where exceptions are not allowed
|
||||
/// (only asserting in debug mode)
|
||||
/// @todo Enable assertion callback like in SQLiteC++
|
||||
#define LOGGER_ASSERT(expression) assert(expression)
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// Disable warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
|
||||
#pragma warning(disable:4290)
|
||||
#endif
|
||||
|
||||
|
||||
namespace Log {
|
||||
|
||||
/**
|
||||
* @brief Encapsulation of an error message based on std::runtime_error.
|
||||
* @ingroup LoggerCpp
|
||||
*/
|
||||
class Exception : public std::runtime_error {
|
||||
public:
|
||||
/**
|
||||
* @brief Encapsulation of an error message based on std::runtime_error.
|
||||
*
|
||||
* @param[in] aErrorMessage The string message describing the error
|
||||
*/
|
||||
explicit Exception(const std::string& aErrorMessage) :
|
||||
std::runtime_error(aErrorMessage)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/// @brief Stringify 1/2 : convert an integer to a string (using the following macro)
|
||||
#define TOSTRING(x) _XSTRING(x)
|
||||
/// @brief Stringify 2/2 : convert an integer to a string (inner macro)
|
||||
#define _XSTRING(x) #x
|
||||
|
||||
#ifdef __FUNCTION__
|
||||
/// @brief Define __func__ under Windows, to use the same name as with GCC
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
/// @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)
|
||||
|
||||
|
||||
} // namespace Log
|
67
LoggerCpp/include/LoggerCpp/Formatter.h
Normal file
67
LoggerCpp/include/LoggerCpp/Formatter.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* @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
|
||||
|
134
LoggerCpp/include/LoggerCpp/Log.h
Normal file
134
LoggerCpp/include/LoggerCpp/Log.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
* @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
|
||||
|
91
LoggerCpp/include/LoggerCpp/Logger.h
Normal file
91
LoggerCpp/include/LoggerCpp/Logger.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* @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
|
||||
|
45
LoggerCpp/include/LoggerCpp/LoggerCpp.h
Normal file
45
LoggerCpp/include/LoggerCpp/LoggerCpp.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file LoggerCpp.h
|
||||
* @ingroup LoggerCpp
|
||||
* @brief LoggerC++ (LoggerCpp) is a simple, elegant and efficient C++ logger library.
|
||||
*
|
||||
* Include this main header file in your project to gain access to all functionality provided by the logger.
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
/**
|
||||
* @defgroup LoggerCpp LoggerC++
|
||||
* @brief LoggerC++ (LoggerCpp) is a simple, elegant and efficient C++ logger library.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
// Include useful headers of LoggerC++
|
||||
#include "LoggerCpp/Logger.h"
|
||||
#include "LoggerCpp/Manager.h"
|
||||
|
||||
|
||||
/**
|
||||
* @def LOGGERCPP_VERSION
|
||||
* @brief Srting version numbers for LoggerC++
|
||||
* @ingroup LoggerCpp
|
||||
*
|
||||
* The LOGGERCPP_VERSION C preprocessor macro in the LoggerCpp.h header
|
||||
* evaluates to a string literal that is the LoggerC++ version in the
|
||||
* format "X.Y.Z" where X is the major version number
|
||||
* and Y is the minor version number and Z is the release number.
|
||||
*/
|
||||
#define LOGGERCPP_VERSION "0.2.0"
|
||||
/**
|
||||
* @def LOGGERCPP_VERSION_NUMBER
|
||||
* @brief Numeric version numbers for LoggerC++
|
||||
* @ingroup LoggerCpp
|
||||
*
|
||||
* The LOGGERCPP_VERSION_NUMBER C preprocessor macro resolves to an integer
|
||||
* with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
|
||||
* numbers used in [LOGGERCPP_VERSION].
|
||||
*/
|
||||
#define LOGGERCPP_VERSION_NUMBER 0002000
|
102
LoggerCpp/include/LoggerCpp/Manager.h
Normal file
102
LoggerCpp/include/LoggerCpp/Manager.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* @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
|
61
LoggerCpp/include/LoggerCpp/Output.h
Normal file
61
LoggerCpp/include/LoggerCpp/Output.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @file Output.h
|
||||
* @ingroup LoggerCpp
|
||||
* @brief Interface of an Output
|
||||
*
|
||||
* 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/Channel.h"
|
||||
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
|
||||
// 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 Log;
|
||||
|
||||
/**
|
||||
* @brief Interface of an Output
|
||||
* @ingroup LoggerCpp
|
||||
*/
|
||||
class Output {
|
||||
public:
|
||||
/// @brief Virtual destructor
|
||||
virtual ~Output() {}
|
||||
|
||||
public:
|
||||
/// @brief Shared Pointer to an Output
|
||||
typedef shared_ptr<Output> Ptr;
|
||||
/// @brief List of Output objects
|
||||
typedef std::vector<Ptr> Vector;
|
||||
|
||||
/**
|
||||
* @brief Output the Log
|
||||
*
|
||||
* @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 = 0;
|
||||
|
||||
/// @brief Return the type name of the Output object
|
||||
inline const char* name() const {
|
||||
return typeid(this).name();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace Log
|
62
LoggerCpp/include/LoggerCpp/OutputConsole.h
Normal file
62
LoggerCpp/include/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 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
|
42
LoggerCpp/include/LoggerCpp/OutputDebug.h
Normal file
42
LoggerCpp/include/LoggerCpp/OutputDebug.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @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
|
84
LoggerCpp/include/LoggerCpp/OutputFile.h
Normal file
84
LoggerCpp/include/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 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
|
78
LoggerCpp/include/LoggerCpp/Utils.h
Normal file
78
LoggerCpp/include/LoggerCpp/Utils.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* @file Utils.h
|
||||
* @ingroup Utils
|
||||
* @brief Shared utility macros and functions.
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
/**
|
||||
* @defgroup Utils Utils
|
||||
* @brief Shared utilities.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Shared utilities.
|
||||
* @ingroup Utils Utils
|
||||
*/
|
||||
namespace Utils {
|
||||
} // namespace Utils
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @brief A macro to disallow the copy constructor and operator= functions.
|
||||
*
|
||||
* This should be used in the private: declarations for a class
|
||||
*
|
||||
* @param[in] TypeName Class name to protect
|
||||
*/
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER < 1600
|
||||
/// A macro to enable the use of the nullptr keyword (NULL on older MSVC compilers, as they does not accept "nullptr_t")
|
||||
#ifndef nullptr
|
||||
#define nullptr NULL
|
||||
#endif // nullptr
|
||||
#endif // _MSC_VER < 1600
|
||||
#else // _MSC_VER
|
||||
#if (__cplusplus < 201103L) && !defined(__GXX_EXPERIMENTAL_CXX0X__) // before C++11 on GCC4.7 and Visual Studio 2010
|
||||
#ifndef HAVE_NULLPTR
|
||||
#define HAVE_NULLPTR ///< A macro to avoid double definition of nullptr
|
||||
/**
|
||||
* @brief nullptr_t is the type of the null pointer literal, nullptr.
|
||||
*/
|
||||
class nullptr_t {
|
||||
public:
|
||||
template<typename T>
|
||||
inline operator T* () const { ///< convertible to any type of null non-member pointer...
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename C, typename T>
|
||||
inline operator T C::* () const { ///< convertible to any type of null member pointer...
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void operator&() const; ///< Can't take address of nullptr NOLINT
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Better way to enable nullptr on older GCC/Clang compilers
|
||||
*/
|
||||
const nullptr_t nullptr = {};
|
||||
#endif // HAVE_NULLPTR
|
||||
#endif // (__cplusplus < 201103L) && !defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
#endif // _MSC_VER
|
||||
|
||||
// A macro for snprintf support in Visual Studio
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
305
LoggerCpp/include/LoggerCpp/shared_ptr.hpp
Normal file
305
LoggerCpp/include/LoggerCpp/shared_ptr.hpp
Normal file
|
@ -0,0 +1,305 @@
|
|||
/**
|
||||
* @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
|
65
LoggerCpp/src/Config.cpp
Normal file
65
LoggerCpp/src/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 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
|
69
LoggerCpp/src/DateTime.cpp
Normal file
69
LoggerCpp/src/DateTime.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* @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
|
75
LoggerCpp/src/Log.cpp
Normal file
75
LoggerCpp/src/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 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
LoggerCpp/src/Logger.cpp
Normal file
61
LoggerCpp/src/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 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
LoggerCpp/src/Manager.cpp
Normal file
140
LoggerCpp/src/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 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
LoggerCpp/src/OutputConsole.cpp
Normal file
94
LoggerCpp/src/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 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
LoggerCpp/src/OutputDebug.cpp
Normal file
49
LoggerCpp/src/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 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
LoggerCpp/src/OutputFile.cpp
Normal file
101
LoggerCpp/src/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 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
|
|
@ -27,6 +27,7 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
#include "LoggerCpp/LoggerCpp.h"
|
||||
|
||||
#ifndef FL_VERSION
|
||||
#define FL_VERSION "?"
|
||||
|
@ -42,13 +43,13 @@
|
|||
|
||||
namespace fl {
|
||||
#ifdef FL_USE_FLOAT
|
||||
typedef float scalar;
|
||||
typedef float scalar;
|
||||
#else
|
||||
typedef double scalar;
|
||||
typedef double scalar;
|
||||
#endif
|
||||
|
||||
static const scalar nan = std::numeric_limits<scalar>::quiet_NaN();
|
||||
static const scalar inf = std::numeric_limits<scalar>::infinity();
|
||||
static const scalar nan = std::numeric_limits<scalar>::quiet_NaN();
|
||||
static const scalar inf = std::numeric_limits<scalar>::infinity();
|
||||
}
|
||||
|
||||
#define FL__FILE__ std::string(__FILE__).substr(std::string(FL_BUILD_PATH).size())
|
||||
|
@ -58,8 +59,8 @@ namespace fl {
|
|||
#define FL_AT FL__FILE__, __LINE__, __FUNCTION__
|
||||
|
||||
|
||||
#define FL_LOG(message) if (fl::fuzzylite::logging()){std::cout << FL_LOG_PREFIX << message << std::endl;}
|
||||
#define FL_LOGP(message) if (fl::fuzzylite::logging()){std::cout << message << std::endl;}
|
||||
#define FL_LOG(message) if (fl::fuzzylite::logging()){fl::fuzzylite::logger->info() << FL_LOG_PREFIX << message /*<< std::endl */;}
|
||||
#define FL_LOGP(message) if (fl::fuzzylite::logging()){fl::fuzzylite::logger->info() << message /* << std::endl */;}
|
||||
|
||||
#ifndef FL_DEBUG
|
||||
#define FL_DEBUG false
|
||||
|
@ -69,9 +70,9 @@ namespace fl {
|
|||
#define FL_END_DEBUG_BLOCK }
|
||||
|
||||
#define FL_DBG(message) FL_BEGIN_DEBUG_BLOCK \
|
||||
std::cout << FL__FILE__ << "::" << __FUNCTION__ << "[" << __LINE__ << "]:" \
|
||||
<< message << std::endl;\
|
||||
FL_END_DEBUG_BLOCK
|
||||
fl::fuzzylite::logger->debug() << FL__FILE__ << "::" << __FUNCTION__ << "[" << __LINE__ << "]:" \
|
||||
<< message /*<< std::endl*/;\
|
||||
FL_END_DEBUG_BLOCK
|
||||
|
||||
//class FL_EXPORT is require to build DLLs in Windows.
|
||||
#ifdef FL_WINDOWS
|
||||
|
@ -108,43 +109,44 @@ namespace fl {
|
|||
|
||||
namespace fl {
|
||||
|
||||
class FL_EXPORT fuzzylite {
|
||||
protected:
|
||||
static int _decimals;
|
||||
static scalar _macheps;
|
||||
static bool _debug;
|
||||
static bool _logging;
|
||||
class FL_EXPORT fuzzylite {
|
||||
protected:
|
||||
static int _decimals;
|
||||
static scalar _macheps;
|
||||
static bool _debug;
|
||||
static bool _logging;
|
||||
|
||||
public:
|
||||
static std::string name();
|
||||
static std::string fullname();
|
||||
static std::string version();
|
||||
static std::string longVersion();
|
||||
static std::string author();
|
||||
|
||||
static std::string date();
|
||||
static std::string platform();
|
||||
static std::string configuration();
|
||||
public:
|
||||
static Log::Logger *logger;
|
||||
static std::string name();
|
||||
static std::string fullname();
|
||||
static std::string version();
|
||||
static std::string longVersion();
|
||||
static std::string author();
|
||||
|
||||
static std::string floatingPoint();
|
||||
static std::string date();
|
||||
static std::string platform();
|
||||
static std::string configuration();
|
||||
|
||||
static bool debug();
|
||||
static void setDebug(bool debug);
|
||||
static std::string floatingPoint();
|
||||
|
||||
static int decimals();
|
||||
static void setDecimals(int decimals);
|
||||
static bool debug();
|
||||
static void setDebug(bool debug);
|
||||
|
||||
static scalar macheps();
|
||||
static void setMachEps(scalar macheps);
|
||||
static int decimals();
|
||||
static void setDecimals(int decimals);
|
||||
|
||||
static bool logging();
|
||||
static void setLogging(bool logging);
|
||||
};
|
||||
static scalar macheps();
|
||||
static void setMachEps(scalar macheps);
|
||||
|
||||
bool icasecmp(const std::string& l, const std::string& r);
|
||||
std::string toLower(std::string word);
|
||||
static bool logging();
|
||||
static void setLogging(bool logging);
|
||||
};
|
||||
|
||||
bool icasecmp(const std::string& l, const std::string& r);
|
||||
std::string toLower(std::string word);
|
||||
}
|
||||
|
||||
|
||||
#endif /* FL_FUZZYLITE_H */
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace fl {
|
|||
scalar fuzzylite::_macheps = 1e-5;
|
||||
bool fuzzylite::_debug = FL_DEBUG;
|
||||
bool fuzzylite::_logging = true;
|
||||
Log::Logger *fuzzylite::logger = NULL;
|
||||
//Log::Logger *fuzzylite::logger = new Log::Logger("FuzzyLite");
|
||||
|
||||
std::string fuzzylite::name() {
|
||||
return "fuzzyliteNG";
|
||||
|
@ -89,6 +91,8 @@ namespace fl {
|
|||
}
|
||||
|
||||
void fuzzylite::setDebug(bool debug) {
|
||||
if (debug && !fl::fuzzylite::logger)
|
||||
fl::fuzzylite::logger = new Log::Logger("FuzzyLite");
|
||||
_debug = debug;
|
||||
}
|
||||
|
||||
|
@ -113,6 +117,9 @@ namespace fl {
|
|||
}
|
||||
|
||||
void fuzzylite::setLogging(bool logging) {
|
||||
if (logging && !fl::fuzzylite::logger)
|
||||
fl::fuzzylite::logger = new Log::Logger("FuzzyLite");
|
||||
|
||||
_logging = logging;
|
||||
}
|
||||
|
||||
|
|
132
src/main.cpp
132
src/main.cpp
|
@ -22,15 +22,23 @@
|
|||
|
||||
#include "fl/Headers.h"
|
||||
|
||||
#include <typeinfo>
|
||||
#include <typeinfo>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
#include <signal.h>
|
||||
#include <fstream>
|
||||
#include <sys/time.h>
|
||||
#include "LoggerCpp/LoggerCpp.h"
|
||||
|
||||
using namespace fl;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void baz(){
|
||||
int *x = (int*) - 1; // make a bad pointer
|
||||
|
@ -184,9 +192,108 @@ void exportAllExamples(const std::string& from, const std::string& to) {
|
|||
}
|
||||
}
|
||||
|
||||
class TestLog : public Log::Output {
|
||||
public:
|
||||
explicit TestLog() {
|
||||
};
|
||||
virtual ~TestLog() {
|
||||
|
||||
}
|
||||
virtual void output(const Log::Channel::Ptr& aChannelPtr, const Log::Log& aLog) const {
|
||||
(void)aChannelPtr;
|
||||
std::cout << "test: " << aLog.getStream().str() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
fl::fuzzylite::setLogging(true);
|
||||
fl::fuzzylite::setDebug(true);
|
||||
|
||||
Log::Config::Vector configList;
|
||||
#if 0
|
||||
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");
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
Log::Config::addOutput(configList, "OutputDebug");
|
||||
#endif
|
||||
|
||||
// Create a Logger object, using a "Main.Example" Channel
|
||||
Log::Logger logger22("Main.Example");
|
||||
|
||||
|
||||
logger22.warning() << "NO logs before configure()";
|
||||
|
||||
try
|
||||
{
|
||||
// Configure the Log Manager (create the Output objects)
|
||||
//Log::Manager::configure(configList);
|
||||
Log::Manager::setCustomLogger(new TestLog());
|
||||
}
|
||||
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;
|
||||
logger22.debug() << "Variables ; '" << str << "', '" << ui << "', '" << dbl << "'";
|
||||
logger22.debug() << "Hexa = " << std::hex << 0x75af0 << " test";
|
||||
logger22.debug() << "Deci = " << std::right << std::setfill('0') << std::setw(8) << 76035 << " test";
|
||||
logger22.debug() << "sizeof(logger)=" << sizeof(logger22);
|
||||
|
||||
// Test outputs of various severity Level
|
||||
logger22.debug() << "Debug.";
|
||||
logger22.info() << "Info.";
|
||||
logger22.notice() << "Notice.";
|
||||
logger22.warning()<< "Warning.";
|
||||
logger22.error() << "Error.";
|
||||
logger22.critic() << "Critic.";
|
||||
|
||||
// Modify the output Level of the underlying Channel, and test various severity Level again
|
||||
logger22.setLevel(Log::Log::eWarning);
|
||||
logger22.debug() << "NO Debug."; // NO more debug logs
|
||||
logger22.info() << "NO Info."; // NO more info logs
|
||||
logger22.notice() << "NO Notice."; // NO more notice logs
|
||||
logger22.warning()<< "Warning.";
|
||||
logger22.error() << "Error.";
|
||||
logger22.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");
|
||||
logger22.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);
|
||||
logger22.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);
|
||||
logger22.debug() << "first logger re-activated";
|
||||
logger2.debug() << "second logger also re-activated";
|
||||
logger3.debug() << "third logger always active";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::set_terminate(fl::Exception::terminate);
|
||||
std::set_unexpected(fl::Exception::terminate);
|
||||
signal(SIGSEGV, fl::Exception::signalHandler);
|
||||
|
@ -194,8 +301,7 @@ int main(int argc, char** argv) {
|
|||
signal(SIGILL, fl::Exception::signalHandler);
|
||||
signal(SIGSEGV, fl::Exception::signalHandler);
|
||||
signal(SIGFPE, fl::Exception::signalHandler);
|
||||
fl::fuzzylite::setLogging(true);
|
||||
fl::fuzzylite::setDebug(true);
|
||||
|
||||
#ifdef FL_UNIX
|
||||
signal(SIGBUS, fl::Exception::signalHandler);
|
||||
signal(SIGPIPE, fl::Exception::signalHandler);
|
||||
|
@ -213,7 +319,7 @@ int main(int argc, char** argv) {
|
|||
// return 0;
|
||||
// return Console::main(argc, argv);
|
||||
fl::Engine* engine = new fl::Engine("simple-dimmer");
|
||||
|
||||
|
||||
fl::InputVariable* ambient = new fl::InputVariable;
|
||||
ambient->setName("Ambient");
|
||||
ambient->setRange(0.000, 1.000);
|
||||
|
@ -250,7 +356,7 @@ fl::Engine* engine = new fl::Engine("simple-dimmer");
|
|||
power1->addTerm(new fl::Triangle("MEDIUM", 0.500, 1.500));
|
||||
power1->addTerm(new fl::Triangle("HIGH", 1.000, 2.000));
|
||||
engine->addOutputVariable(power1);
|
||||
|
||||
|
||||
fl::RuleBlock* ruleblock = new fl::RuleBlock;
|
||||
ruleblock->addRule(fl::Rule::parse("if Ambient1 is DARK and Ambient is Now(2:27pm) then Power is very HiGh", engine));
|
||||
ruleblock->addRule(fl::Rule::parse("if Ambient is DARK then Power is HIGH", engine));
|
||||
|
@ -259,10 +365,10 @@ fl::Engine* engine = new fl::Engine("simple-dimmer");
|
|||
ruleblock->addRule(fl::Rule::parse("if Ambient is BRIGHT then in 533m set Power is LOW and Power1 is HIGH", engine));
|
||||
//# ruleblock->addRule(fl::Rule::parse("if Ambient is BRIGHT then in 5m Power is LOW", engine));
|
||||
engine->addRuleBlock(ruleblock);
|
||||
|
||||
|
||||
//No Conjunction or Disjunction is needed
|
||||
engine->configure("AlgebraicProduct", "", "AlgebraicProduct", "AlgebraicSum", "Centroid");
|
||||
|
||||
|
||||
std::string status;
|
||||
if (not engine->isReady(&status))
|
||||
throw fl::Exception("Engine not ready. "
|
||||
|
@ -283,18 +389,18 @@ fl::Engine* engine = new fl::Engine("simple-dimmer");
|
|||
fl::scalar light = ambient->getMinimum() + i * (ambient->range() / 50);
|
||||
ambient->setInputValue(light);
|
||||
engine->process();
|
||||
FL_LOG("Ambient.input = " << fl::Op::str(light) << " -> " <<
|
||||
"Power.output = " << fl::Op::str(power->defuzzify()) <<
|
||||
" Timer: " << power->getTimer() <<
|
||||
" Power1.output = " << fl::Op::str(power1->defuzzify()) <<
|
||||
FL_LOG("Ambient.input = " << fl::Op::str(light) << " -> " <<
|
||||
"Power.output = " << fl::Op::str(power->defuzzify()) <<
|
||||
" Timer: " << power->getTimer() <<
|
||||
" Power1.output = " << fl::Op::str(power1->defuzzify()) <<
|
||||
" Timer: " << power1->getTimer());
|
||||
}
|
||||
#endif
|
||||
std::cout << engine->toString() << std::endl;
|
||||
fl::fuzzylite::logger->debug() << engine->toString();
|
||||
|
||||
Exporter* exporter;
|
||||
exporter = new JavaExporter;
|
||||
std::cout << exporter->toString(engine) << std::endl;
|
||||
fl::fuzzylite::logger->debug() << exporter->toString(engine);
|
||||
#if 0
|
||||
else if (to == "fld") exporter = new FldExporter(" ", 1024);
|
||||
else if (to == "fcl") exporter = new FclExporter;
|
||||
|
|
Loading…
Add table
Reference in a new issue