Skip to content

[#464] c api #466

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

Merged
merged 10 commits into from
Oct 16, 2024
3 changes: 2 additions & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ jobs:
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
toolchain: [stable, stable-gnu, 1.75.0]
# toolchain: [stable, stable-gnu, 1.75.0]
toolchain: [stable, 1.75.0]
mode:
- name: "release"
arg: "--release"
Expand Down
19 changes: 11 additions & 8 deletions iceoryx2-bb/log/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,6 @@ use std::{
sync::{atomic::Ordering, Once},
};

use logger::Logger;

#[cfg(feature = "logger_tracing")]
static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();

Expand All @@ -163,10 +161,15 @@ static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();

const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;

static mut LOGGER: Option<&'static dyn logger::Logger> = None;
static mut LOGGER: Option<&'static dyn Log> = None;
static LOG_LEVEL: IoxAtomicU8 = IoxAtomicU8::new(DEFAULT_LOG_LEVEL);
static INIT: Once = Once::new();

pub trait Log: Send + Sync {
/// logs a message
fn log(&self, log_level: LogLevel, origin: Arguments, formatted_message: Arguments);
}

/// Describes the log level.
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
Expand All @@ -190,9 +193,9 @@ pub fn get_log_level() -> u8 {
LOG_LEVEL.load(Ordering::Relaxed)
}

/// Sets the [`Logger`]. Can be only called once at the beginning of the program. If the
/// [`Logger`] is already set it returns false and does not update it.
pub fn set_logger<T: logger::Logger + 'static>(value: &'static T) -> bool {
/// Sets the [`Log`]ger. Can be only called once at the beginning of the program. If the
/// [`Log`]ger is already set it returns false and does not update it.
pub fn set_logger<T: Log + 'static>(value: &'static T) -> bool {
let mut set_logger_success = false;
INIT.call_once(|| {
unsafe { LOGGER = Some(value) };
Expand All @@ -202,8 +205,8 @@ pub fn set_logger<T: logger::Logger + 'static>(value: &'static T) -> bool {
set_logger_success
}

/// Returns a reference to the [`Logger`].
pub fn get_logger() -> &'static dyn Logger {
/// Returns a reference to the [`Log`]ger.
pub fn get_logger() -> &'static dyn Log {
INIT.call_once(|| {
unsafe { LOGGER = Some(&DEFAULT_LOGGER) };
});
Expand Down
2 changes: 1 addition & 1 deletion iceoryx2-bb/log/src/logger/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Logger {
}
}

impl crate::logger::Logger for Logger {
impl crate::Log for Logger {
fn log(
&self,
log_level: LogLevel,
Expand Down
2 changes: 1 addition & 1 deletion iceoryx2-bb/log/src/logger/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl Logger {
}
}

impl crate::logger::Logger for Logger {
impl crate::Log for Logger {
fn log(
&self,
log_level: crate::LogLevel,
Expand Down
2 changes: 1 addition & 1 deletion iceoryx2-bb/log/src/logger/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl Drop for Logger {
}
}

impl crate::Logger for Logger {
impl crate::Log for Logger {
fn log(
&self,
log_level: LogLevel,
Expand Down
2 changes: 1 addition & 1 deletion iceoryx2-bb/log/src/logger/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl Logger {
}
}

impl crate::logger::Logger for Logger {
impl crate::Log for Logger {
fn log(
&self,
log_level: crate::LogLevel,
Expand Down
18 changes: 13 additions & 5 deletions iceoryx2-bb/log/src/logger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,19 @@ pub mod log;
#[cfg(feature = "logger_tracing")]
pub mod tracing;

use std::fmt::Arguments;
/// Sets the [`console::Logger`] as default logger
pub fn use_console_logger() -> bool {
// LazyLock is only available from 1.80 but currently iceoryx2 has the minimum version 1.75.
// But since static values are never dropped in Rust, we can also use Box::leak
let logger = Box::leak(Box::new(console::Logger::new()));
crate::set_logger(&*logger)
}

use crate::LogLevel;
/// Sets the [`file::Logger`] as default logger
pub fn use_file_logger(log_file_name: &str) -> bool {
// we cannot capture non const parameters in a LazyLock and since static values are not
// dropped in Rust we can also use Box::leak
let logger = Box::leak(Box::new(file::Logger::new(log_file_name)));

pub trait Logger: Send + Sync {
/// logs a message
fn log(&self, log_level: LogLevel, origin: Arguments, formatted_message: Arguments);
crate::set_logger(logger)
}
2 changes: 1 addition & 1 deletion iceoryx2-bb/log/src/logger/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl Logger {
}
}

impl crate::logger::Logger for Logger {
impl crate::Log for Logger {
fn log(
&self,
log_level: crate::LogLevel,
Expand Down
33 changes: 27 additions & 6 deletions iceoryx2-ffi/cxx/include/iox2/enum_translation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,22 +646,43 @@ constexpr auto from<int, iox2::ConfigCreationError>(const int value) noexcept ->
template <>
constexpr auto from<iox2::LogLevel, iox2_log_level_e>(iox2::LogLevel value) noexcept -> iox2_log_level_e {
switch (value) {
case iox2::LogLevel::TRACE:
case iox2::LogLevel::Trace:
return iox2_log_level_e_TRACE;
case iox2::LogLevel::DEBUG:
case iox2::LogLevel::Debug:
return iox2_log_level_e_DEBUG;
case iox2::LogLevel::INFO:
case iox2::LogLevel::Info:
return iox2_log_level_e_INFO;
case iox2::LogLevel::WARN:
case iox2::LogLevel::Warn:
return iox2_log_level_e_WARN;
case iox2::LogLevel::ERROR:
case iox2::LogLevel::Error:
return iox2_log_level_e_ERROR;
case iox2::LogLevel::FATAL:
case iox2::LogLevel::Fatal:
return iox2_log_level_e_FATAL;
}
IOX_UNREACHABLE();
}

template <>
constexpr auto from<int, iox2::LogLevel>(int value) noexcept -> iox2::LogLevel {
const auto variant = static_cast<iox2_log_level_e>(value);
switch (value) {
case iox2_log_level_e_TRACE:
return iox2::LogLevel::Trace;
case iox2_log_level_e_DEBUG:
return iox2::LogLevel::Debug;
case iox2_log_level_e_INFO:
return iox2::LogLevel::Info;
case iox2_log_level_e_WARN:
return iox2::LogLevel::Warn;
case iox2_log_level_e_ERROR:
return iox2::LogLevel::Error;
case iox2_log_level_e_FATAL:
return iox2::LogLevel::Fatal;
default:
IOX_UNREACHABLE();
}
}

template <>
constexpr auto from<int, iox2::WaitSetCreateError>(const int value) noexcept -> iox2::WaitSetCreateError {
const auto variant = static_cast<iox2_waitset_create_error_e>(value);
Expand Down
44 changes: 44 additions & 0 deletions iceoryx2-ffi/cxx/include/iox2/log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,50 @@

namespace iox2 {

/// The abstract base class every custom logger has to implement.
///
/// # Example
///
/// @code
/// class ConsoleLogger : public Log {
/// public:
/// void log(LogLevel log_level, const char* origin, const char* message) override {
/// std::cout << "origin = " << origin << ", message = " << message << std::endl;
/// }
/// };
///
/// static ConsoleLogger CUSTOM_LOGGER = ConsoleLogger();
///
/// set_logger(CUSTOM_LOGGER);
/// @endcode
class Log {
public:
Log() = default;
Log(const Log&) = default;
Log(Log&&) = default;
auto operator=(const Log&) -> Log& = default;
auto operator=(Log&&) -> Log& = default;
virtual ~Log() = default;

/// The actual log method. The system provides the log level, the origin of the message and
/// the actual message.
virtual void log(LogLevel log_level, const char* origin, const char* message) = 0;
};

/// Adds a log message to the logger.
void log(LogLevel log_level, const char* origin, const char* message);

/// Sets the console logger as default logger. Returns true if the logger was set, otherwise false.
auto use_console_logger() -> bool;

/// Sets the file logger as default logger. Returns true if the logger was set, otherwise false.
auto use_file_logger(const char* log_file) -> bool;

/// Sets the logger that shall be used. This function can only be called once and must be called
/// before any log message was created.
/// It returns true if the logger was set, otherwise false.
auto set_logger(Log& logger) -> bool;

/// Sets the global log level for the application
auto set_log_level(LogLevel level) -> void;

Expand Down
12 changes: 6 additions & 6 deletions iceoryx2-ffi/cxx/include/iox2/log_level.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
namespace iox2 {

enum class LogLevel : uint8_t {
TRACE = 0,
DEBUG = 1,
INFO = 2,
WARN = 3,
ERROR = 4,
FATAL = 5,
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4,
Fatal = 5,
};

} // namespace iox2
Expand Down
29 changes: 29 additions & 0 deletions iceoryx2-ffi/cxx/src/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,31 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

#include "iox2/log.hpp"
#include "iox/into.hpp"
#include "iox/optional.hpp"
#include "iox2/internal/iceoryx2.hpp"

namespace iox2 {
namespace {
//NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables): it is in an anonymous namespace and therefore only accessible in this compilation unit
iox::optional<Log*> global_logger = iox::nullopt;
} // namespace

void internal_log_callback(iox2_log_level_e log_level, const char* origin, const char* message) {
(*global_logger)->log(iox::into<LogLevel>(static_cast<int>(log_level)), origin, message);
}

auto set_logger(Log& logger) -> bool {
auto success = iox2_set_logger(internal_log_callback);
if (success) {
global_logger.emplace(&logger);
}
return success;
}

void log(LogLevel log_level, const char* origin, const char* message) {
iox2_log(iox::into<iox2_log_level_e>(log_level), origin, message);
}

auto set_log_level(LogLevel level) -> void {
iox2_set_log_level(iox::into<iox2_log_level_e>(level));
Expand All @@ -23,4 +45,11 @@ auto get_log_level() -> LogLevel {
return LogLevel(iox2_get_log_level());
}

auto use_console_logger() -> bool {
return iox2_use_console_logger();
}

auto use_file_logger(const char* log_file) -> bool {
return iox2_use_file_logger(log_file);
}
} // namespace iox2
38 changes: 0 additions & 38 deletions iceoryx2-ffi/cxx/tests/src/log.cpp

This file was deleted.

Loading