Compare commits

...

4 Commits

Author SHA1 Message Date
gabime
5284043ddb Update jetbrains logo 2025-05-12 16:01:16 +03:00
gabime
1d1e1df770 Update jetbrains logo 2025-05-12 15:38:00 +03:00
Gabi Melman
37ff466454 Add coverity scan to CI and fix warnings (#3400)
* Move callback function in thread_pool ctor

* Added const qualifiers to logger.h

* Remove unused includes from file_helper-inl.h

* Fix comments and remove unused include from helpers-inl.h

* Fix typo in comment for set_default_logger method.

* Use `std::move` for `old_logger` in `set_default_logger`.

* Use std::move in example

* Wrap `main` content in try block for exception safety.

* Added coverity to ci
2025-05-12 15:36:07 +03:00
Gabi Melman
677a2d93e6 Update test_stopwatch.cpp 2025-05-09 13:22:39 +03:00
10 changed files with 108 additions and 62 deletions

51
.github/workflows/coverity_scan.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: coverity-linux
on: [pull_request]
permissions:
contents: read
jobs:
coverity_scan:
runs-on: ubuntu-latest
name: Coverity Scan
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y curl build-essential cmake pkg-config libsystemd-dev
- name: Download Coverity Tool
run: |
curl -s -L --output coverity_tool.tgz "https://scan.coverity.com/download/linux64?token=${{ secrets.COVERITY_TOKEN }}&project=gabime%2Fspdlog"
mkdir coverity_tool
tar -C coverity_tool --strip-components=1 -xf coverity_tool.tgz
echo "$PWD/coverity_tool/bin" >> $GITHUB_PATH
- name: Build with Coverity
run: |
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17
cd ..
cov-build --dir cov-int make -C build -j4
- name: Submit results to Coverity
run: |
tar czf cov-int.tgz cov-int
response=$(curl --silent --show-error --fail \
--form token="${{ secrets.COVERITY_TOKEN }}" \
--form file=@cov-int.tgz \
--form version="GitHub PR #${{ github.event.pull_request.number }}" \
--form description="CI run for PR" \
https://scan.coverity.com/builds?project=gabime%2Fspdlog)
echo "$response"
if echo "$response" | grep -qi "Build successfully submitted"; then
echo "Coverity upload succeeded"
else
echo "Coverity upload failed or was rejected"
exit 1
fi

View File

@@ -524,6 +524,7 @@ Documentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki)
--- ---
Thanks to [JetBrains](https://www.jetbrains.com/?from=spdlog) for donating product licenses to help develop **spdlog** <a href="https://www.jetbrains.com/?from=spdlog"><img src="logos/jetbrains-variant-4.svg" width="94" align="center" /></a> ### Powered by
<a href="https://jb.gg/OpenSource">
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" alt="JetBrains logo" width="200">
</a>

View File

@@ -33,41 +33,41 @@ void mdc_example();
#include "spdlog/fmt/ostr.h" // support for user defined types #include "spdlog/fmt/ostr.h" // support for user defined types
int main(int, char *[]) { int main(int, char *[]) {
// Log levels can be loaded from argv/env using "SPDLOG_LEVEL"
load_levels_example();
spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR,
SPDLOG_VER_PATCH);
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("{:>8} aligned, {:<8} aligned", "right", "left");
// Runtime log levels
spdlog::set_level(spdlog::level::info); // Set global log level to info
spdlog::debug("This message should not be displayed!");
spdlog::set_level(spdlog::level::trace); // Set specific logger's log level
spdlog::debug("This message should be displayed..");
// Customize msg format for all loggers
spdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [thread %t] %v");
spdlog::info("This an info message with custom format");
spdlog::set_pattern("%+"); // back to default format
spdlog::set_level(spdlog::level::info);
// Backtrace support
// Loggers can store in a ring buffer all messages (including debug/trace) for later inspection.
// When needed, call dump_backtrace() to see what happened:
spdlog::enable_backtrace(10); // create ring buffer with capacity of 10 messages
for (int i = 0; i < 100; i++) {
spdlog::debug("Backtrace message {}", i); // not logged..
}
// e.g. if some error happened:
spdlog::dump_backtrace(); // log them now!
try { try {
// Log levels can be loaded from argv/env using "SPDLOG_LEVEL"
load_levels_example();
spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR,
SPDLOG_VER_PATCH);
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("{:>8} aligned, {:<8} aligned", "right", "left");
// Runtime log levels
spdlog::set_level(spdlog::level::info); // Set global log level to info
spdlog::debug("This message should not be displayed!");
spdlog::set_level(spdlog::level::trace); // Set specific logger's log level
spdlog::debug("This message should be displayed..");
// Customize msg format for all loggers
spdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [thread %t] %v");
spdlog::info("This an info message with custom format");
spdlog::set_pattern("%+"); // back to default format
spdlog::set_level(spdlog::level::info);
// Backtrace support
// Loggers can store in a ring buffer all messages (including debug/trace) for later
// inspection. When needed, call dump_backtrace() to see what happened:
spdlog::enable_backtrace(10); // create ring buffer with capacity of 10 messages
for (int i = 0; i < 100; i++) {
spdlog::debug("Backtrace message {}", i); // not logged..
}
// e.g. if some error happened:
spdlog::dump_backtrace(); // log them now!
stdout_logger_example(); stdout_logger_example();
basic_example(); basic_example();
rotating_example(); rotating_example();
@@ -371,15 +371,13 @@ void replace_default_logger_example() {
// store the old logger so we don't break other examples. // store the old logger so we don't break other examples.
auto old_logger = spdlog::default_logger(); auto old_logger = spdlog::default_logger();
auto new_logger = auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/somelog.txt", true);
spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true); spdlog::set_default_logger(std::move(new_logger));
spdlog::set_default_logger(new_logger);
spdlog::set_level(spdlog::level::info); spdlog::set_level(spdlog::level::info);
spdlog::debug("This message should not be displayed!"); spdlog::debug("This message should not be displayed!");
spdlog::set_level(spdlog::level::trace); spdlog::set_level(spdlog::level::trace);
spdlog::debug("This message should be displayed.."); spdlog::debug("This message should be displayed..");
spdlog::set_default_logger(std::move(old_logger));
spdlog::set_default_logger(old_logger);
} }
// Mapped Diagnostic Context (MDC) is a map that stores key-value pairs (string values) in thread // Mapped Diagnostic Context (MDC) is a map that stores key-value pairs (string values) in thread

View File

@@ -9,7 +9,6 @@
#include <spdlog/details/os.h> #include <spdlog/details/os.h>
#include <spdlog/details/registry.h> #include <spdlog/details/registry.h>
#include <spdlog/spdlog.h>
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
@@ -36,7 +35,7 @@ inline std::string &trim_(std::string &str) {
return str; return str;
} }
// return (name,value) trimmed pair from given "name=value" string. // return (name,value) trimmed pair from the given "name = value" string.
// return empty string on missing parts // return empty string on missing parts
// "key=val" => ("key", "val") // "key=val" => ("key", "val")
// " key = val " => ("key", "val") // " key = val " => ("key", "val")
@@ -55,7 +54,7 @@ inline std::pair<std::string, std::string> extract_kv_(char sep, const std::stri
return std::make_pair(trim_(k), trim_(v)); return std::make_pair(trim_(k), trim_(v));
} }
// return vector of key/value pairs from sequence of "K1=V1,K2=V2,.." // return vector of key/value pairs from a sequence of "K1=V1,K2=V2,.."
// "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...} // "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...}
inline std::unordered_map<std::string, std::string> extract_key_vals_(const std::string &str) { inline std::unordered_map<std::string, std::string> extract_key_vals_(const std::string &str) {
std::string token; std::string token;
@@ -82,14 +81,14 @@ SPDLOG_INLINE void load_levels(const std::string &input) {
bool global_level_found = false; bool global_level_found = false;
for (auto &name_level : key_vals) { for (auto &name_level : key_vals) {
auto &logger_name = name_level.first; const auto &logger_name = name_level.first;
auto level_name = to_lower_(name_level.second); const auto &level_name = to_lower_(name_level.second);
auto level = level::from_str(level_name); auto level = level::from_str(level_name);
// ignore unrecognized level names // ignore unrecognized level names
if (level == level::off && level_name != "off") { if (level == level::off && level_name != "off") {
continue; continue;
} }
if (logger_name.empty()) // no logger name indicate global level if (logger_name.empty()) // no logger name indicates global level
{ {
global_level_found = true; global_level_found = true;
global_level = level; global_level = level;

View File

@@ -11,10 +11,8 @@
#include <spdlog/details/os.h> #include <spdlog/details/os.h>
#include <cerrno> #include <cerrno>
#include <chrono>
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <thread>
#include <tuple> #include <tuple>
namespace spdlog { namespace spdlog {

View File

@@ -101,7 +101,7 @@ SPDLOG_INLINE std::shared_ptr<logger> registry::default_logger() {
SPDLOG_INLINE logger *registry::get_default_raw() { return default_logger_.get(); } SPDLOG_INLINE logger *registry::get_default_raw() { return default_logger_.get(); }
// set default logger. // set default logger.
// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. // the default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map.
SPDLOG_INLINE void registry::set_default_logger(std::shared_ptr<logger> new_default_logger) { SPDLOG_INLINE void registry::set_default_logger(std::shared_ptr<logger> new_default_logger) {
std::lock_guard<std::mutex> lock(logger_map_mutex_); std::lock_guard<std::mutex> lock(logger_map_mutex_);
if (new_default_logger != nullptr) { if (new_default_logger != nullptr) {

View File

@@ -35,7 +35,7 @@ SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items,
SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items,
size_t threads_n, size_t threads_n,
std::function<void()> on_thread_start) std::function<void()> on_thread_start)
: thread_pool(q_max_items, threads_n, on_thread_start, [] {}) {} : thread_pool(q_max_items, threads_n, std::move(on_thread_start), [] {}) {}
SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n) SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n)
: thread_pool(q_max_items, threads_n, [] {}, [] {}) {} : thread_pool(q_max_items, threads_n, [] {}, [] {}) {}
@@ -94,8 +94,7 @@ void SPDLOG_INLINE thread_pool::worker_loop_() {
} }
// process next message in the queue // process next message in the queue
// return true if this thread should still be active (while no terminate msg // returns true if this thread should still be active (while no terminated msg was received)
// was received)
bool SPDLOG_INLINE thread_pool::process_next_msg_() { bool SPDLOG_INLINE thread_pool::process_next_msg_() {
async_msg incoming_async_msg; async_msg incoming_async_msg;
q_.dequeue(incoming_async_msg); q_.dequeue(incoming_async_msg);

View File

@@ -57,7 +57,7 @@ SPDLOG_INLINE void logger::swap(spdlog::logger &other) SPDLOG_NOEXCEPT {
std::swap(tracer_, other.tracer_); std::swap(tracer_, other.tracer_);
} }
SPDLOG_INLINE void swap(logger &a, logger &b) { a.swap(b); } SPDLOG_INLINE void swap(logger &a, logger &b) noexcept { a.swap(b); }
SPDLOG_INLINE void logger::set_level(level::level_enum log_level) { level_.store(log_level); } SPDLOG_INLINE void logger::set_level(level::level_enum log_level) { level_.store(log_level); }
@@ -163,12 +163,12 @@ SPDLOG_INLINE void logger::dump_backtrace_() {
} }
} }
SPDLOG_INLINE bool logger::should_flush_(const details::log_msg &msg) { SPDLOG_INLINE bool logger::should_flush_(const details::log_msg &msg) const {
auto flush_level = flush_level_.load(std::memory_order_relaxed); auto flush_level = flush_level_.load(std::memory_order_relaxed);
return (msg.level >= flush_level) && (msg.level != level::off); return (msg.level >= flush_level) && (msg.level != level::off);
} }
SPDLOG_INLINE void logger::err_handler_(const std::string &msg) { SPDLOG_INLINE void logger::err_handler_(const std::string &msg) const {
if (custom_err_handler_) { if (custom_err_handler_) {
custom_err_handler_(msg); custom_err_handler_(msg);
} else { } else {

View File

@@ -363,14 +363,14 @@ protected:
virtual void sink_it_(const details::log_msg &msg); virtual void sink_it_(const details::log_msg &msg);
virtual void flush_(); virtual void flush_();
void dump_backtrace_(); void dump_backtrace_();
bool should_flush_(const details::log_msg &msg); bool should_flush_(const details::log_msg &msg) const;
// handle errors during logging. // handle errors during logging.
// default handler prints the error to stderr at max rate of 1 message/sec. // default handler prints the error to stderr at max rate of 1 message/sec.
void err_handler_(const std::string &msg); void err_handler_(const std::string &msg) const;
}; };
void swap(logger &a, logger &b); void swap(logger &a, logger &b) noexcept;
} // namespace spdlog } // namespace spdlog

View File

@@ -5,7 +5,7 @@
TEST_CASE("stopwatch1", "[stopwatch]") { TEST_CASE("stopwatch1", "[stopwatch]") {
using std::chrono::milliseconds; using std::chrono::milliseconds;
using clock = std::chrono::steady_clock; using clock = std::chrono::steady_clock;
milliseconds wait_ms(200); milliseconds wait_ms(500);
milliseconds tolerance_ms(250); milliseconds tolerance_ms(250);
auto start = clock::now(); auto start = clock::now();
spdlog::stopwatch sw; spdlog::stopwatch sw;
@@ -22,7 +22,7 @@ TEST_CASE("stopwatch2", "[stopwatch]") {
using std::chrono::milliseconds; using std::chrono::milliseconds;
using clock = std::chrono::steady_clock; using clock = std::chrono::steady_clock;
clock::duration wait_duration(milliseconds(200)); clock::duration wait_duration(milliseconds(500));
clock::duration tolerance_duration(milliseconds(250)); clock::duration tolerance_duration(milliseconds(250));
auto test_sink = std::make_shared<test_sink_st>(); auto test_sink = std::make_shared<test_sink_st>();