Skip to content

Commit

Permalink
Add alternative logging backends
Browse files Browse the repository at this point in the history
This commit allows for btop to log to either syslog(3) or systemd's
journal
  • Loading branch information
imwints committed Sep 18, 2023
1 parent 801bf00 commit cec4904
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 23 deletions.
20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
option(BTOP_STATIC "Link btop statically" OFF)
option(BTOP_LTO "Enable LTO" ON)
option(BTOP_USE_MOLD "Use mold to link btop" OFF)
option(BTOP_SYSLOG "Log with syslog instead of log file" OFF)
option(BTOP_JOURNALD "Directly log to journald instead of log file" OFF)
option(BTOP_PEDANTIC "Enable a bunch of additional warnings" OFF)
option(BTOP_WERROR "Compile with warnings as errors" OFF)

Expand All @@ -52,13 +54,15 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
endif()

include(CheckCXXCompilerFlag)
include(CheckIncludeFileCXX)
include(CheckIPOSupported)

add_executable(btop
src/btop.cpp
src/btop_config.cpp
src/btop_draw.cpp
src/btop_input.cpp
src/btop_log.cpp
src/btop_menu.cpp
src/btop_shared.cpp
src/btop_theme.cpp
Expand Down Expand Up @@ -150,6 +154,22 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(btop PRIVATE Threads::Threads)

# Logging
if(BTOP_JOURNALD)
find_package(Systemd REQUIRED)
target_compile_definitions(btop PRIVATE HAVE_JOURNALD)
target_link_libraries(btop PRIVATE Systemd::Journald)
message(STATUS "Using journald as logging backend")
elseif(BTOP_SYSLOG)
check_include_file_cxx("syslog.h" HAVE_SYSLOG)
if(HAVE_SYSLOG)
target_compile_definitions(btop PRIVATE HAVE_SYSLOG)
message(STATUS "Using syslog as logging backend")
endif()
else()
message(STATUS "Using plain log file")
endif()

if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_link_libraries(btop PRIVATE $<LINK_LIBRARY:FRAMEWORK,CoreFoundation)
target_link_libraries(btop PRIVATE $<LINK_LIBRARY:FRAMEWORK,IOKit)
Expand Down
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,16 @@ else
LTO := $(THREADS)
endif

#? Enable journald direct logging
ifeq ($(ENABLE_JOURNALD),true)
override ADDFLAGS += $(shell echo "int main() {}" | $(CXX) -include "systemd/sd-journal.h" -lsystemd -o /dev/null -x c++ - >/dev/null 2>&1 && echo "-DHAVE_JOURNALD -lsystemd")
else ifeq ($(ENABLE_SYSLOG),true)
override ADDFLAGS += $(strip $(shell echo "int main() {}" | $(CXX) -include "syslog.h" -o /dev/null -x c++ - >/dev/null 2>&1 && echo "-DHAVE_SYSLOG"))
endif

#? The Directories, Source, Includes, Objects and Binary
SRCDIR := src
INCDIRS := include $(wildcard lib/**/include)
INCDIRS := include
BUILDDIR := obj
TARGETDIR := bin
SRCEXT := cpp
Expand All @@ -172,7 +179,7 @@ override GOODFLAGS := $(foreach flag,$(TESTFLAGS),$(strip $(shell echo "int main
override REQFLAGS := -std=c++20
WARNFLAGS := -Wall -Wextra -pedantic
OPTFLAGS := -O2 -ftree-vectorize -flto=$(LTO)
LDCXXFLAGS := -pthread -DFMT_HEADER_ONLY -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -D_FILE_OFFSET_BITS=64 $(GOODFLAGS) $(ADDFLAGS)
LDCXXFLAGS := -pthread -DFMT_HEADER_ONLY -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS _LIBCPP_ENABLE_ASSERTIONS=1 -D_FILE_OFFSET_BITS=64 $(GOODFLAGS) $(ADDFLAGS)
override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS)
override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS)
INC := $(foreach incdir,$(INCDIRS),-isystem $(incdir)) -I$(SRCDIR)
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ Also needs a UTF8 locale and a font that covers:
Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag).
Append `ENABLE_SYSLOG=true` to log to syslog instead of a log file.
Append `ENABLE_JOURNALD=true` to log to journald instead of a log file.
Append `ARCH=<architecture>` to manually set the target architecture.
If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system.
Expand Down Expand Up @@ -447,6 +451,8 @@ Also needs a UTF8 locale and a font that covers:
| `-DBTOP_STATIC=<ON\|OFF>` | Enables static linking (OFF by default) |
| `-DBTOP_LTO=<ON\|OFF>` | Enables link time optimization (ON by default) |
| `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) |
| `-DBTOP_SYSLOG=<ON\|OFF>` | Log to syslog instead of a log file (OFF by default) |
| `-DBTOP_JOURNALD=<ON\|OFF>` | Log to journald instead of a log file (OFF by default) |
| `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) |
| `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) |
| `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) |
Expand Down Expand Up @@ -509,6 +515,8 @@ Also needs a UTF8 locale and a font that covers:
Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag).
Append `ENABLE_SYSLOG=true` to log to syslog instead of a log file.
Append `ARCH=<architecture>` to manually set the target architecture.
If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system.
Expand Down Expand Up @@ -603,6 +611,8 @@ Also needs a UTF8 locale and a font that covers:
Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag).
Append `ENABLE_SYSLOG=true` to log to syslog instead of a log file.
Append `ARCH=<architecture>` to manually set the target architecture.
If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system.
Expand Down Expand Up @@ -719,6 +729,7 @@ Also needs a UTF8 locale and a font that covers:
| `-DBTOP_STATIC=<ON\|OFF>` | Enables static linking (OFF by default) |
| `-DBTOP_LTO=<ON\|OFF>` | Enables link time optimization (ON by default) |
| `-DBTOP_USE_MOLD=<ON\|OFF>` | Use mold to link btop (OFF by default) |
| `-DBTOP_SYSLOG=<ON\|OFF>` | Log to syslog instead of a log file (OFF by default) |
| `-DBTOP_PEDANTIC=<ON\|OFF>` | Compile with additional warnings (OFF by default) |
| `-DBTOP_WERROR=<ON\|OFF>` | Compile with warnings as errors (OFF by default) |
| `-DCMAKE_INSTALL_PREFIX=<path>` | The installation prefix ('/usr/local' by default) |
Expand Down
26 changes: 26 additions & 0 deletions cmake/Modules/FindSystemd.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# SPDX-License-Identifier: Apache-2.0
#
# Find libSystemd, the Kernel Data Access Library
#

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_path(Systemd_INCLUDE_DIR NAMES systemd/sd-journal.h)
find_library(Systemd_LIBRARY NAMES systemd)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Systemd REQUIRED_VARS Systemd_LIBRARY Systemd_INCLUDE_DIR)

if(Systemd_FOUND AND NOT TARGET Systemd::Systemd)
add_library(Systemd::Systemd UNKNOWN IMPORTED)
set_target_properties(Systemd::Systemd PROPERTIES
IMPORTED_LOCATION "${Systemd_LIBRARY}"
)
endif()

if(Systemd_FOUND AND NOT TARGET Systemd::Journald)
add_library(Systemd::Journald ALIAS Systemd::Systemd)
endif()

mark_as_advanced(Systemd_INCLUDE_DIR Systemd_LIBRARY)
endif()

43 changes: 39 additions & 4 deletions src/btop_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@
#include <filesystem>
#include <iostream>
#include <mutex>
#include <source_location>
#include <string>
#include <string_view>

#if defined(HAVE_JOURNALD)
#include <systemd/sd-journal.h>
#elif defined(HAVE_SYSLOG)
#include <syslog.h>
#endif

#include <fmt/core.h>
#include <fmt/ostream.h>

Expand All @@ -18,7 +25,7 @@ namespace fs = std::filesystem;

namespace Logger {
using namespace Tools;
std::mutex log_mtx {};
std::mutex log_mtx{};
bool first = true;
const string tdf = "%Y/%m/%d (%T) | ";

Expand All @@ -44,12 +51,39 @@ namespace Logger {

void set(const string& level) { loglevel = v_index(log_levels, level); }

void log_write(const size_t level, const std::string_view msg) {
if (loglevel < level or logfile.empty()) {
void log(const size_t level, const std::string_view msg, const std::source_location location) {
if (loglevel < level) {
return;
}
std::lock_guard lock {log_mtx};

std::lock_guard lock{log_mtx};
lose_priv neutered{};

#if defined(HAVE_JOURNALD) || defined(HAVE_SYSLOG)
int status = LOG_DEBUG;
switch (level) {
case 1: status = LOG_ERR; break;
case 2: status = LOG_WARNING; break;
case 3: status = LOG_INFO; break;
case 4: status = LOG_DEBUG; break;
}
#endif

#if defined(HAVE_JOURNALD)
sd_journal_print_with_location( // NOLINT(cppcoreguidelines-pro-type-vararg)
status,
("CODE_FILE="s + location.file_name()).data(),
("CODE_LINE="s + std::to_string(location.line())).data(),
location.function_name(),
"%s",
msg.data()
);
#elif defined(HAVE_SYSLOG)
syslog(status, "%s", msg.data()); // NOLINT(cppcoreguidelines-pro-type-vararg)
#else
if (logfile.empty()) {
return;
}
std::error_code ec;
try {
if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) {
Expand Down Expand Up @@ -80,5 +114,6 @@ namespace Logger {
logfile.clear();
throw std::runtime_error(fmt::format("Exception in Logger::log_write() : {}", e.what()));
}
#endif
}
} // namespace Logger
69 changes: 52 additions & 17 deletions src/btop_log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma once

#include <filesystem>
#include <source_location>
#include <string_view>
#include <vector>

Expand All @@ -16,30 +17,64 @@ namespace Logger {
"INFO",
"DEBUG",
};

extern std::filesystem::path logfile;

//* Set log level, valid arguments: "DISABLED", "ERROR", "WARNING", "INFO" and "DEBUG"
void set(const std::string& level);

void log_write(const size_t level, const std::string_view msg);
void log(const size_t level, const std::string_view msg, const std::source_location location);

template<typename... Args>
struct error {
error(
const fmt::format_string<Args...> fmt, Args&&... args,
const std::source_location location = std::source_location::current()
) {
log(1, fmt::format(fmt, std::forward<Args>(args)...), location);
}
};

template<typename... Args>
struct warning {
warning(
const fmt::format_string<Args...> fmt, Args&&... args,
const std::source_location location = std::source_location::current()
) {
log(2, fmt::format(fmt, std::forward<Args>(args)...), location);
}
};

template<typename... Args>
struct info {
info(
const fmt::format_string<Args...> fmt, Args&&... args,
const std::source_location location = std::source_location::current()
) {
log(3, fmt::format(fmt, std::forward<Args>(args)...), location);
}
};

template<typename... Args>
struct debug {
debug(
const fmt::format_string<Args...> fmt, Args&&... args,
const std::source_location location = std::source_location::current()
) {
log(4, fmt::format(fmt, std::forward<Args>(args)...), location);
}
};

template <typename... T>
inline void error(const fmt::format_string<T...> fmt, T&&... args) {
log_write(1, fmt::format(fmt, std::forward<T>(args)...));
}
// Deduction guide to allow default arguement after variadic template
template<typename... Args>
error(const std::string_view, Args&&...) -> error<Args...>;

template <typename... T>
inline void warning(const fmt::format_string<T...> fmt, T&&... args) {
log_write(2, fmt::format(fmt, std::forward<T>(args)...));
}
template<typename... Args>
warning(const std::string_view, Args&&...) -> warning<Args...>;

template <typename... T>
inline void info(const fmt::format_string<T...> fmt, T&&... args) {
log_write(3, fmt::format(fmt, std::forward<T>(args)...));
}
template<typename... Args>
info(const std::string_view, Args&&...) -> info<Args...>;

template <typename... T>
inline void debug(const fmt::format_string<T...> fmt, T&&... args) {
log_write(4, fmt::format(fmt, std::forward<T>(args)...));
}
template<typename... Args>
debug(const std::string_view, Args&&...) -> debug<Args...>;
} // namespace Logger

0 comments on commit cec4904

Please sign in to comment.