From b9c5d80c3c78851c7289089513798bea5f177036 Mon Sep 17 00:00:00 2001 From: Daniel Edwards Date: Wed, 8 Jul 2026 16:34:43 +0200 Subject: [PATCH 1/2] capi: allow printing calls on stderr Signed-off-by: Daniel Edwards --- CMakeLists.txt | 5 ++ SilKit/source/capi/CMakeLists.txt | 1 + SilKit/source/capi/CapiCan.cpp | 24 ++++++ SilKit/source/capi/CapiImpl.cpp | 33 ++++++++ SilKit/source/capi/CapiImpl.hpp | 122 +++++++++++++-------------- SilKit/source/util/StringHelpers.cpp | 9 +- SilKit/source/util/StringHelpers.hpp | 2 + 7 files changed, 131 insertions(+), 65 deletions(-) create mode 100644 SilKit/source/capi/CapiImpl.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 997fc2fb2..9fd18a199 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ option(SILKIT_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF) option(SILKIT_PACKAGE_SYMBOLS "Add a post-build step to create PDB/Symbol archives" OFF) option(SILKIT_BUILD_DASHBOARD "Build the SIL Kit Dashboard client." ON) option(SILKIT_ENABLE_TRACING_INSTRUMENTATION "Enable tracing instrumentation (_SILKIT_TRACE_CLASS_NAMES)." OFF) +option(SILKIT_ENABLE_API_TRACING_INSTRUMENTATION "Enable API tracing instrumentation." ON) option(SILKIT_LINK_LLD "Use the lld linker for SIL KIT" OFF) option(SILKIT_USE_SYSTEM_LIBRARIES "Use the libraries installed on the system for third party dependencies" OFF) option(SILKIT_BUILD_REPRODUCIBLE "Creates a reproducible build by ommiting timestamps/unique build ids" ON) @@ -70,6 +71,10 @@ if(SILKIT_ENABLE_TRACING_INSTRUMENTATION) add_compile_definitions(SILKIT_ENABLE_TRACING_INSTRUMENTATION=1) endif() +if(SILKIT_ENABLE_API_TRACING_INSTRUMENTATION) + add_compile_definitions(SILKIT_ENABLE_API_TRACING_INSTRUMENTATION=1) +endif() + # Configure build settings like warning and sanitizers include(SilKitBuildSettings) silkit_enable_coverage(${SILKIT_ENABLE_COVERAGE}) diff --git a/SilKit/source/capi/CMakeLists.txt b/SilKit/source/capi/CMakeLists.txt index 59e74758d..f33c07f7b 100644 --- a/SilKit/source/capi/CMakeLists.txt +++ b/SilKit/source/capi/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(O_SilKit_Capi OBJECT CapiEthernet.cpp CapiExceptions.hpp CapiFlexray.cpp + CapiImpl.cpp CapiImpl.hpp CapiLin.cpp CapiLogger.cpp diff --git a/SilKit/source/capi/CapiCan.cpp b/SilKit/source/capi/CapiCan.cpp index 772339b8b..e06abe647 100644 --- a/SilKit/source/capi/CapiCan.cpp +++ b/SilKit/source/capi/CapiCan.cpp @@ -18,6 +18,8 @@ SilKit_ReturnCode SilKitCALL SilKit_CanController_Create(SilKit_CanController** const char* cNetwork) try { + VSILKIT_API_TRACE("{:p} {:?} {:?}", fmt::ptr(participant), cName, cNetwork); + ASSERT_VALID_OUT_PARAMETER(outController); ASSERT_VALID_POINTER_PARAMETER(participant); ASSERT_VALID_POINTER_PARAMETER(cName); @@ -26,6 +28,9 @@ try auto cppParticipant = reinterpret_cast(participant); auto canController = cppParticipant->CreateCanController(cName, cNetwork); *outController = reinterpret_cast(canController); + + VSILKIT_API_TRACE("{:p}", fmt::ptr(*outController)); + return SilKit_ReturnCode_SUCCESS; } CAPI_CATCH_EXCEPTIONS @@ -37,6 +42,8 @@ SilKit_ReturnCode SilKitCALL SilKit_CanController_AddFrameHandler(SilKit_CanCont SilKit_HandlerId* outHandlerId) try { + VSILKIT_API_TRACE("{:p} {:p} {:p} {} {:p}", fmt::ptr(controller), fmt::ptr(context), fmt::ptr(callback), directionMask, fmt::ptr(outHandlerId)); + ASSERT_VALID_POINTER_PARAMETER(controller); ASSERT_VALID_HANDLER_PARAMETER(callback); ASSERT_VALID_OUT_PARAMETER(outHandlerId); @@ -65,6 +72,9 @@ try callback(context, controller, &frameEvent); }, directionMask); + + VSILKIT_API_TRACE("{}", *outHandlerId); + return SilKit_ReturnCode_SUCCESS; } CAPI_CATCH_EXCEPTIONS @@ -74,6 +84,8 @@ SilKit_ReturnCode SilKitCALL SilKit_CanController_RemoveFrameHandler(SilKit_CanC SilKit_HandlerId handlerId) try { + VSILKIT_API_TRACE("{:p} {}", fmt::ptr(controller), handlerId); + ASSERT_VALID_POINTER_PARAMETER(controller); auto canController = reinterpret_cast(controller); @@ -205,6 +217,8 @@ SilKit_ReturnCode SilKitCALL SilKit_CanController_SetBaudRate(SilKit_CanControll uint32_t fdRate, uint32_t xlRate) try { + VSILKIT_API_TRACE("{:p} {} {} {}", fmt::ptr(controller), rate, fdRate, xlRate); + ASSERT_VALID_POINTER_PARAMETER(controller); auto canController = reinterpret_cast(controller); @@ -218,6 +232,8 @@ SilKit_ReturnCode SilKitCALL SilKit_CanController_SendFrame(SilKit_CanController void* transmitContext) try { + VSILKIT_API_TRACE("{:p} {:p} {:p}", fmt::ptr(controller), fmt::ptr(message), fmt::ptr(transmitContext)); + ASSERT_VALID_POINTER_PARAMETER(controller); ASSERT_VALID_POINTER_PARAMETER(message); ASSERT_VALID_STRUCT_HEADER(message); @@ -243,6 +259,8 @@ CAPI_CATCH_EXCEPTIONS SilKit_ReturnCode SilKitCALL SilKit_CanController_Start(SilKit_CanController* controller) try { + VSILKIT_API_TRACE("{:p}", fmt::ptr(controller)); + ASSERT_VALID_POINTER_PARAMETER(controller); auto canController = reinterpret_cast(controller); @@ -255,6 +273,8 @@ CAPI_CATCH_EXCEPTIONS SilKit_ReturnCode SilKitCALL SilKit_CanController_Stop(SilKit_CanController* controller) try { + VSILKIT_API_TRACE("{:p}", fmt::ptr(controller)); + ASSERT_VALID_POINTER_PARAMETER(controller); auto canController = reinterpret_cast(controller); @@ -267,6 +287,8 @@ CAPI_CATCH_EXCEPTIONS SilKit_ReturnCode SilKitCALL SilKit_CanController_Reset(SilKit_CanController* controller) try { + VSILKIT_API_TRACE("{:p}", fmt::ptr(controller)); + ASSERT_VALID_POINTER_PARAMETER(controller); auto canController = reinterpret_cast(controller); @@ -279,6 +301,8 @@ CAPI_CATCH_EXCEPTIONS SilKit_ReturnCode SilKitCALL SilKit_CanController_Sleep(SilKit_CanController* controller) try { + VSILKIT_API_TRACE("{:p}", fmt::ptr(controller)); + ASSERT_VALID_POINTER_PARAMETER(controller); auto canController = reinterpret_cast(controller); diff --git a/SilKit/source/capi/CapiImpl.cpp b/SilKit/source/capi/CapiImpl.cpp new file mode 100644 index 000000000..3e5df7c66 --- /dev/null +++ b/SilKit/source/capi/CapiImpl.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2022 Vector Informatik GmbH +// +// SPDX-License-Identifier: MIT + +#include "util/StringHelpers.hpp" + +#include +#include +#include +#include + +#include "fmt/format.h" +#include "fmt/ostream.h" + +namespace VSilKit { + +void ApiTraceEventImpl(const std::string_view func, const std::string_view data) +{ + thread_local std::string message; + + message.clear(); + message.append(R"({"thread":)"); + fmt::format_to(std::back_inserter(message), "{}", fmt::streamed(std::this_thread::get_id())); + message.append(R"(,"func":")"); + SilKit::Util::AppendEscapedJsonStringTo(func, message); + message.append(R"(","data":")"); + SilKit::Util::AppendEscapedJsonStringTo(data, message); + message.append(R"("})"); + + std::cerr << message << '\n'; +} + +} // namespace VSilKit diff --git a/SilKit/source/capi/CapiImpl.hpp b/SilKit/source/capi/CapiImpl.hpp index 31943e722..eeee1cbcf 100644 --- a/SilKit/source/capi/CapiImpl.hpp +++ b/SilKit/source/capi/CapiImpl.hpp @@ -10,74 +10,68 @@ #include "capi/CapiExceptions.hpp" -#define CAPI_CATCH_EXCEPTIONS \ - catch (const SilKit::CapiBadParameterError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_BADPARAMETER; \ - } \ - catch (const SilKit::StateError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_WRONGSTATE; \ - } \ - catch (const SilKit::TypeConversionError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_TYPECONVERSIONERROR; \ - } \ - catch (const SilKit::ConfigurationError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_CONFIGURATIONERROR; \ - } \ - catch (const SilKit::ProtocolError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_PROTOCOLERROR; \ - } \ - catch (const SilKit::AssertionError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_ASSERTIONERROR; \ - } \ - catch (const SilKit::ExtensionError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_EXTENSIONERROR; \ - } \ - catch (const SilKit::LengthError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_LENGTHERROR; \ - } \ - catch (const SilKit::OutOfRangeError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_OUTOFRANGEERROR; \ - } \ - catch (const SilKit::LogicError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_LOGICERROR; \ - } \ - catch (const SilKit::SilKitError& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_UNSPECIFIEDERROR; \ - } \ - catch (const std::runtime_error& e) \ - { \ - SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_UNSPECIFIEDERROR; \ - } \ - catch (const std::exception& e) \ +#include + +#include "fmt/format.h" + + +namespace VSilKit { + +void ApiTraceEventImpl(std::string_view func, std::string_view data); + +template +void ApiTraceEvent(const std::string_view func, Args&&... args) +{ + thread_local std::string data; + + data.clear(); + fmt::format_to(std::back_inserter(data), std::forward(args)...); + + ApiTraceEventImpl(func, data); +} + +} // namespace VSilKit + +#ifdef SILKIT_ENABLE_API_TRACING_INSTRUMENTATION + +#define VSILKIT_API_TRACE(...) ::VSilKit::ApiTraceEvent((__func__), __VA_ARGS__) + +#else + +#define VSILKIT_API_TRACE(...) \ +do \ +{ \ +} while (false) + +#endif + + +#define CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(ErrorType, ReturnCode) \ + catch (const ErrorType& e) \ { \ SilKit_error_string = e.what(); \ - return SilKit_ReturnCode_UNSPECIFIEDERROR; \ - } \ + VSILKIT_API_TRACE("ERROR {}", #ReturnCode); \ + return ReturnCode; \ + } + + +#define CAPI_CATCH_EXCEPTIONS \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::CapiBadParameterError, SilKit_ReturnCode_BADPARAMETER) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::StateError, SilKit_ReturnCode_WRONGSTATE) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::TypeConversionError, SilKit_ReturnCode_TYPECONVERSIONERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::ConfigurationError, SilKit_ReturnCode_CONFIGURATIONERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::ProtocolError, SilKit_ReturnCode_PROTOCOLERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::AssertionError, SilKit_ReturnCode_ASSERTIONERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::ExtensionError, SilKit_ReturnCode_EXTENSIONERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::LengthError, SilKit_ReturnCode_LENGTHERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::OutOfRangeError, SilKit_ReturnCode_OUTOFRANGEERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::LogicError, SilKit_ReturnCode_LOGICERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(SilKit::SilKitError, SilKit_ReturnCode_UNSPECIFIEDERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(std::runtime_error, SilKit_ReturnCode_UNSPECIFIEDERROR) \ + CAPI_CATCH_EXCEPTIONS_CATCH_BLOCK(std::exception, SilKit_ReturnCode_UNSPECIFIEDERROR) \ catch (...) \ { \ + VSILKIT_API_TRACE("ERROR SilKit_ReturnCode_UNSPECIFIEDERROR"); \ return SilKit_ReturnCode_UNSPECIFIEDERROR; \ } diff --git a/SilKit/source/util/StringHelpers.cpp b/SilKit/source/util/StringHelpers.cpp index 08fe20a41..65d103c9f 100644 --- a/SilKit/source/util/StringHelpers.cpp +++ b/SilKit/source/util/StringHelpers.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "fmt/chrono.h" @@ -18,7 +19,7 @@ namespace Util { namespace { template -void DoEscape(const std::string& string, F f) +void DoEscape(const std::string_view string, F f) { for (const char ch : string) { @@ -62,6 +63,12 @@ void DoEscape(const std::string& string, F f) } // namespace +void AppendEscapedJsonStringTo(const std::string_view input, std::string& output) +{ + DoEscape(input, [&output](const auto ch) { output.push_back(ch); }); +} + + auto EscapeString(const std::string& input) -> std::string { std::size_t count{0}; diff --git a/SilKit/source/util/StringHelpers.hpp b/SilKit/source/util/StringHelpers.hpp index 549df682d..748d93cf7 100644 --- a/SilKit/source/util/StringHelpers.hpp +++ b/SilKit/source/util/StringHelpers.hpp @@ -23,6 +23,8 @@ struct EscapedJsonString friend auto operator<<(std::ostream& ostream, const EscapedJsonString& self) -> std::ostream&; }; +void AppendEscapedJsonStringTo(std::string_view input, std::string& output); + auto EscapeString(const std::string& input) -> std::string; auto CurrentTimestampString() -> std::string; From ce2b777aa14e1a2622a2112cca624a6c9dba7184 Mon Sep 17 00:00:00 2001 From: Daniel Edwards Date: Wed, 8 Jul 2026 16:58:24 +0200 Subject: [PATCH 2/2] fixup! capi: allow printing calls on stderr Signed-off-by: Daniel Edwards --- SilKit/source/capi/CapiImpl.cpp | 6 ++++++ SilKit/source/capi/CapiImpl.hpp | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/SilKit/source/capi/CapiImpl.cpp b/SilKit/source/capi/CapiImpl.cpp index 3e5df7c66..b7e17433d 100644 --- a/SilKit/source/capi/CapiImpl.cpp +++ b/SilKit/source/capi/CapiImpl.cpp @@ -2,6 +2,10 @@ // // SPDX-License-Identifier: MIT +#include "capi/CapiImpl.hpp" + +#ifdef SILKIT_ENABLE_API_TRACING_INSTRUMENTATION + #include "util/StringHelpers.hpp" #include @@ -31,3 +35,5 @@ void ApiTraceEventImpl(const std::string_view func, const std::string_view data) } } // namespace VSilKit + +#endif \ No newline at end of file diff --git a/SilKit/source/capi/CapiImpl.hpp b/SilKit/source/capi/CapiImpl.hpp index eeee1cbcf..80cef8717 100644 --- a/SilKit/source/capi/CapiImpl.hpp +++ b/SilKit/source/capi/CapiImpl.hpp @@ -15,6 +15,8 @@ #include "fmt/format.h" +#ifdef SILKIT_ENABLE_API_TRACING_INSTRUMENTATION + namespace VSilKit { void ApiTraceEventImpl(std::string_view func, std::string_view data); @@ -32,8 +34,6 @@ void ApiTraceEvent(const std::string_view func, Args&&... args) } // namespace VSilKit -#ifdef SILKIT_ENABLE_API_TRACING_INSTRUMENTATION - #define VSILKIT_API_TRACE(...) ::VSilKit::ApiTraceEvent((__func__), __VA_ARGS__) #else