2022年3月7日 星期一

spdlog in CLion in 2022

 https://github.com/gabime/spdlog


Ubuntu new project, language standard use "C++17" or "C++14"


"Copy the include folder to your build tree and use a C++11 compiler" so that "include/spdlog/spdlog.h" exists

https://github.com/gabime/spdlog/tree/v1.x/include


CMakeLists.txt

cmake_minimum_required(VERSION 3.21)
project(untitled8)
set(CMAKE_CXX_STANDARD 17)
add_executable(untitled8 main.cpp)
include_directories("include")

main.cpp

#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}


Basic usage

#include "spdlog/spdlog.h"

int main() 
{
    spdlog::info("Welcome to spdlog!");
    spdlog::error("Some error message with arg: {}", 1);
    
    spdlog::warn("Easy padding in numbers like {:08d}", 12);
    spdlog::critical("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
    spdlog::info("Support for floats {:03.2f}", 1.23456);
    spdlog::info("Positional args are {1} {0}..", "too", "supported");
    spdlog::info("{:<30}", "left aligned");
    
    spdlog::set_level(spdlog::level::debug); // Set global log level to debug
    spdlog::debug("This message should be displayed..");    
    
    // change log pattern
    spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
    
    // Compile time log levels
    // define SPDLOG_ACTIVE_LEVEL to desired level
    SPDLOG_TRACE("Some trace message with param {}", 42);
    SPDLOG_DEBUG("Some debug message");
}


Comprehensive

CMakeList.txt

cmake_minimum_required(VERSION 3.21)
project(untitled8)
set(CMAKE_CXX_STANDARD 17)
add_executable(untitled8 main.cpp)
include_directories("include")

find_package (Threads REQUIRED)
target_link_libraries(untitled8 ${CMAKE_THREAD_LIBS_INIT})

main.cpp

#include <iostream>

// trace 0 > debug 1 > info 2 > warn 3 > error 4 > critical 5 > off 6
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG

#include "spdlog/spdlog.h"
struct TempLogLevel {
TempLogLevel(spdlog::level::level_enum newLevel = spdlog::level::debug) : oldLevel(spdlog::get_level()) {
spdlog::set_level(newLevel);
}
~TempLogLevel() {
spdlog::set_level(oldLevel);
}
private:
spdlog::level::level_enum oldLevel;
};

// Basic usage
#include "spdlog/spdlog.h"
void basic() {
spdlog::debug("This message should not be displayed..");

spdlog::info("Welcome to spdlog!");
spdlog::error("Some error message with arg: {}", 1);

spdlog::warn("Easy padding in numbers like {:08d}", 12);
spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
spdlog::info("Support for floats {:03.2f}", 1.23456);
spdlog::info("Positional args are {1} {0}..", "too", "supported");
spdlog::info("{:<30}", "left aligned");


spdlog::set_level(spdlog::level::debug); // Set global log level to debug
spdlog::debug("This message should be displayed..");
spdlog::set_level(spdlog::level::info);

// change log pattern
//spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");

// Compile time log levels
// define SPDLOG_ACTIVE_LEVEL to desired level
SPDLOG_TRACE("Some trace message with param {}", 42);
SPDLOG_DEBUG("see me if you #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG");

SPDLOG_INFO("SPDLOG_INFO");
}

// Create stdout/stderr logger object
#include "spdlog/sinks/stdout_color_sinks.h"
void stdout_example()
{
// create color multi threaded logger
auto console = spdlog::stdout_color_mt("console");
console->info("apple");
auto err_logger = spdlog::stderr_color_mt("stderr");
spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
}

// Basic file logger
#include "spdlog/sinks/basic_file_sink.h"
void basic_logfile_example()
{
try
{
auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic-log.txt");
logger->info("spdlog::basic_logger_mt() to logs/basic-log.txt");
}
catch (const spdlog::spdlog_ex &ex)
{
std::cout << "Log init failed: " << ex.what() << std::endl;
}
}

// Rotating files
#include "spdlog/sinks/rotating_file_sink.h"
void rotating_example()
{
// Create a file rotating logger with 5mb size max and 3 rotated files
auto max_size = 1048576 * 5; // 5242880
auto max_files = 3;
auto logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", max_size, max_files);
for (int i=0; i<1000*1000; ++i) {
logger->info("time {}", time(nullptr));
}
// acutal file is 5242868, 12 bytes less than 5242880
/*
-rw-rw-r-- 1 user user 5242868 3 7 11:45 rotating.1.txt
-rw-rw-r-- 1 user user 5242868 3 7 11:45 rotating.2.txt
-rw-rw-r-- 1 user user 5242868 3 7 11:45 rotating.3.txt
-rw-rw-r-- 1 user user 5085584 3 7 11:45 rotating.txt
*/
}

// Daily files
#include "spdlog/sinks/daily_file_sink.h"
void daily_example()
{
// Create a daily logger - a new file is created every day on 2:30am
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
}

// Backtrace support
void backtrace() {
// Debug messages can be stored in a ring buffer instead of being logged immediately.
// This is useful in order to display debug logs only when really needed (e.g. when error happens).
// When needed, call dump_backtrace() to see them.

spdlog::enable_backtrace(32); // Store the latest 32 messages in a buffer. Older messages will be dropped.
// or my_logger->enable_backtrace(32)..
for(int i = 0; i < 100; i++)
{
spdlog::debug("Backtrace message {}", i); // not logged yet..
}
// e.g. if some error happened:
spdlog::dump_backtrace(); // log them now! show the last 32 messages

// or my_logger->dump_backtrace(32)..
}

// Periodic flush
void periodic() {
// periodically flush all *registered* loggers every 3 seconds:
// warning: only use if all your loggers are thread safe ("_mt" loggers)
spdlog::flush_every(std::chrono::seconds(3));
}

// Stopwatch
#include "spdlog/stopwatch.h"
void stopwatch_example()
{
spdlog::stopwatch sw;
int count = 0;
for (int i=0; i<1000*1000; ++i) {
count += i;
}
spdlog::debug("Elapsed {}", sw);
spdlog::debug("Elapsed {:.3}", sw);
spdlog::debug("Elapsed {:.9}s", sw);
// need below in cmakes
// find_package (Threads REQUIRED)
// target_link_libraries(untitled8 ${CMAKE_THREAD_LIBS_INIT})
}

// Log binary data in hex
// many types of std::container<char> types can be used.
// ranges are supported too.
// format flags:
// {:X} - print in uppercase.
// {:s} - don't separate each byte with space.
// {:p} - don't print the position on each line start.
// {:n} - don't split the output to lines.
// {:a} - show ASCII if :n is not set.
#include "spdlog/fmt/bin_to_hex.h"
void binary_example()
{
auto console = spdlog::get("console");
std::array<char, 80> buf;
console->info("Binary example: {}", spdlog::to_hex(buf));
console->info("Another binary example:{:n}", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10));
// more examples:
// logger->info("uppercase: {:X}", spdlog::to_hex(buf));
// logger->info("uppercase, no delimiters: {:Xs}", spdlog::to_hex(buf));
// logger->info("uppercase, no delimiters, no position info: {:Xsp}", spdlog::to_hex(buf));
}

// Logger with multi sinks - each with different format and log level
// create logger with 2 targets with different log levels and formats.
// the console will show only warnings or errors, while the file will log all.
void multi_sink_example()
{
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
console_sink->set_level(spdlog::level::warn);
console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v");

auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multisink.txt", true);
file_sink->set_level(spdlog::level::trace);

spdlog::logger logger("multi_sink", {console_sink, file_sink});
logger.set_level(spdlog::level::debug);
logger.warn("this should appear in both console and file");
logger.info("this message should not appear in the console, only in the file");
}

// Asynchronous logging
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
void async_example()
{
// default thread pool settings can be modified *before* creating the async logger:
// spdlog::init_thread_pool(8192, 1); // queue with 8k items and 1 backing thread.
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
async_file->info("basic_logger_mt async_factory logs/async_log.txt");
// alternatively:
// auto async_file = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async_file_logger", "logs/async_log.txt");
}

// Asynchronous logger with multi sinks
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/rotating_file_sink.h"
void multi_sink_example2()
{
spdlog::init_thread_pool(8192, 1);
auto stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt >();
auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("logs/multi_sink_example2.txt", 1024*1024*10, 3);
std::vector<spdlog::sink_ptr> sinks {stdout_sink, rotating_sink};
auto logger = std::make_shared<spdlog::async_logger>("loggername", sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
spdlog::register_logger(logger);
logger->info("multi_sink_example2()");
}

// User defined types
// user defined types logging by implementing operator<<
#include "spdlog/fmt/ostr.h" // must be included
struct my_type
{
int i;
template<typename OStream>
friend OStream &operator<<(OStream &os, const my_type &c)
{
return os << "[my_type i=" << c.i << "]";
}
};
void user_defined_example()
{
spdlog::get("console")->info("user defined type: {}", my_type{14});
}

// User defined flags in the log pattern
// Log patterns can contain custom flags.
// the following example will add new flag '%*' - which will be bound to a <my_formatter_flag> instance.
#include "spdlog/pattern_formatter.h"
class my_formatter_flag : public spdlog::custom_flag_formatter
{
public:
void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override
{
std::string some_txt = "custom-flag";
dest.append(some_txt.data(), some_txt.data() + some_txt.size());
}

std::unique_ptr<custom_flag_formatter> clone() const override
{
return spdlog::details::make_unique<my_formatter_flag>();
}
};
void custom_flags_example()
{
auto formatter = std::make_unique<spdlog::pattern_formatter>();
formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v");
spdlog::set_formatter(std::move(formatter));
}

// Custom error handler
#include "spdlog/sinks/syslog_sink.h"
void syslog_example()
{
std::string ident = "spdlog-example";
auto syslog_logger = spdlog::syslog_logger_mt("syslog", ident, LOG_PID);
syslog_logger->warn("This is warning that will end up in syslog.");
// tail -f /var/log/syslog
/*
Mar 7 12:25:08 ricky-ryzen systemd[1440]: Starting Kite Updater...
Mar 7 12:25:10 ricky-ryzen spdlog-example[1578877]: This is warning that will end up in syslog.
Mar 7 12:25:10 ricky-ryzen systemd[1440]: kite-updater.service: Succeeded.
*/
}

// Android example
#ifdef __ANDROID__
#include "spdlog/sinks/android_sink.h"
void android_example()
{
std::string tag = "spdlog-android";
auto android_logger = spdlog::android_logger_mt("android", tag);
android_logger->critical("Use \"adb shell logcat\" to view this message.");
}
#endif

// Load log levels from env variable or from argv
#include "spdlog/cfg/env.h"
int main_env()
{
spdlog::cfg::load_env_levels();
return 0;
}

// Load log levels from env variable or from argv
#include "spdlog/cfg/argv.h" // for loading levels from argv
int main_argv (int argc, char *argv[])
{
// ./example SPDLOG_LEVEL=info,mylogger=trace
// #include "spdlog/cfg/argv.h" // for loading levels from argv
spdlog::cfg::load_argv_levels(argc, argv);
return 0;
}

// Log file open/close event handlers
// You can get callbacks from spdlog before/after log file has been opened or closed.
// This is useful for cleanup procedures or for adding someting the start/end of the log files.
void file_events_example()
{
// pass the spdlog::file_event_handlers to file sinks for open/close log file notifications
spdlog::file_event_handlers handlers;
handlers.before_open = [](spdlog::filename_t filename) { spdlog::info("Before opening {}", filename); };
handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) { fputs("After opening\n", fstream); };
handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) { fputs("Before closing\n", fstream); };
handlers.after_close = [](spdlog::filename_t filename) { spdlog::info("After closing {}", filename); };
auto my_logger = spdlog::basic_logger_st("some_logger", "logs/events-sample.txt", true, handlers);
}

// Replace the Default Logger
void replace_default_logger_example()
{
auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true);
spdlog::set_default_logger(new_logger);
spdlog::info("new logger log message");
}

int main(int argc, char *argv[])
{
basic();
stdout_example();
basic_logfile_example();
rotating_example();
backtrace();
periodic();
stopwatch_example();
binary_example();
multi_sink_example();
async_example();
multi_sink_example2();
user_defined_example();
custom_flags_example();
syslog_example();
#ifdef __ANDROID__
android_example();
#endif
main_env();
main_argv(argc, argv);
file_events_example();
replace_default_logger_example();
return 0;
}



End

End

End



沒有留言:

張貼留言

2007 to 2023 HP and Dell Servers Comparison

  HP Gen5 to Gen11  using ChatGPT HP ProLiant Gen Active Years CPU Socket Popular HP CPUs Cores Base Clock Max RAM Capacity Comparable Dell ...