Skip to content

Commit

Permalink
Implement slog2 logging capability
Browse files Browse the repository at this point in the history
slog2 is enabled by default, but guarded with #ifdef __QNX__. It can be
controlled with /etc/vsomeip/logging.json, i.e.:

```json
"logging": {
  "slog2": true
}
```

This code allocates 4 pages (16kB) by default, but the caller can provide
an environment variable VSOMEIP_SLOG2_NUM_PAGES to control the allocation

Minimal CMake changes were made to link against the slog2 library on QNX

This commit also modifies the routingmanager example to set the
LogApplication property which is used as the log tag for AOSP logcat
logging.
  • Loading branch information
kheaactua committed May 29, 2024
1 parent 6c0e9db commit 568411d
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 107 deletions.
62 changes: 49 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,27 +64,65 @@ endif()
set(CMAKE_CXX_STANDARD 17)

# OS
add_library(OS_INTERFACE INTERFACE IMPORTED)
target_link_libraries(OS_INTERFACE INTERFACE Threads::Threads)

if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(DL_LIBRARY "dl")

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# This is only relevant for GCC and causes warnings on Clang
set(EXPORTSYMBOLS "-Wl,-export-dynamic -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exportmap.gcc")
set(OS_CXX_FLAGS "${OS_CXX_FLAGS} -pie -Wno-tsan -Wl,-z,relro,-z,now")
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# This is only relevant for GCC and causes warnings on Clang
set(EXPORTSYMBOLS "-Wl,-export-dynamic -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exportmap.gcc")
set(OS_CXX_FLAGS "${OS_CXX_FLAGS} -Wno-tsan -Wl,-z,now")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()

set(NO_DEPRECATED "")
set(OPTIMIZE "")
if(NOT DEFINED _FORTIFY_SOURCE)
set(_FORTIFY_SOURCE 2)
endif()
set(OS_CXX_FLAGS "${OS_CXX_FLAGS} -D_GLIBCXX_USE_NANOSLEEP -pthread -O -Wall -Wextra -Wformat -Wformat-security -Wconversion -fexceptions -fstrict-aliasing -fstack-protector-strong -fasynchronous-unwind-tables -fno-omit-frame-pointer -D_FORTIFY_SOURCE=${_FORTIFY_SOURCE} -Wformat -Wformat-security -Wpedantic -Werror -fPIE")
if(NOT DEFINED _FORTIFY_SOURCE)
set(_FORTIFY_SOURCE 2)
endif()

add_compile_options(
-Wall
-Wextra
-Wformat
-Wformat-security
-Wconversion
-fexceptions
-fstrict-aliasing
-fstack-protector-strong
-fasynchronous-unwind-tables
-fno-omit-frame-pointer
-Wformat
-Wformat-security
-Wpedantic
-Werror
)

# force all use of std::mutex and std::recursive_mutex to use runtime init
# instead of static initialization so mutexes can be hooked to enable PI as needed
add_definitions(-D_GTHREAD_USE_MUTEX_INIT_FUNC -D_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
add_definitions(-D_GTHREAD_USE_MUTEX_INIT_FUNC -D_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC -D_FORTIFY_SOURCE=${_FORTIFY_SOURCE})

add_link_options(-Wl,--wrap=socket,--wrap=accept,--wrap=open)
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")

if(${CMAKE_SYSTEM_NAME} MATCHES "QNX")
set(OS "QNX")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

add_compile_options(
-fexceptions
-fstrict-aliasing
-fstack-protector
-fasynchronous-unwind-tables
-fno-omit-frame-pointer
)
add_link_options(-Wl,-export-dynamic)
add_link_options(-Wl,--wrap=socket,--wrap=accept,--wrap=open)
target_link_libraries(OS_INTERFACE INTERFACE slog2 socket)
endif (${CMAKE_SYSTEM_NAME} MATCHES "QNX")

if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(DL_LIBRARY "")
set(EXPORTSYMBOLS "")
Expand Down Expand Up @@ -308,8 +346,6 @@ set_target_properties (${VSOMEIP_NAME} PROPERTIES VERSION ${VSOMEIP_VERSION} SOV
target_compile_features(${VSOMEIP_NAME} PRIVATE cxx_std_17)
if (MSVC)
set_target_properties(${VSOMEIP_NAME} PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION")
else ()
set_target_properties(${VSOMEIP_NAME} PROPERTIES LINK_FLAGS "-Wl,-wrap,socket -Wl,-wrap,accept -Wl,-wrap,open")
endif ()
target_include_directories(${VSOMEIP_NAME} INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/interface>
Expand All @@ -320,7 +356,7 @@ target_include_directories(${VSOMEIP_NAME} INTERFACE
# them (which shouldn't be required). ${Boost_LIBRARIES} includes absolute
# build host paths as of writing, which also makes this important as it breaks
# the build.
target_link_libraries(${VSOMEIP_NAME} PRIVATE ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${DLT_LIBRARIES} ${SystemD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${VSOMEIP_NAME} PRIVATE ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${DLT_LIBRARIES} ${SystemD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} OS_INTERFACE)

if(NOT WIN32)
target_link_options(${VSOMEIP_NAME} PRIVATE "LINKER:-as-needed")
Expand Down
3 changes: 3 additions & 0 deletions examples/routingmanagerd/routingmanagerd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#endif
#endif

extern char * __progname;

static std::shared_ptr<vsomeip::application> its_application;

#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
Expand Down Expand Up @@ -75,6 +77,7 @@ int routingmanagerd_process(bool _is_quiet) {

std::shared_ptr<vsomeip::runtime> its_runtime
= vsomeip::runtime::get();
its_runtime->set_property("LogApplication", __progname);

if (!its_runtime) {
return -1;
Expand Down
1 change: 1 addition & 0 deletions implementation/configuration/include/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class configuration {
virtual bool has_console_log() const = 0;
virtual bool has_file_log() const = 0;
virtual bool has_dlt_log() const = 0;
virtual bool has_slog2_log() const = 0;
virtual const std::string &get_logfile() const = 0;
virtual logger::level_e get_loglevel() const = 0;

Expand Down
5 changes: 4 additions & 1 deletion implementation/configuration/include/configuration_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class configuration_impl:
VSOMEIP_EXPORT bool has_console_log() const;
VSOMEIP_EXPORT bool has_file_log() const;
VSOMEIP_EXPORT bool has_dlt_log() const;
VSOMEIP_EXPORT bool has_slog2_log() const;
VSOMEIP_EXPORT const std::string & get_logfile() const;
VSOMEIP_EXPORT vsomeip_v3::logger::level_e get_loglevel() const;

Expand Down Expand Up @@ -491,6 +492,7 @@ class configuration_impl:
bool has_console_log_;
bool has_file_log_;
bool has_dlt_log_;
bool has_slog2_log_;
std::string logfile_;
mutable std::mutex mutex_loglevel_;
vsomeip_v3::logger::level_e loglevel_;
Expand Down Expand Up @@ -561,6 +563,7 @@ class configuration_impl:
ET_LOGGING_CONSOLE,
ET_LOGGING_FILE,
ET_LOGGING_DLT,
ET_LOGGING_SLOG2,
ET_LOGGING_LEVEL,
ET_ROUTING,
ET_SERVICE_DISCOVERY_ENABLE,
Expand Down Expand Up @@ -598,7 +601,7 @@ class configuration_impl:
ET_PARTITIONS,
ET_SECURITY_AUDIT_MODE,
ET_SECURITY_REMOTE_ACCESS,
ET_MAX = 45
ET_MAX = 46
};

bool is_configured_[ET_MAX];
Expand Down
19 changes: 19 additions & 0 deletions implementation/configuration/src/configuration_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ configuration_impl::configuration_impl(const std::string &_path)
has_console_log_(true),
has_file_log_(false),
has_dlt_log_(false),
#ifdef __QNX__
has_slog2_log_(true),
#else
has_slog2_log_(false),
#endif
logfile_("/tmp/vsomeip.log"),
loglevel_(vsomeip_v3::logger::level_e::LL_INFO),
is_sd_enabled_(VSOMEIP_SD_DEFAULT_ENABLED),
Expand Down Expand Up @@ -162,6 +167,7 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
has_console_log_ = _other.has_console_log_;
has_file_log_ = _other.has_file_log_;
has_dlt_log_ = _other.has_dlt_log_;
has_slog2_log_ = _other.has_slog2_log_;
logfile_ = _other.logfile_;

loglevel_ = _other.loglevel_;
Expand Down Expand Up @@ -655,6 +661,15 @@ bool configuration_impl::load_logging(
has_dlt_log_ = (its_value == "true");
is_configured_[ET_LOGGING_DLT] = true;
}
} else if (its_key == "slog2") {
if (is_configured_[ET_LOGGING_SLOG2]) {
_warnings.insert("Multiple definitions for logging.slog2."
" Ignoring definition from " + _element.name_);
} else {
std::string its_value(i->second.data());
has_slog2_log_ = (its_value == "true");
is_configured_[ET_LOGGING_SLOG2] = true;
}
} else if (its_key == "level") {
if (is_configured_[ET_LOGGING_LEVEL]) {
_warnings.insert("Multiple definitions for logging.level."
Expand Down Expand Up @@ -2894,6 +2909,10 @@ bool configuration_impl::has_dlt_log() const {
return has_dlt_log_;
}

bool configuration_impl::has_slog2_log() const {
return has_slog2_log_;
}

const std::string & configuration_impl::get_logfile() const {
return logfile_;
}
Expand Down
104 changes: 104 additions & 0 deletions implementation/logger/include/logger_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
#include <memory>
#include <mutex>

#ifdef __QNX__
#include <sys/slog2.h>
#endif

#ifdef ANDROID
#include <android/log.h>
#endif
#ifdef USE_DLT
#ifndef ANDROID
#include <dlt/dlt.h>
Expand All @@ -34,19 +41,116 @@ class logger_impl {
std::shared_ptr<configuration> get_configuration() const;
void set_configuration(const std::shared_ptr<configuration> &_configuration);

#ifdef __QNX__
static slog2_buffer_set_config_t buffer_config;
static slog2_buffer_t buffer_handle[1];

auto slog2_is_initialized() const -> bool {
return slog2_is_initialized_;
}

auto set_slog2_initialized(bool initialized) -> void {
slog2_is_initialized_ = initialized;
}
#endif

#ifdef USE_DLT
void log(level_e _level, const char *_data);

private:
void enable_dlt(const std::string &_application, const std::string &_context);
#endif

static auto constexpr levelAsString(level_e const _level) -> const char *
{
const char* its_level = nullptr;
switch (_level) {
case level_e::LL_FATAL:
its_level = "fatal";
break;
case level_e::LL_ERROR:
its_level = "error";
break;
case level_e::LL_WARNING:
its_level = "warning";
break;
case level_e::LL_INFO:
its_level = "info";
break;
case level_e::LL_DEBUG:
its_level = "debug";
break;
case level_e::LL_VERBOSE:
its_level = "verbose";
break;
default:
its_level = "none";
}

return its_level;
}

#ifdef __QNX__
static auto constexpr levelAsSlog2(level_e const _level) -> std::uint8_t
{
uint8_t severity = 0;
switch (_level) {
case level_e::LL_FATAL:
severity = SLOG2_CRITICAL;
break;
case level_e::LL_ERROR:
severity = SLOG2_ERROR;
break;
case level_e::LL_WARNING:
severity = SLOG2_WARNING;
break;
case level_e::LL_INFO:
severity = SLOG2_INFO;
break;
case level_e::LL_DEBUG:
severity = SLOG2_DEBUG1;
break;
case level_e::LL_VERBOSE:
default:
severity = SLOG2_DEBUG2;
break;
}
return severity;
}
#endif

#ifdef ANDROID
static constexpr auto levelAsAospLevel(level_e _level) -> android_LogPriority {
switch (_level) {
case level_e::LL_FATAL:
return ANDROID_LOG_ERROR;
case level_e::LL_ERROR:
return ANDROID_LOG_ERROR;
case level_e::LL_WARNING:
return ANDROID_LOG_WARN;
case level_e::LL_INFO:
return ANDROID_LOG_INFO;
case level_e::LL_DEBUG:
return ANDROID_LOG_DEBUG;
case level_e::LL_VERBOSE:
return ANDROID_LOG_VERBOSE;
default:
return ANDROID_LOG_INFO;
}
}
#endif // !ANDROID

private:
static std::mutex mutex__;

std::shared_ptr<configuration> configuration_;
mutable std::mutex configuration_mutex_;

#ifdef __QNX__
// Flag whether slog2 was successfully initialized.
bool slog2_is_initialized_ = false;
#endif

#ifdef USE_DLT
#ifndef ANDROID
DLT_DECLARE_CONTEXT(dlt_)
Expand Down
37 changes: 37 additions & 0 deletions implementation/logger/src/logger_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
#include "../include/logger_impl.hpp"
#include "../../configuration/include/configuration.hpp"

#ifdef __QNX__
#include <sys/slog2.h>
extern char * __progname;
#elif __linux__
extern char * __progname;
#endif


namespace vsomeip_v3 {
namespace logger {

Expand All @@ -21,6 +29,35 @@ logger_impl::init(const std::shared_ptr<configuration> &_configuration) {
auto its_logger = logger_impl::get();
its_logger->set_configuration(_configuration);

#ifdef __QNX__
logger_impl::buffer_config.buffer_set_name = __progname;
logger_impl::buffer_config.num_buffers = 1;
logger_impl::buffer_config.verbosity_level = levelAsSlog2(its_logger->configuration_->get_loglevel());

// Use a 16kB log buffer by default
// Override with a size specified by environment variable
long unsigned int num_pages = 4;
auto s = getenv("VSOMEIP_SLOG2_NUM_PAGES");
if (s != nullptr)
{
char * endptr = nullptr;
num_pages = strtoul(s, &endptr, 0);
}
logger_impl::buffer_config.buffer_config[0].buffer_name = "vsomeip";
logger_impl::buffer_config.buffer_config[0].num_pages = static_cast<int>(num_pages);

// Register the buffer set.
if (-1 == slog2_register(&logger_impl::buffer_config, logger_impl::buffer_handle, 0))
{
std::fprintf(stderr, "Error registering slogger2 buffer!\n");
return;
}
else
{
its_logger->set_slog2_initialized(true);
}
#endif

#ifdef USE_DLT
# define VSOMEIP_LOG_DEFAULT_CONTEXT_ID "VSIP"
# define VSOMEIP_LOG_DEFAULT_CONTEXT_NAME "vSomeIP context"
Expand Down
Loading

0 comments on commit 568411d

Please sign in to comment.