Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added logging functionality (spdlog) #190

Merged
merged 1 commit into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
steps:
# Checks-out our repository under $GITHUB_WORKSPACE, so our job can access it
- uses: actions/checkout@v2
with:
submodules: recursive

# Sets up useful environment variables
- name: Setup environment variables
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "submodules/spdlog"]
path = submodules/spdlog
url = https://github.com/gabime/spdlog.git
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ endif()
set(PROFILE_GPERFTOOLS "${PROFILE_GPERFTOOLS}"
CACHE BOOL "Build with the GPerfTools profiler library" FORCE)

if(NOT BUILD_BENCHMARK_LOG)
set(BUILD_BENCHMARK_LOG OFF)
endif()
set(BUILD_BENCHMARK_LOG "${BUILD_BENCHMARK_LOG}"
CACHE BOOL "Build binary that benchmarks spdlog speed" FORCE)

# Define a default build type when using a single-mode tool like make/ninja
# We make this default to Release, unless profiling is enabled, in which
Expand Down Expand Up @@ -92,6 +97,11 @@ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE
#--- project specific subdirectories -------------------------------------------
add_subdirectory(package)

#--- include directories -------------------------------------------
target_include_directories(prmon PRIVATE ${PROJECT_SOURCE_DIR}/package/include)
if (BUILD_BENCHMARK_LOG)
target_include_directories(benchmark-log PRIVATE ${PROJECT_SOURCE_DIR}/package/include)
endif(BUILD_BENCHMARK_LOG)
#--- create uninstall target ---------------------------------------------------
include(cmake/prmonUninstall.cmake)

Expand Down
5 changes: 4 additions & 1 deletion package/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ add_executable(prmon src/prmon.cpp
src/wallmon.cpp
src/memmon.cpp
src/nvidiamon.cpp
src/MessageBase.cpp
)

if (BUILD_BENCHMARK_LOG)
add_executable(benchmark-log src/benchmark.cpp)
endif(BUILD_BENCHMARK_LOG)
# Some older versions of the nlohmann_json package don't define
# this target (< 3.0.0 ?). The build on these platforms seems to
# go ok even without this "link library" definition.
Expand Down
1 change: 1 addition & 0 deletions package/include/spdlog
28 changes: 28 additions & 0 deletions package/src/MessageBase.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "MessageBase.h"

#include "spdlog/spdlog.h"

void MessageBase::log_init(const std::string& classname,
const spdlog::level::level_enum& level) {
// Initialise sink list
spdlog::sinks_init_list s_list = {c_sink, f_sink};

// Use the sink list to create multi sink logger
logger =
std::make_shared<spdlog::logger>(classname, s_list.begin(), s_list.end());
log_level = level;
set_log_level(level);
logger->flush_on(level);
spdlog::register_logger(logger);
info(classname + " logger initialised!");
}

void MessageBase::set_log_level(const spdlog::level::level_enum& level) {
log_level = level;
logger->set_level(level);
logger->flush_on(level);
}
void MessageBase::debug(const std::string& message) { logger->debug(message); }
void MessageBase::info(const std::string& message) { logger->info(message); }
void MessageBase::warning(const std::string& message) { logger->warn(message); }
void MessageBase::error(const std::string& message) { logger->error(message); }
31 changes: 31 additions & 0 deletions package/src/MessageBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef PRMON_MESSAGEBASE_H
#define PRMON_MESSAGEBASE_H 1

#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"

// Global sinks

static const std::shared_ptr<spdlog::sinks::stdout_color_sink_st> c_sink{
std::make_shared<spdlog::sinks::stdout_color_sink_st>()};
static const std::shared_ptr<spdlog::sinks::basic_file_sink_st> f_sink{
std::make_shared<spdlog::sinks::basic_file_sink_st>("prmon.log", true)};

class MessageBase {
std::shared_ptr<spdlog::logger> logger;

protected:
spdlog::level::level_enum log_level;
void log_init(const std::string& classname,
const spdlog::level::level_enum& level = spdlog::level::warn);

public:
void set_log_level(const spdlog::level::level_enum& level);
void debug(const std::string& message);
void info(const std::string& message);
void warning(const std::string& message);
void error(const std::string& message);
};

#endif // PRMON_MESSAGEBASE_H
18 changes: 18 additions & 0 deletions package/src/benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"

int main() {
auto sink = std::make_shared<spdlog::sinks::stdout_color_sink_st>();
auto fsink =
std::make_shared<spdlog::sinks::basic_file_sink_mt>("sample.log", true);
spdlog::sinks_init_list sink_list = {sink, fsink};
auto logger = std::make_shared<spdlog::logger>("benchmark", sink_list.begin(),
sink_list.end());
logger->set_level(spdlog::level::warn);
const int maxN = 1e6;
for (int i = 0; i < maxN; ++i) {
logger->warn("Hello, benchmarking currently");
}
return 0;
}
4 changes: 4 additions & 0 deletions package/src/countmon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include "utils.h"

#define MONITOR_NAME "countmon"

// Constructor; uses RAII pattern to be valid
// after construction
countmon::countmon()
Expand All @@ -21,6 +23,8 @@ countmon::countmon()
count_average_stats{},
count_total_stats{},
iterations{0L} {
log_init(MONITOR_NAME);
#undef MONITOR_NAME
count_params.reserve(params.size());
for (const auto& param : params) {
count_params.push_back(param.get_name());
Expand Down
3 changes: 2 additions & 1 deletion package/src/countmon.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
#include <vector>

#include "Imonitor.h"
#include "MessageBase.h"
#include "parameter.h"
#include "registry.h"

class countmon final : public Imonitor {
class countmon final : public Imonitor, public MessageBase {
private:
// Setup the parameters to monitor here
const prmon::parameter_list params = {{"nprocs", "1", "1"},
Expand Down
8 changes: 6 additions & 2 deletions package/src/cpumon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@

#include "utils.h"

#define MONITOR_NAME "cpumon"

// Constructor; uses RAII pattern to be valid
// after construction
cpumon::cpumon() : cpu_params{}, cpu_stats{} {
log_init(MONITOR_NAME);
#undef MONITOR_NAME
cpu_params.reserve(params.size());
for (const auto& param : params) {
cpu_params.push_back(param.get_name());
Expand Down Expand Up @@ -74,8 +78,8 @@ void const cpumon::get_hardware_info(nlohmann::json& hw_json) {

// If the command failed print an error and move on
if (cmd_result.first) {
std::cerr << "Failed to execute 'lscpu' to get CPU information (code "
<< cmd_result.first << ")" << std::endl;
error("Failed to execute 'lscpu' to get CPU information (code " +
std::to_string(cmd_result.first) + ")");
return;
}

Expand Down
4 changes: 2 additions & 2 deletions package/src/cpumon.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
#include <vector>

#include "Imonitor.h"
#include "MessageBase.h"
#include "parameter.h"
#include "registry.h"

class cpumon final : public Imonitor {
class cpumon final : public Imonitor, public MessageBase {
private:
// Setup the parameters to monitor here
const prmon::parameter_list params = {{"utime", "s", ""}, {"stime", "s", ""}};
Expand Down
30 changes: 21 additions & 9 deletions package/src/iomon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include "utils.h"

#define MONITOR_NAME "iomon"

// Define this to be 1 to activate the artificial
// supression of i/o values so that the recovery
// of stats from the max values is checked
Expand All @@ -17,6 +19,8 @@
// Constructor; uses RAII pattern to be valid
// after construction
iomon::iomon() : io_params{}, io_stats{} {
log_init(MONITOR_NAME);
#undef MONITOR_NAME
io_params.reserve(params.size());
for (const auto& param : params) {
io_params.push_back(param.get_name());
Expand Down Expand Up @@ -49,20 +53,28 @@ void iomon::update_stats(const std::vector<pid_t>& pids) {
#endif

for (auto& stat : io_stats) {
#if IOMON_TEST == 1
// This code block randomly suppresses io stat values
// to test recovery from the peak measured values
auto t = time(NULL);
auto m = (t + stat_counter) % 4;
std::cout << stat_counter << " " << t << " " << m << std::endl;
if (m == 0) stat.second = 0;
++stat_counter;
#if IOMON_TEST == 1
if (log_level <= spdlog::level::debug) {
auto t = time(NULL);
auto m = (t + stat_counter) % 4;
std::stringstream strm;
strm << stat_counter << " " << t << " " << m << std::endl;
debug(strm.str());
if (m == 0) stat.second = 0;
++stat_counter;
}
#endif
if (stat.second < io_max_stats[stat.first]) {
// Uh oh - somehow the i/o stats dropped so some i/o was lost
std::clog << "prmon: Warning, detected drop in i/o values for "
<< stat.first << " (" << io_max_stats[stat.first] << " became "
<< stat.second << ")" << std::endl;
if (log_level <= spdlog::level::warn) {
std::stringstream strm;
strm << "prmon: Warning, detected drop in i/o values for " << stat.first
<< " (" << io_max_stats[stat.first] << " became " << stat.second
<< ")" << std::endl;
warning(strm.str());
}
stat.second = io_max_stats[stat.first];
} else {
io_max_stats[stat.first] = stat.second;
Expand Down
4 changes: 2 additions & 2 deletions package/src/iomon.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
#include <vector>

#include "Imonitor.h"
#include "MessageBase.h"
#include "parameter.h"
#include "registry.h"

class iomon final : public Imonitor {
class iomon final : public Imonitor, public MessageBase {
private:
// Setup the parameters to monitor here
const prmon::parameter_list params = {{"rchar", "B", "B/s"},
Expand Down
6 changes: 5 additions & 1 deletion package/src/memmon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include "utils.h"

#define MONITOR_NAME "memmon"

// Constructor; uses RAII pattern to be valid
// after construction
memmon::memmon()
Expand All @@ -23,6 +25,8 @@ memmon::memmon()
mem_average_stats{},
mem_total_stats{},
iterations{0} {
log_init(MONITOR_NAME);
#undef MONITOR_NAME
mem_params.reserve(params.size());
for (const auto& param : params) {
mem_params.push_back(param.get_name());
Expand Down Expand Up @@ -93,7 +97,7 @@ void const memmon::get_hardware_info(nlohmann::json& hw_json) {
// Read some information from /proc/meminfo
std::ifstream memInfoFile{"/proc/meminfo"};
if (!memInfoFile.is_open()) {
std::cerr << "Failed to open /proc/meminfo" << std::endl;
error("Failed to open /proc/meminfo");
return;
}

Expand Down
3 changes: 2 additions & 1 deletion package/src/memmon.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
#include <vector>

#include "Imonitor.h"
#include "MessageBase.h"
#include "parameter.h"
#include "registry.h"

class memmon final : public Imonitor {
class memmon final : public Imonitor, public MessageBase {
private:
// Default paramater list
// const static std::vector<std::string> default_memory_params{"vmem", "pss",
Expand Down
20 changes: 13 additions & 7 deletions package/src/netmon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@

#include <cstring>
#include <memory>
#include <sstream>

#include "utils.h"

#define MONITOR_NAME "netmon"

// Constructor; uses RAII pattern to open all monitored
// network device streams and to take initial values
// to the monitor relative differences
netmon::netmon(std::vector<std::string> netdevs)
: interface_params{}, network_if_streams{} {
log_init(MONITOR_NAME);
#undef MONITOR_NAME
interface_params.reserve(params.size());
for (const auto& param : params) interface_params.push_back(param.get_name());

Expand Down Expand Up @@ -51,9 +56,9 @@ std::vector<std::string> const netmon::get_all_network_devs() {
}
closedir(d);
} else {
std::cerr << "Failed to open " << netdir
<< " to get list of network devices. "
<< "No network data will be available" << std::endl;
error("Failed to open " + std::string(netdir) +
" to get list of network devices. " +
"No network data will be available");
}
return devices;
}
Expand Down Expand Up @@ -94,10 +99,11 @@ void netmon::update_stats(const std::vector<pid_t>& pids) {
if (i.second >= network_stats_last[i.first]) {
network_net_counters[i.first] += i.second - network_stats_last[i.first];
} else {
std::clog
<< "prmon: network statistics error, counter values dropped for "
<< i.first << " (" << i.second << " < " << network_stats_last[i.first]
<< ")" << std::endl;
std::stringstream strm;
strm << "prmon: network statistics error, counter values dropped for "
<< i.first << " (" << i.second << " < "
<< network_stats_last[i.first] << ")" << std::endl;
warning(strm.str());
}
network_stats_last[i.first] = i.second;
}
Expand Down
3 changes: 2 additions & 1 deletion package/src/netmon.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
#include <vector>

#include "Imonitor.h"
#include "MessageBase.h"
#include "parameter.h"
#include "registry.h"

class netmon final : public Imonitor {
class netmon final : public Imonitor, public MessageBase {
private:
// Setup the parameters to monitor here
const prmon::parameter_list params = {{"rx_bytes", "B", "B/s"},
Expand Down
Loading