From e032f726837af9b2c4fe836450306f4805798c77 Mon Sep 17 00:00:00 2001 From: Andrey Astafyev Date: Wed, 2 Oct 2019 15:22:47 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D0=BD=D0=B0=20=D0=B6=D1=83?= =?UTF-8?q?=D1=80=D0=BD=D0=B0=D0=BB=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 4 ++ src/log/CMakeLists.txt | 42 ++++++++++++++++++ src/log/spdlog.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++ src/log/spdlog.hpp | 70 ++++++++++++++++++++++++++++++ 4 files changed, 213 insertions(+) create mode 100644 src/log/CMakeLists.txt create mode 100644 src/log/spdlog.cpp create mode 100644 src/log/spdlog.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b610d23..866cdc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,9 @@ find_package(PkgConfig) # Qt5 find_package(Qt5 COMPONENTS Core Network Gui Widgets DBus Concurrent Sql REQUIRED) +pkg_check_modules(FMT fmt>=5.3.0) +pkg_check_modules(SPDLOG spdlog>=1.3.1) + # Автоматически генерируемый заголовочный файл cmlib_config_hpp_generate() @@ -39,6 +42,7 @@ include(ExternalProject) # Библиотеки add_subdirectory(src/base) add_subdirectory(src/filesystem) +add_subdirectory(src/log) # Примеры add_subdirectory(examples/filesystem) diff --git a/src/log/CMakeLists.txt b/src/log/CMakeLists.txt new file mode 100644 index 0000000..8826ed1 --- /dev/null +++ b/src/log/CMakeLists.txt @@ -0,0 +1,42 @@ +# Название основной цели и имя библиотеки в текущем каталоге +set(current_target log) + +# Список файлов исходных текстов +set(current_target_sources + ${CMAKE_CURRENT_SOURCE_DIR}/spdlog.cpp +) + +# Список заголовочных файлов (используется для установки) +set(current_target_headers + ${CMAKE_CURRENT_SOURCE_DIR}/spdlog.hpp +) + +add_common_library(TARGET ${current_target} SOURCES ${current_target_sources}) +common_target_properties(${current_target}) +add_clang_tidy_check(${current_target} ${current_target_sources}) +add_clang_analyze_check(${current_target} ${current_target_sources}) +add_clazy_check(${current_target} ${current_target_sources}) +add_pvs_check(${current_target}) +add_uncrustify_format(${current_target} ${current_target_sources} ${current_target_headers}) + +target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS}) +target_include_directories(${current_target} SYSTEM PUBLIC ${FMT_INCLUDE_DIRS}) +target_include_directories(${current_target} SYSTEM PUBLIC ${SPDLOG_INCLUDE_DIRS}) +target_include_directories(${current_target} PRIVATE ${CMAKE_SOURCE_DIR}/src/base) + +# Цель, используемая только для установки заголовочных файлов без компиляции проекта +add_custom_target(${current_target}-install-headers + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=headers -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" + ) + +# Правила для установки +install(TARGETS ${current_target}_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) +if(BUILD_SHARED_LIBS) + install(TARGETS ${current_target}_shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() +install(FILES ${current_target_headers} + COMPONENT headers + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${current_target}) +install(FILES ${CMAKE_BINARY_DIR}/${current_target}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + diff --git a/src/log/spdlog.cpp b/src/log/spdlog.cpp new file mode 100644 index 0000000..60bf5e2 --- /dev/null +++ b/src/log/spdlog.cpp @@ -0,0 +1,97 @@ +#include + +#include +#include +#include +#include +#include + +#include "config.hpp" +#include "spdlog.hpp" + +namespace myx { + +namespace log { + +static std::shared_ptr< spdlog::logger > logger = nullptr; +static std::shared_ptr< spdlog::logger > logger_mt = nullptr; + + +std::shared_ptr< spdlog::logger > default_logger() +{ + return( logger ); +} + + +std::shared_ptr< spdlog::logger > default_mt_logger() +{ + return( logger_mt ); +} + + +void spdlog_init() +{ + auto nameSt = fmt::format( "{}_{}", PROJECT_NAME, "st" ); + auto sinksSt = std::make_shared< std::vector< spdlog::sink_ptr > >(); + + #ifndef RELEASE + sinksSt->push_back( std::make_shared< spdlog::sinks::ansicolor_stdout_sink_st >() ); + sinksSt->push_back( std::make_shared< spdlog::sinks::daily_file_sink_st >( nameSt, 23, 59 ) ); + #endif + sinksSt->push_back( std::make_shared< spdlog::sinks::syslog_sink_st >( nameSt ) ); + logger = std::make_shared< spdlog::logger >( nameSt, sinksSt->begin(), sinksSt->end() ); + logger->flush_on( spdlog::level::warn ); + spdlog::register_logger( logger ); + + spdlog::init_thread_pool( 128, 1 ); + auto nameMt = fmt::format( "{}_{}", PROJECT_NAME, "mt" ); + auto sinksMt = std::make_shared< std::vector< spdlog::sink_ptr > >(); + #ifndef RELEASE + sinksMt->push_back( std::make_shared< spdlog::sinks::ansicolor_stdout_sink_mt >() ); + sinksMt->push_back( std::make_shared< spdlog::sinks::daily_file_sink_mt >( nameMt, 23, 59 ) ); + #endif + sinksMt->push_back( std::make_shared< spdlog::sinks::syslog_sink_mt >( nameMt ) ); + logger_mt = std::make_shared< spdlog::async_logger >( nameMt, sinksMt->begin(), sinksMt->end(), spdlog::thread_pool() ); + logger_mt->flush_on( spdlog::level::warn ); + spdlog::register_logger( logger_mt ); + + #ifndef QT_NO_DEBUG + spdlog::set_level( spdlog::level::debug ); + #endif +} // spdlog_init + + +void qt_message_handler( QtMsgType type, const QMessageLogContext& context, const QString& qMsg ) +{ + if ( !logger ) + { + return; + } + Q_UNUSED( context ) + + const char* msg = qMsg.toUtf8().constData(); + + switch ( type ) + { + case QtDebugMsg: + logger->debug( msg ); + break; + case QtInfoMsg: + logger->info( msg ); + break; + case QtWarningMsg: + logger->warn( msg ); + break; + case QtCriticalMsg: + logger->critical( msg ); + break; + case QtFatalMsg: + logger->critical( "FATAL: %s", msg ); + QCoreApplication::exit( 1 ); + break; + } +} // messageHandler + +} // namespace log + +} // namespace myx diff --git a/src/log/spdlog.hpp b/src/log/spdlog.hpp new file mode 100644 index 0000000..fecdad5 --- /dev/null +++ b/src/log/spdlog.hpp @@ -0,0 +1,70 @@ +#ifndef MYX_LOG_SPDLOG_HPP_ +#define MYX_LOG_SPDLOG_HPP_ + +#include +#include +#include + +namespace myx { + +namespace log { + +void spdlog_init(); +std::shared_ptr< spdlog::logger > default_logger(); +std::shared_ptr< spdlog::logger > default_mt_logger(); +void qt_message_handler( QtMsgType type, const QMessageLogContext& context, const QString& qMsg ); + + +template < class F, class ... Args > +void trace( F&& format, Args&& ... args ) noexcept +{ + default_logger()->trace( std::forward< F >( format ), + std::forward< Args >( args )... ); +} + + +template < class F, class ... Args > +void debug( F&& format, Args&& ... args ) noexcept +{ + default_logger()->debug( std::forward< F >( format ), + std::forward< Args >( args )... ); +} + + +template < class F, class ... Args > +void info( F&& format, Args&& ... args ) noexcept +{ + default_logger()->info( std::forward< F >( format ), + std::forward< Args >( args )... ); +} + + +template < class F, class ... Args > +void warn( F&& format, Args&& ... args ) noexcept +{ + default_logger()->warn( std::forward< F >( format ), + std::forward< Args >( args )... ); +} + + +template < class F, class ... Args > +void error( F&& format, Args&& ... args ) noexcept +{ + default_logger()->error( std::forward< F >( format ), + std::forward< Args >( args )... ); +} + + +template < class F, class ... Args > +void log( spdlog::level::level_enum lv, F&& format, Args&& ... args ) noexcept +{ + default_logger()->log( lv, std::forward< F >( format ), + std::forward< Args >( args )... ); +} + +} // namespace log + +} // namespace myx + + +#endif // ifndef MYX_LOG_SPDLOG_HPP_