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
This commit is contained in:
Gabi Melman
2025-05-12 15:36:07 +03:00
committed by GitHub
parent 677a2d93e6
commit 37ff466454
8 changed files with 102 additions and 57 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

@@ -33,6 +33,7 @@ void mdc_example();
#include "spdlog/fmt/ostr.h" // support for user defined types
int main(int, char *[]) {
try {
// Log levels can be loaded from argv/env using "SPDLOG_LEVEL"
load_levels_example();
@@ -58,8 +59,8 @@ int main(int, char *[]) {
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:
// 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..
@@ -67,7 +68,6 @@ int main(int, char *[]) {
// e.g. if some error happened:
spdlog::dump_backtrace(); // log them now!
try {
stdout_logger_example();
basic_example();
rotating_example();
@@ -371,15 +371,13 @@ void replace_default_logger_example() {
// store the old logger so we don't break other examples.
auto old_logger = spdlog::default_logger();
auto new_logger =
spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true);
spdlog::set_default_logger(new_logger);
auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/somelog.txt", true);
spdlog::set_default_logger(std::move(new_logger));
spdlog::set_level(spdlog::level::info);
spdlog::debug("This message should not be displayed!");
spdlog::set_level(spdlog::level::trace);
spdlog::debug("This message should be displayed..");
spdlog::set_default_logger(old_logger);
spdlog::set_default_logger(std::move(old_logger));
}
// 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/registry.h>
#include <spdlog/spdlog.h>
#include <algorithm>
#include <sstream>
@@ -36,7 +35,7 @@ inline std::string &trim_(std::string &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
// "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 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"),...}
inline std::unordered_map<std::string, std::string> extract_key_vals_(const std::string &str) {
std::string token;
@@ -82,14 +81,14 @@ SPDLOG_INLINE void load_levels(const std::string &input) {
bool global_level_found = false;
for (auto &name_level : key_vals) {
auto &logger_name = name_level.first;
auto level_name = to_lower_(name_level.second);
const auto &logger_name = name_level.first;
const auto &level_name = to_lower_(name_level.second);
auto level = level::from_str(level_name);
// ignore unrecognized level names
if (level == level::off && level_name != "off") {
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 = level;

View File

@@ -11,10 +11,8 @@
#include <spdlog/details/os.h>
#include <cerrno>
#include <chrono>
#include <cstdio>
#include <string>
#include <thread>
#include <tuple>
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(); }
// 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) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
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,
size_t threads_n,
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)
: thread_pool(q_max_items, threads_n, [] {}, [] {}) {}
@@ -94,8 +94,7 @@ void SPDLOG_INLINE thread_pool::worker_loop_() {
}
// process next message in the queue
// return true if this thread should still be active (while no terminate msg
// was received)
// returns true if this thread should still be active (while no terminated msg was received)
bool SPDLOG_INLINE thread_pool::process_next_msg_() {
async_msg 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_);
}
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); }
@@ -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);
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_) {
custom_err_handler_(msg);
} else {

View File

@@ -363,14 +363,14 @@ protected:
virtual void sink_it_(const details::log_msg &msg);
virtual void flush_();
void dump_backtrace_();
bool should_flush_(const details::log_msg &msg);
bool should_flush_(const details::log_msg &msg) const;
// handle errors during logging.
// 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