-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement logging for ebpfdiscoverysrv
- Loading branch information
Showing
19 changed files
with
712 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,192 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
#include "ebpfdiscovery/Discovery.h" | ||
#include "ebpfdiscovery/DiscoveryBpf.h" | ||
#include "ebpfdiscovery/DiscoveryBpfLoader.h" | ||
#include "logging/Global.h" | ||
|
||
#include <bpf/libbpf.h> | ||
#include <boost/program_options.hpp> | ||
#include <fmt/format.h> | ||
|
||
#include <condition_variable> | ||
#include <iostream> | ||
#include <memory> | ||
#include <signal.h> | ||
#include <sstream> | ||
#include <unistd.h> | ||
|
||
static ebpfdiscovery::Discovery discoveryInstance; | ||
enum class ProgramStatus { | ||
Running, | ||
UnixShutdownSignalReceived, | ||
} programStatus; | ||
|
||
std::atomic<bool> isShuttingDown; | ||
std::condition_variable programStatusCV; | ||
std::mutex programStatusMutex; | ||
|
||
static void handleUnixExitSignal(int signo) { | ||
if (isShuttingDown) { | ||
return; | ||
} | ||
isShuttingDown = true; | ||
/* | ||
* CLI options | ||
*/ | ||
|
||
using logging::LogLevel; | ||
|
||
static boost::program_options::options_description getProgramOptions() { | ||
namespace po = boost::program_options; | ||
po::options_description desc{"Options"}; | ||
|
||
// clang-format off | ||
desc.add_options() | ||
("log-level", po::value<logging::LogLevel>()->default_value(logging::LogLevel::Err, "error"), "Set log level {trace,debug,info,warning,error,critical,off}") | ||
("help,h", "Display available options") | ||
("log-dir", po::value<std::string>()->default_value(""), "Log files directory") | ||
("log-no-stdout", po::value<bool>()->default_value(false), "Disable logging to stdout") | ||
("version", "Display program version") | ||
; | ||
|
||
// clang-format on | ||
return desc; | ||
} | ||
|
||
static std::string getProgramVersion() { | ||
std::ostringstream ss; | ||
ss << EBPFDISCOVERY_VERSION_MAJOR << "." << EBPFDISCOVERY_VERSION_MINOR << "." << EBPFDISCOVERY_VERSION_PATCH; | ||
return ss.str(); | ||
} | ||
|
||
/* | ||
* Logging setup | ||
*/ | ||
|
||
discoveryInstance.stopRun(); | ||
static void setupLogging(logging::LogLevel logLevel, bool enableStdout, std::string_view logDir) { | ||
logging::Global::getInstance().setup("eBPF-Discovery", enableStdout, logDir); | ||
logging::Global::getInstance().setLevel(logLevel); | ||
LOG_TRACE("Logging has been set up. (logDir: {})", logDir); | ||
} | ||
|
||
void setupUnixSignalHandlers() { | ||
struct sigaction action {}; | ||
action.sa_handler = handleUnixExitSignal; | ||
action.sa_flags = 0; | ||
sigaction(SIGINT, &action, nullptr); | ||
sigaction(SIGTERM, &action, nullptr); | ||
sigaction(SIGPIPE, &action, nullptr); | ||
/* | ||
* Unix signals setup | ||
*/ | ||
|
||
static sigset_t getSigset() { | ||
sigset_t sigset; | ||
sigfillset(&sigset); | ||
return sigset; | ||
} | ||
|
||
static void runUnixSignalHandlerLoop() { | ||
while (true) { | ||
sigset_t sigset{getSigset()}; | ||
LOG_TRACE("Waiting for unix signals."); | ||
int signo{sigwaitinfo(&sigset, nullptr)}; | ||
if (signo == -1) { | ||
LOG_CRITICAL("Failed to wait for unix signals: {}", std::strerror(errno)); | ||
std::abort(); | ||
} | ||
LOG_DEBUG("Received unix signal. (signo: {})", signo); | ||
if (signo == SIGINT || signo == SIGPIPE || signo == SIGTERM) { | ||
std::lock_guard<std::mutex> lock(programStatusMutex); | ||
programStatus = ProgramStatus::UnixShutdownSignalReceived; | ||
LOG_TRACE("Unix signal handler is notifying for shutdown."); | ||
programStatusCV.notify_all(); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
/* | ||
* Libbpf setup | ||
*/ | ||
|
||
static int libbpfPrintFn(enum libbpf_print_level level, const char* format, va_list args) { | ||
#ifdef DEBUG | ||
return vfprintf(stderr, format, args); | ||
#else | ||
switch (level) { | ||
case LIBBPF_WARN: | ||
logging::Global::getInstance().vlogf(logging::LogLevel::Warn, format, args); | ||
return 0; | ||
case LIBBPF_INFO: | ||
logging::Global::getInstance().vlogf(logging::LogLevel::Info, format, args); | ||
return 0; | ||
case LIBBPF_DEBUG: | ||
logging::Global::getInstance().vlogf(logging::LogLevel::Debug, format, args); | ||
return 0; | ||
} | ||
return 0; | ||
#endif | ||
} | ||
|
||
void setupLibbpf() { | ||
static void setupLibbpf() { | ||
libbpf_set_print(libbpfPrintFn); | ||
} | ||
|
||
int main(int argc, char** argv) { | ||
setupLibbpf(); | ||
setupUnixSignalHandlers(); | ||
namespace po = boost::program_options; | ||
po::options_description desc{getProgramOptions()}; | ||
po::variables_map vm; | ||
|
||
try { | ||
po::store(po::parse_command_line(argc, argv, desc), vm); | ||
po::notify(vm); | ||
} catch (const po::error& e) { | ||
std::cout << e.what() << '\n'; | ||
return EXIT_FAILURE; | ||
} | ||
|
||
if (vm.count("help")) { | ||
std::cout << desc; | ||
return EXIT_SUCCESS; | ||
} | ||
|
||
if (vm.count("version")) { | ||
std::cout << "eBPF-Discovery " << getProgramVersion() << '\n'; | ||
return EXIT_SUCCESS; | ||
} | ||
|
||
logging::LogLevel logLevel{vm["log-level"].as<logging::LogLevel>()}; | ||
bool isStdoutLogDisabled{vm["log-no-stdout"].as<bool>()}; | ||
std::string logDir{vm["log-dir"].as<std::string>()}; | ||
|
||
try { | ||
discoveryInstance.load(); | ||
setupLogging(logLevel, !isStdoutLogDisabled, logDir); | ||
} catch (const std::runtime_error& e) { | ||
std::cerr << "Couldn't load BPF program: " << e.what() << std::endl; | ||
std::cerr << "Couldn't setup logging: " << e.what() << '\n'; | ||
return EXIT_FAILURE; | ||
} | ||
|
||
if (discoveryInstance.run() != 0) { | ||
LOG_DEBUG("Starting the program."); | ||
|
||
{ | ||
LOG_TRACE("Setting up unix signals handling."); | ||
sigset_t sigset = getSigset(); | ||
if (sigprocmask(SIG_BLOCK, &sigset, nullptr) == -1) { | ||
LOG_CRITICAL("Failed to block unix signals: {}", std::strerror(errno)); | ||
return EXIT_FAILURE; | ||
} | ||
} | ||
|
||
setupLibbpf(); | ||
ebpfdiscovery::DiscoveryBpfLoader loader; | ||
try { | ||
loader.load(); | ||
} catch (const std::runtime_error& e) { | ||
LOG_CRITICAL("Couldn't load BPF program. ({})", e.what()); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
ebpfdiscovery::Discovery instance(loader.get()); | ||
try { | ||
instance.start(); | ||
} catch (const std::runtime_error& e) { | ||
LOG_CRITICAL("Couldn't start Discovery: {}", e.what()); | ||
} | ||
|
||
std::thread unixSignalThread(runUnixSignalHandlerLoop); | ||
{ | ||
std::unique_lock<std::mutex> programStatusLock(programStatusMutex); | ||
programStatusCV.wait(programStatusLock, []() { return programStatus != ProgramStatus::Running; }); | ||
} | ||
|
||
LOG_DEBUG("Exiting the program."); | ||
if (unixSignalThread.joinable()) { | ||
unixSignalThread.join(); | ||
} | ||
instance.stop(); | ||
instance.wait(); | ||
|
||
return EXIT_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
#pragma once | ||
|
||
#include "discovery.skel.h" | ||
|
||
namespace ebpfdiscovery { | ||
|
||
class DiscoveryBpf { | ||
public: | ||
DiscoveryBpf(discovery_bpf* skel); | ||
DiscoveryBpf(const DiscoveryBpf&) = default; | ||
DiscoveryBpf& operator=(const DiscoveryBpf&) = default; | ||
DiscoveryBpf(DiscoveryBpf&&) = default; | ||
DiscoveryBpf& operator=(DiscoveryBpf&&) = default; | ||
~DiscoveryBpf() = default; | ||
|
||
discovery_bpf* skel; | ||
}; | ||
|
||
} // namespace ebpfdiscovery |
Oops, something went wrong.