From ccfcd56dea64aee4af8da2f263bba3a224bbdf4a Mon Sep 17 00:00:00 2001 From: Jan Baraniewski Date: Sat, 27 Apr 2024 13:29:18 +0200 Subject: [PATCH] Add logging --- CMakeLists.txt | 6 ++++- src/client.cpp | 22 ++++++++++----- src/logging.cpp | 45 +++++++++++++++++++++++++++++++ src/logging.h | 17 ++++++++++++ src/server.cpp | 71 +++++++++++++++++++++++++++++++++++++------------ 5 files changed, 136 insertions(+), 25 deletions(-) create mode 100644 src/logging.cpp create mode 100644 src/logging.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a5dd35b..d2525b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Find Boost libraries -find_package(Boost 1.65 REQUIRED COMPONENTS system program_options) +find_package(Boost 1.65 REQUIRED COMPONENTS system program_options log_setup log date_time) include(FetchContent) FetchContent_Declare( @@ -22,6 +22,8 @@ else() message(FATAL_ERROR "GTest::gtest_main not found") endif() +add_library(logging src/logging.cpp) +target_link_libraries(logging Boost::log Boost::log_setup Boost::date_time) # Define the executable for the server add_executable(serial_server src/server.cpp) @@ -29,6 +31,7 @@ target_include_directories(serial_server PRIVATE ${Boost_INCLUDE_DIRS}) target_link_libraries(serial_server PRIVATE Boost::system Boost::program_options + logging pthread ) @@ -39,6 +42,7 @@ target_include_directories(serial_client PRIVATE ${Boost_INCLUDE_DIRS}) target_link_libraries(serial_client PRIVATE Boost::system Boost::program_options + logging pthread ) diff --git a/src/client.cpp b/src/client.cpp index 179ffc0..620e2c7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1,11 +1,14 @@ #include -#include -#include #include #include #include #include +#include +#include + +#include "logging.h" + using namespace boost::asio; using namespace boost::program_options; using ip::tcp; @@ -31,18 +34,21 @@ class SerialClient { // Setup PTY master_fd_ = posix_openpt(O_RDWR | O_NOCTTY); if (master_fd_ == -1 || grantpt(master_fd_) != 0 || unlockpt(master_fd_) != 0) { + BOOST_LOG_TRIVIAL(error) << "Failed to open or configure PTY master"; throw std::runtime_error("Failed to open or configure PTY master"); } char* slave_name = ptsname(master_fd_); if (!slave_name) { + BOOST_LOG_TRIVIAL(error) << "Failed to get PTY slave name"; throw std::runtime_error("Failed to get PTY slave name"); } slave_fd_ = open(slave_name, O_RDWR); if (slave_fd_ == -1) { + BOOST_LOG_TRIVIAL(error) << "Failed to open PTY slave"; throw std::runtime_error("Failed to open PTY slave"); } - cout << "PTY setup completed. Slave device: " << slave_name << endl; + BOOST_LOG_TRIVIAL(info) << "PTY setup completed. Slave device: " << slave_name; } void run() { @@ -55,24 +61,26 @@ class SerialClient { socket_.async_read_some(boost::asio::buffer(buffer_), [this](boost::system::error_code ec, std::size_t length) { if (!ec) { if (write(master_fd_, buffer_.data(), length) < 0) { - cerr << "Write to PTY master failed" << endl; + BOOST_LOG_TRIVIAL(error) << "Write to PTY master failed"; return; } async_write(socket_, boost::asio::buffer(buffer_, length), [this](boost::system::error_code ec, std::size_t) { if (!ec) { do_read_write(); } else { - cerr << "Write back to TCP socket failed: " << ec.message() << endl; + BOOST_LOG_TRIVIAL(error) << "Write back to TCP socket failed: " << ec.message(); } }); } else { - cerr << "Read error: " << ec.message() << endl; + BOOST_LOG_TRIVIAL(error) << "Read error: " << ec.message(); } }); } }; int main(int argc, char* argv[]) { + init_logging(); // Initialize logging at the start of the main function + try { options_description desc{"Options"}; desc.add_options() @@ -95,7 +103,7 @@ int main(int argc, char* argv[]) { SerialClient client(server_ip, server_port); client.run(); } catch (const std::exception& e) { - cerr << "Exception: " << e.what() << "\n"; + BOOST_LOG_TRIVIAL(error) << "Exception: " << e.what(); } return 0; } diff --git a/src/logging.cpp b/src/logging.cpp new file mode 100644 index 0000000..163ab1e --- /dev/null +++ b/src/logging.cpp @@ -0,0 +1,45 @@ +#include "logging.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include // Ensure this is included for date-time support + + +// Define the global logger +src::severity_logger lg; + +void init_logging() { + logging::add_common_attributes(); // Adds common attributes like LineID, TimeStamp + + logging::add_console_log( + std::cout, + keywords::format = ( + expr::stream + << expr::format_date_time("TimeStamp", "%Y-%m-%d %H:%M:%S") + << " [" << logging::trivial::severity << "] " + << expr::smessage + ) + ); + + logging::add_file_log( + keywords::file_name = "serial_application_%N.log", // File name pattern + keywords::rotation_size = 10 * 1024 * 1024, // Rotate files every 10 MiB + keywords::time_based_rotation = logging::sinks::file::rotation_at_time_point(0, 0, 0), + keywords::format = ( + expr::stream + << expr::format_date_time("TimeStamp", "%Y-%m-%d %H:%M:%S") + << " [" << logging::trivial::severity << "] " + << expr::smessage + ) + ); + + logging::core::get()->set_filter( + logging::trivial::severity >= logging::trivial::info + ); +} diff --git a/src/logging.h b/src/logging.h new file mode 100644 index 0000000..c432789 --- /dev/null +++ b/src/logging.h @@ -0,0 +1,17 @@ +#ifndef LOGGING_H +#define LOGGING_H + +#include +#include + +// Namespace aliases +namespace logging = boost::log; +namespace src = boost::log::sources; +namespace expr = boost::log::expressions; +namespace keywords = boost::log::keywords; + +extern src::severity_logger lg; + +void init_logging(); + +#endif // LOGGING_H diff --git a/src/server.cpp b/src/server.cpp index 53c54a8..da73684 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1,12 +1,15 @@ #include -#include -#include -#include #include #include #include #include +#include +#include +#include + +#include "logging.h" + using namespace boost::asio; using namespace boost::program_options; using ip::tcp; @@ -15,6 +18,7 @@ using std::cout; using std::cerr; using std::endl; + class SerialServer { private: io_service io_service_; @@ -25,50 +29,83 @@ class SerialServer { public: SerialServer(const string& dev_name, unsigned int baud_rate, unsigned short port) : serial_(io_service_), socket_(io_service_), acceptor_(io_service_, tcp::endpoint(tcp::v4(), port)) { + BOOST_LOG_SEV(lg, logging::trivial::info) << "Initializing server with device: " << dev_name << ", baud rate: " << baud_rate << ", port: " << port; + // Open the serial port - serial_.open(dev_name); - serial_.set_option(serial_port_base::baud_rate(baud_rate)); + try { + serial_.open(dev_name); + serial_.set_option(serial_port_base::baud_rate(baud_rate)); + BOOST_LOG_SEV(lg, logging::trivial::info) << "Serial port opened and configured."; + } catch (boost::system::system_error& e) { + BOOST_LOG_SEV(lg, logging::trivial::error) << "Failed to open serial port: " << e.what(); + throw; + } // Start accepting connections - acceptor_.async_accept(socket_, [this](boost::system::error_code ec) { - if (!ec) { - cout << "Client connected." << endl; - do_read_write(); - } - }); + start_accept(); } void run() { + BOOST_LOG_SEV(lg, logging::trivial::info) << "Server is running."; io_service_.run(); + BOOST_LOG_SEV(lg, logging::trivial::info) << "Server stopped."; } private: + void start_accept() { + acceptor_.async_accept(socket_, [this](boost::system::error_code ec) { + if (!ec) { + BOOST_LOG_SEV(lg, logging::trivial::info) << "Client connected."; + do_read_write(); + } else { + BOOST_LOG_SEV(lg, logging::trivial::error) << "Error accepting connection: " << ec.message(); + } + }); + } + void do_read_write() { static boost::array buf; - serial_.async_read_some(buffer(buf), [this](boost::system::error_code ec, std::size_t length) { + // Asynchronous read from serial port + serial_.async_read_some(boost::asio::buffer(buf), [this](boost::system::error_code ec, std::size_t length) { if (!ec) { - async_write(socket_, buffer(buf, length), [this](boost::system::error_code ec, std::size_t /*length*/) { + BOOST_LOG_SEV(lg, logging::trivial::info) << "Read " << length << " bytes from the serial port."; + // Write to TCP socket + async_write(socket_, boost::asio::buffer(buf, length), [this](boost::system::error_code ec, std::size_t) { if (!ec) { + BOOST_LOG_SEV(lg, logging::trivial::info) << "Data written to client."; do_read_write(); // Loop back to continue reading/writing + } else { + BOOST_LOG_SEV(lg, logging::trivial::error) << "Error writing to client: " << ec.message(); } }); + } else { + BOOST_LOG_SEV(lg, logging::trivial::error) << "Error reading from serial port: " << ec.message(); } }); - socket_.async_read_some(buffer(buf), [this](boost::system::error_code ec, std::size_t length) { + // Asynchronous read from TCP socket + socket_.async_read_some(boost::asio::buffer(buf), [this](boost::system::error_code ec, std::size_t length) { if (!ec) { - async_write(serial_, buffer(buf, length), [this](boost::system::error_code ec, std::size_t /*length*/) { + BOOST_LOG_SEV(lg, logging::trivial::info) << "Received " << length << " bytes from client."; + // Write to serial port + async_write(serial_, boost::asio::buffer(buf, length), [this](boost::system::error_code ec, std::size_t) { if (!ec) { + BOOST_LOG_SEV(lg, logging::trivial::info) << "Data written to serial port."; do_read_write(); // Loop back to continue reading/writing + } else { + BOOST_LOG_SEV(lg, logging::trivial::error) << "Error writing to serial port: " << ec.message(); } }); + } else { + BOOST_LOG_SEV(lg, logging::trivial::error) << "Error reading from client: " << ec.message(); } }); } }; int main(int argc, char* argv[]) { + init_logging(); try { options_description desc{"Options"}; desc.add_options() @@ -93,7 +130,7 @@ int main(int argc, char* argv[]) { SerialServer server(dev_name, baud_rate, port); server.run(); } catch (const std::exception& e) { - std::cerr << "Exception: " << e.what() << "\n"; + BOOST_LOG_TRIVIAL(error) << "Exception: " << e.what(); } return 0; -} +} \ No newline at end of file