2022-03 I bought AC9560NGW at $27 that can reaches 866Mhz with ASUS AC Router. Sellers said 9260 at $70 with better compatibility with same functions. Someone sells AX210 with pcie x1 adaptor at $129.
2022-03 I bought AC8260 at $28 with M2 to PCIe x1 at $20.
2022-04
AC8260 on MSI B450M Mortar Max needs to set BIOS PCIe X1 from PCIE_2 to PCIE_3. Ubuntu 20.04 works well with 866MHz. Test Speed with iCable 130MB/s.
$ wget https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz $ tar -xzvf libevent-2.1.8-stable.tar.gz $ cd libevent-2.1.8-stable $ ./configure $ make $ sudo make install
#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)"); }
// 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)); }
// 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()); }
// 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"); }