From 4f319ac3dc9205bfa25847de11e405790d7d99f8 Mon Sep 17 00:00:00 2001 From: sametd Date: Mon, 27 May 2024 21:09:15 +0000 Subject: [PATCH 1/6] basic implementation for structured data (only for origin) --- src/eckit/log/SysLog.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/eckit/log/SysLog.h b/src/eckit/log/SysLog.h index 28931e295..c7738b9dc 100644 --- a/src/eckit/log/SysLog.h +++ b/src/eckit/log/SysLog.h @@ -99,6 +99,11 @@ class SysLog { return s; } + /// Optional fields for structured data (RFC 5424 section 6.3) + void software(const std::string& software) { software_ = software; } + void swVersion(const std::string& version) { swVersion_ = version; } + void enterpriseId(const std::string& id) { enterpriseId_ = id; } + private: // methods void print(std::ostream& out) const; @@ -112,6 +117,11 @@ class SysLog { int msgid_; std::string msg_; + + // optional fields for structured data + std::string software_; + std::string swVersion_; + std::string enterpriseId_; }; } // namespace eckit From 3662286b104cee407c4ba4c16eca986f0a14bd03 Mon Sep 17 00:00:00 2001 From: sametd Date: Mon, 27 May 2024 21:32:26 +0000 Subject: [PATCH 2/6] initial structured data implementation for syslog (only origin part) --- src/eckit/log/SysLog.cc | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/eckit/log/SysLog.cc b/src/eckit/log/SysLog.cc index 98c5ffc54..02f9e783b 100644 --- a/src/eckit/log/SysLog.cc +++ b/src/eckit/log/SysLog.cc @@ -18,12 +18,13 @@ #include "eckit/runtime/Main.h" #include "eckit/log/TimeStamp.h" +#include "eckit/net/IPAddress.h" namespace eckit { -SysLog::SysLog(const std::string& msg, int msgid, Facility f, Severity s) : - facility_(f), severity_(s), appName_(Main::instance().name()), msgid_(msgid), msg_(msg) { +SysLog::SysLog(const std::string& msg, int msgid, Facility f, Severity s) + : facility_(f), severity_(s), appName_(Main::instance().name()), msgid_(msgid), msg_(msg) { timestamp_ = TimeStamp("%Y-%m-%dT%H:%M:%SZ"); ///< assumes we are in UTC } @@ -43,11 +44,26 @@ int SysLog::procid() const { return ::getpid(); } + std::string SysLog::structuredData() const { + if (software_.empty() && swVersion_.empty() && enterpriseId_.empty()) { + return std::string(1, nilvalue()); + } + // RFC 5424 section 6.3 (only origin) std::ostringstream s; - - /// @todo Implement the structured message meta-description as described in RFC5424 secion 6.3 - s << nilvalue(); + std::string ip = net::IPAddress::myIPAddress().asString(); + + s << "[origin ip=\"" << ip << "\""; + if (!enterpriseId_.empty()) { + s << " enterpriseId=\"" << enterpriseId_ << "\""; + } + if (!software_.empty()) { + s << " software=\"" << software_ << "\""; + if (!swVersion_.empty()) { + s << " swVersion=\"" << swVersion_ << "\""; + } + } + s << "]"; return s.str(); } From 7e4ee5dfd7ec7a6f2a610fe4f966f71da7e82b45 Mon Sep 17 00:00:00 2001 From: sametd Date: Mon, 27 May 2024 21:33:19 +0000 Subject: [PATCH 3/6] clang-format --- src/eckit/log/SysLog.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eckit/log/SysLog.cc b/src/eckit/log/SysLog.cc index 02f9e783b..ab7371720 100644 --- a/src/eckit/log/SysLog.cc +++ b/src/eckit/log/SysLog.cc @@ -23,8 +23,8 @@ namespace eckit { -SysLog::SysLog(const std::string& msg, int msgid, Facility f, Severity s) - : facility_(f), severity_(s), appName_(Main::instance().name()), msgid_(msgid), msg_(msg) { +SysLog::SysLog(const std::string& msg, int msgid, Facility f, Severity s) : + facility_(f), severity_(s), appName_(Main::instance().name()), msgid_(msgid), msg_(msg) { timestamp_ = TimeStamp("%Y-%m-%dT%H:%M:%SZ"); ///< assumes we are in UTC } From 8b616794f5f23fced3a66002fb454d21af504408 Mon Sep 17 00:00:00 2001 From: sametd Date: Mon, 27 May 2024 21:34:18 +0000 Subject: [PATCH 4/6] spelling correction --- src/eckit/log/SysLog.cc | 2 +- src/eckit/log/SysLog.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eckit/log/SysLog.cc b/src/eckit/log/SysLog.cc index ab7371720..e10304ad3 100644 --- a/src/eckit/log/SysLog.cc +++ b/src/eckit/log/SysLog.cc @@ -75,7 +75,7 @@ SysLog::operator std::string() const { static char sep = ' '; os // RFC 5424 section 6.2 (Header) - << "<" << priotity() << ">" << version() << sep << timestamp() << sep << fqdn() << sep << appName() << sep + << "<" << priority() << ">" << version() << sep << timestamp() << sep << fqdn() << sep << appName() << sep << procid() << sep << msgid() << sep // RFC 5424 section 6.3 diff --git a/src/eckit/log/SysLog.h b/src/eckit/log/SysLog.h index c7738b9dc..d88c31f53 100644 --- a/src/eckit/log/SysLog.h +++ b/src/eckit/log/SysLog.h @@ -72,7 +72,7 @@ class SysLog { SysLog(const std::string& msg, int msgid = 0, Facility f = SysLog::User, Severity s = SysLog::Info); - unsigned priotity() const { return facility_ * 8 + severity_; } + unsigned priority() const { return facility_ * 8 + severity_; } unsigned version() const { return 1; } From 65981d628ac8d532d04d2e197a2c16531834521e Mon Sep 17 00:00:00 2001 From: sametd Date: Tue, 28 May 2024 13:35:59 +0000 Subject: [PATCH 5/6] added tests for syslog class --- tests/log/test_syslog.cc | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests/log/test_syslog.cc diff --git a/tests/log/test_syslog.cc b/tests/log/test_syslog.cc new file mode 100644 index 000000000..ab602a23a --- /dev/null +++ b/tests/log/test_syslog.cc @@ -0,0 +1,84 @@ +/* + * (C) Copyright 1996- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * In applying this licence, ECMWF does not waive the privileges and immunities + * granted to it by virtue of its status as an intergovernmental organisation nor + * does it submit to any jurisdiction. + */ + +#include + +#include "eckit/log/SysLog.h" +#include "eckit/testing/Test.h" + +using namespace std; +using namespace eckit; +using namespace eckit::testing; + +namespace eckit::test { + +//---------------------------------------------------------------------------------------------------------------------- + +CASE("test_priority") { + SysLog log("Test message", 0, SysLog::Local7, SysLog::Info); + std::string logString = static_cast(log); + std::string expectedPriority = "<" + std::to_string(log.priority()) + ">"; + EXPECT(logString.find(expectedPriority) != std::string::npos); +} + +//---------------------------------------------------------------------------------------------------------------------- + +CASE("test_timezone") { + SysLog log("Test message", 0, SysLog::Local7, SysLog::Info); + std::string logString = static_cast(log); + // Check if 'Z' UTC indicator is present + EXPECT(logString.find("Z") != std::string::npos); + // Check if 'T' separator is present + EXPECT(logString.find("T") != std::string::npos); +} + +//---------------------------------------------------------------------------------------------------------------------- + +CASE("test_appname") { + SysLog log("Test message", 0, SysLog::Local7, SysLog::Info); + EXPECT(log.appName() == Main::instance().name()); + + // Change the appName and check if it persists + log.appName("test_app"); + std::string logString = static_cast(log); + EXPECT(logString.find("test_app") != std::string::npos); + + // Create a new SysLog instance and check if it retains the original appName + SysLog newLog("New message", 2, SysLog::Local7, SysLog::Info); + EXPECT(newLog.appName() == Main::instance().name()); +} + +//---------------------------------------------------------------------------------------------------------------------- + +CASE("test_without_structured_data") { + SysLog log("Test message", 0, SysLog::Local7, SysLog::Info); + std::string logString = static_cast(log); + // Check if structured data is not present + EXPECT(logString.find("[origin") == std::string::npos); +} + +//---------------------------------------------------------------------------------------------------------------------- +CASE("test_with_structured_data") { + SysLog log("Test message", 0, SysLog::Local7, SysLog::Info); + log.software("log_test"); + log.swVersion("1.0.0"); + log.enterpriseId("7464"); + std::string logString = static_cast(log); + EXPECT(logString.find("enterpriseId=\"7464\"") != std::string::npos); + EXPECT(logString.find("software=\"log_test\"") != std::string::npos); + EXPECT(logString.find("swVersion=\"1.0.0\"") != std::string::npos); +} +//---------------------------------------------------------------------------------------------------------------------- + +} // namespace eckit::test + +int main(int argc, char** argv) { + return run_tests(argc, argv); +} From 52ba68964e71f4598e90af50d0ba545d2f4ad77a Mon Sep 17 00:00:00 2001 From: sametd Date: Tue, 28 May 2024 13:36:13 +0000 Subject: [PATCH 6/6] added syslog test --- tests/log/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/log/CMakeLists.txt b/tests/log/CMakeLists.txt index fbd95d313..58f9346bc 100644 --- a/tests/log/CMakeLists.txt +++ b/tests/log/CMakeLists.txt @@ -27,3 +27,7 @@ ecbuild_add_test( TARGET eckit_test_log_user_channels ENABLED OFF SOURCES test_log_user_channels.cc LIBS eckit ) + +ecbuild_add_test( TARGET eckit_test_syslog + SOURCES test_syslog.cc + LIBS eckit ) \ No newline at end of file