From 87c105e6563b9f90f0e1e12de8ce5dbc2c58698f Mon Sep 17 00:00:00 2001 From: DownerCase <119755054+DownerCase@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:24:48 +0000 Subject: [PATCH] feat: eCAL Logging (#7) * Add logging * String publisher now behaves like Print(f) * Update example with eCAL logging * Fix enum type handling --- CMakeLists.txt | 1 + ecal/core.go | 26 +++---- ecal/logging/logging.cpp | 19 +++++ ecal/logging/logging.go | 77 +++++++++++++++++++ ecal/logging/logging.h | 22 ++++++ ecal/string/publisher/string_publisher.go | 13 +++- .../string/publisher/string_publisher_test.go | 1 - main.go | 25 +++--- 8 files changed, 158 insertions(+), 26 deletions(-) create mode 100644 ecal/logging/logging.cpp create mode 100644 ecal/logging/logging.go create mode 100644 ecal/logging/logging.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c2db2e5..9ed9c95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ target_link_libraries(ecal_go_publisher PRIVATE eCAL::core) set(subpackages "ecal" "ecal/publisher" + "ecal/logging" ) foreach(package ${subpackages}) diff --git a/ecal/core.go b/ecal/core.go index 58e638b..87717a0 100644 --- a/ecal/core.go +++ b/ecal/core.go @@ -8,15 +8,15 @@ import "unsafe" const ( // eCAL Components - C_None C.uint = 0x000 - C_Publisher = 0x001 - C_Subscriber = 0x002 - C_Service = 0x004 - C_Monitoring = 0x008 - C_Logging = 0x010 - C_TimeSync = 0x020 - C_Default = C_Publisher | C_Subscriber | C_Service | C_Logging | C_TimeSync - C_All = C_Publisher | C_Subscriber | C_Service | C_Monitoring | C_Logging | C_TimeSync + C_None uint = 0x000 + C_Publisher uint = 0x001 + C_Subscriber uint = 0x002 + C_Service uint = 0x004 + C_Monitoring uint = 0x008 + C_Logging uint = 0x010 + C_TimeSync uint = 0x020 + C_Default uint = C_Publisher | C_Subscriber | C_Service | C_Logging | C_TimeSync + C_All uint = C_Publisher | C_Subscriber | C_Service | C_Monitoring | C_Logging | C_TimeSync ) func NewConfig() C.struct_config { @@ -35,17 +35,17 @@ func GetVersion() C.struct_version { return C.GetVersion() } -func Initialize(config C.struct_config, unit_name string, components C.uint) int { +func Initialize(config C.struct_config, unit_name string, components uint) int { unit_c := C.CString(unit_name) defer C.free(unsafe.Pointer(unit_c)) - return int(C.Initialize(&config, unit_c, components)) + return int(C.Initialize(&config, unit_c, C.uint(components))) } func Finalize() int { return int(C.Finalize()) } -func IsInitialized(component C.uint) bool { - return bool(C.IsInitialized(component)) +func IsInitialized(component uint) bool { + return bool(C.IsInitialized(C.uint(component))) } func SetUnitName(unit_name string) bool { unit_c := C.CString(unit_name) diff --git a/ecal/logging/logging.cpp b/ecal/logging/logging.cpp new file mode 100644 index 0000000..4c96bb4 --- /dev/null +++ b/ecal/logging/logging.cpp @@ -0,0 +1,19 @@ +#include "logging.h" + +#include + +void Log(eCAL_Logging_eLogLevel level, const char *const msg, size_t len) { + eCAL::Logging::Log(level, std::string(msg, len)); +} + +void SetFileFilter(eCAL_Logging_Filter filter_bitset) { + eCAL::Logging::SetFileLogFilter(filter_bitset); +} + +void SetUDPFilter(eCAL_Logging_Filter filter_bitset) { + eCAL::Logging::SetUDPLogFilter(filter_bitset); +} + +void SetConsoleFilter(eCAL_Logging_Filter filter_bitset) { + eCAL::Logging::SetConsoleLogFilter(filter_bitset); +} diff --git a/ecal/logging/logging.go b/ecal/logging/logging.go new file mode 100644 index 0000000..4ae0df8 --- /dev/null +++ b/ecal/logging/logging.go @@ -0,0 +1,77 @@ +package logging + +// #include +// #include "logging.h" +// void GoLog(enum eCAL_Logging_eLogLevel level, _GoString_ msg) { +// Log(level, _GoStringPtr(msg), _GoStringLen(msg)); +// } +import "C" +import "fmt" + +type Level uint8 + +const ( + LevelNone Level = C.log_level_none + LevelAll Level = C.log_level_all + LevelInfo Level = C.log_level_info + LevelWarn Level = C.log_level_warning + LevelError Level = C.log_level_error + LevelFatal Level = C.log_level_fatal + LevelDebug Level = C.log_level_debug1 + LevelDebug1 Level = C.log_level_debug1 + LevelDebug2 Level = C.log_level_debug2 + LevelDebug3 Level = C.log_level_debug3 + LevelDebug4 Level = C.log_level_debug4 +) + +func Log(level Level, a ...any) { + C.GoLog(uint32(level), fmt.Sprint(a...)) +} + +func Logf(level Level, format string, a ...any) { + C.GoLog(uint32(level), fmt.Sprintf(format, a...)) +} + +func Error(a ...any) { + Log(LevelError, a...) +} + +func Errorf(format string, a ...any) { + Logf(LevelError, format, a...) +} + +func Warn(a ...any) { + Log(LevelWarn, a...) +} + +func Warnf(format string, a ...any) { + Logf(LevelWarn, format, a...) +} + +func Info(a ...any) { + Log(LevelInfo, a...) +} + +func Infof(format string, a ...any) { + Logf(LevelInfo, format, a...) +} + +func Debug(a ...any) { + Log(LevelDebug, a...) +} + +func Debugf(format string, a ...any) { + Logf(LevelDebug, format, a...) +} + +func SetConsoleFilter(levels Level) { + C.SetConsoleFilter(C.eCAL_Logging_Filter(levels)) +} + +func SetUdpFilter(levels Level) { + C.SetUDPFilter(C.eCAL_Logging_Filter(levels)) +} + +func SetFileFilter(levels Level) { + C.SetFileFilter(C.eCAL_Logging_Filter(levels)) +} diff --git a/ecal/logging/logging.h b/ecal/logging/logging.h new file mode 100644 index 0000000..c411e72 --- /dev/null +++ b/ecal/logging/logging.h @@ -0,0 +1,22 @@ +#ifndef ECAL_GO_LOGGING +#define ECAL_GO_LOGGING + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void Log(enum eCAL_Logging_eLogLevel level, const char *const msg, size_t len); + +void SetFileFilter(eCAL_Logging_Filter filter_bitset); +void SetUDPFilter(eCAL_Logging_Filter filter_bitset); +void SetConsoleFilter(eCAL_Logging_Filter filter_bitset); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecal/string/publisher/string_publisher.go b/ecal/string/publisher/string_publisher.go index 5b36c83..8110b6d 100644 --- a/ecal/string/publisher/string_publisher.go +++ b/ecal/string/publisher/string_publisher.go @@ -1,6 +1,8 @@ package publisher import ( + "fmt" + "github.com/DownerCase/ecal-go/ecal/publisher" ) @@ -13,8 +15,15 @@ func New() (*Publisher, error) { return &Publisher{*pub}, err } -func (p *Publisher) Send(msg string) error { - p.Messages <- []byte(msg) +// Send a message formatted with fmt.Print +func (p *Publisher) Send(msg ...any) error { + p.Messages <- []byte(fmt.Sprint(msg...)) + return nil +} + +// Send a message formatted with fmt.Printf +func (p *Publisher) Sendf(format string, a ...any) error { + p.Messages <- []byte(fmt.Sprintf(format, a...)) return nil } diff --git a/ecal/string/publisher/string_publisher_test.go b/ecal/string/publisher/string_publisher_test.go index cb884af..7776683 100644 --- a/ecal/string/publisher/string_publisher_test.go +++ b/ecal/string/publisher/string_publisher_test.go @@ -25,4 +25,3 @@ func TestProtobufPublisher(t *testing.T) { t.Error("Failed to send message", err) } } - diff --git a/main.go b/main.go index 8a2ae03..5380b50 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,12 @@ package main +import "C" import ( "fmt" - "strconv" "time" "github.com/DownerCase/ecal-go/ecal" + "github.com/DownerCase/ecal-go/ecal/logging" "github.com/DownerCase/ecal-go/ecal/protobuf/publisher" string_publisher "github.com/DownerCase/ecal-go/ecal/string/publisher" "github.com/DownerCase/ecal-go/protos" @@ -23,17 +24,22 @@ func main() { "Go eCAL!", ecal.C_Publisher|ecal.C_Subscriber|ecal.C_Logging, ) - fmt.Println("Init:", initResult) + + // Enable all logging levels in the console + logging.SetConsoleFilter(logging.LevelAll) + + // Log a message + logging.Log(logging.LevelInfo, "Initialized: ", initResult) defer ecal.Finalize() // Shutdown eCAL at the end of the program // Change the unit name - fmt.Println("Changed name:", ecal.SetUnitName("Go demo")) + logging.Debug("Changed name:", ecal.SetUnitName("Go demo")) // Check if the eCAL system is Ok. // Other eCAL programs can send a message to cause ecal.Ok() to return false // Typically used as a condition to terminate daemon-style programs - fmt.Println("eCAL ok?", ecal.Ok()) + logging.Infof("eCAL ok: %t", ecal.Ok()) // Create new protobuf publisher pub, err := publisher.New(&protos.Person{}) @@ -59,23 +65,22 @@ func main() { for idx := range 100 { // Check if program has been requested to stop if !ecal.Ok() { - fmt.Println("eCAL.Ok() is false; shutting down") + logging.Warn("eCAL.Ok() is false; shutting down") return } - fmt.Println("Sending message ", idx) + logging.Info("Sending message ", idx) // Update message to send person.Id = int32(idx) // Serialize and send protobuf message if err := pub.Send(person); err != nil { - fmt.Println("Error: ", err) + logging.Error(err) } - string_msg := "Sent " + strconv.Itoa(idx) + " messages" - if err = string_pub.Send(string_msg); err != nil { - fmt.Println("Error: ", err) + if err = string_pub.Send("Sent ", idx, " messages"); err != nil { + logging.Error(err) } // Delay next iteration