Skip to content

Commit

Permalink
Merge pull request #466 from elfenpiff/iox2-464-c-api
Browse files Browse the repository at this point in the history
[#464] c api
  • Loading branch information
elfenpiff authored Oct 16, 2024
2 parents cd27eee + 4f105f3 commit e2c9afe
Show file tree
Hide file tree
Showing 15 changed files with 372 additions and 70 deletions.
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

0 comments on commit e2c9afe

Please sign in to comment.