diff --git a/CMakeLists.txt b/CMakeLists.txt index c6aa0a08..2c8b599c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -169,6 +169,17 @@ if(DBUS_LINUX) endif() endif() +if(DBUS_LINUX) + option(ENABLE_VERBOSE_LTTNG "Enable redirecting verbose messages to lttng tracing systen" OFF) + if(ENABLE_VERBOSE_LTTNG) + pkg_check_modules(LTTNG lttng-ust) + if(LTTNG_FOUND) + set(HAVE_LTTNG 1) + message(STATUS "lttng found using ${LTTNG_LIBRARIES}") + endif() + endif() +endif() + if(NOT ENABLE_TRADITIONAL_ACTIVATION AND NOT (DBUS_LINUX AND DBUS_BUS_ENABLE_SYSTEMD)) message(WARNING "\ Traditional activation and systemd activation are both disabled, so service \ diff --git a/README-lttng.md b/README-lttng.md new file mode 100644 index 00000000..24610601 --- /dev/null +++ b/README-lttng.md @@ -0,0 +1,82 @@ +# LTTNG support for dbus + +The lttng support for DBus allows verbose messages issued on the console +on unix-like operating systems, when verbose mode is enabled at build time +and the environment variable DBUS_VERBOSE=1 is set, to be redirected to the +tracing system provided by lttng. + +This requires installing the development package for lttng-ust and building +dbus with it by adding -DENABLE_VERBOSE_LTTNG=1 to the cmake configure line. + +For more details on lttng, see https://lttng.org/. + +## lttng example session +```sh +# create session +$ lttng create dbus +Session dbus created. +Traces will be output to /home/user/lttng-traces/dbus-20230116-094713 + +# activate session (only required when using multiple sessions) +$ lttng set-session dbus + +# enable events +$ lttng enable-event --userspace 'dbus:*' +UST event dbus:* created in channel channel0 + +# show session status (opptional) +$ lttng status +Tracing session dbus: [active] + Trace output: /home/user/lttng-traces/dbus-20230116-094713 + +=== Domain: User space === + +Buffering scheme: per-user + +Tracked process attributes + Virtual process IDs: all + Virtual user IDs: all + Virtual group IDs: all + +Channels: +------------- +- channel0: [enabled] + + Attributes: + Event-loss mode: discard + Sub-buffer size: 524288 bytes + Sub-buffer count: 4 + Switch timer: inactive + Read timer: inactive + Monitor timer: 1000000 us + Blocking timeout: 0 us + Trace file count: 1 per stream + Trace file size: unlimited + Output mode: mmap + + Statistics: + Discarded events: 0 + + Event rules: + dbus:* (type: tracepoint) [enabled] + +# start tracing +$ lttng start + +# run dbus app +$ ../dbus-cmake-build/bin/test-lttng + +# stop tracing +$ lttng stop +Waiting for data availability. +Tracing stopped for session dbus + +# show tracing results +$ lttng view +Trace directory: /home/user/lttng-traces/dbus-20230116-094713 + +[10:34:22.255406515] (+?.?????????) host dbus:lttng_test: { cpu_id = 8 }, { my_integer_field = 1, my_string_field = "../dbus-cmake-build/bin/test-lttng" } + +# destroy session +$ lttng destroy dbus +``` diff --git a/cmake/modules/Macros.cmake b/cmake/modules/Macros.cmake index 14d06c24..ad51ffef 100644 --- a/cmake/modules/Macros.cmake +++ b/cmake/modules/Macros.cmake @@ -392,3 +392,24 @@ macro(add_systemd_service file) install_symlink(../${_name} ${_linkdir}/${_name}) endforeach() endmacro() + +# +# generate source files from lttng tracepoint template and add to target +# +# _target: target to add the generated sources +# _tpfile: file with lttng tracepoint template +# +macro(add_lttng_tracepoint _target _tpfile) + string(REPLACE ".tp" "-tp.h" h_file ${_tpfile}) + string(REPLACE ".tp" "-tp.c" c_file ${_tpfile}) + get_filename_component(h_file ${h_file} NAME) + get_filename_component(c_file ${c_file} NAME) + add_custom_command( + OUTPUT ${c_file} + COMMAND lttng-gen-tp ${CMAKE_CURRENT_SOURCE_DIR}/${_tpfile} -o ${c_file} -o ${h_file} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${_tpfile} + ) + set_source_files_properties(${h_file} ${c_file} PROPERTIES GENERATED 1) + target_sources(${_target} PRIVATE ${h_file} ${c_file} ${_tpfile}) +endmacro() diff --git a/dbus/CMakeLists.txt b/dbus/CMakeLists.txt index 04f9ca22..2cac6274 100644 --- a/dbus/CMakeLists.txt +++ b/dbus/CMakeLists.txt @@ -286,17 +286,23 @@ else(WIN32) if(DEFINED DBUS_LIBRARY_REVISION) set_target_properties(dbus-1 PROPERTIES VERSION ${DBUS_LIBRARY_MAJOR}.${DBUS_LIBRARY_AGE}.${DBUS_LIBRARY_REVISION} SOVERSION ${DBUS_LIBRARY_MAJOR}) endif() - target_link_libraries(dbus-1 ${CMAKE_THREAD_LIBS_INIT} ${SYSTEMD_LIBRARIES}) + target_link_libraries(dbus-1 PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${SYSTEMD_LIBRARIES}) if(LIBRT) - target_link_libraries(dbus-1 ${LIBRT}) + target_link_libraries(dbus-1 PRIVATE ${LIBRT}) endif() if(LIBSOCKET) - target_link_libraries(dbus-1 ${LIBSOCKET}) + target_link_libraries(dbus-1 PRIVATE ${LIBSOCKET}) endif() if (HAVE_BACKTRACE) - target_link_libraries(dbus-1 ${Backtrace_LIBRARY}) + target_link_libraries(dbus-1 PRIVATE ${Backtrace_LIBRARY}) target_include_directories(dbus-1 PRIVATE ${Backtrace_INCLUDE_DIR}) endif() + if(HAVE_LTTNG) + add_lttng_tracepoint(dbus-1 dbus-lttng-verbose.tp) + target_compile_definitions(dbus-1 PRIVATE HAVE_LTTNG) + target_include_directories(dbus-1 PRIVATE ${LTTNG_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + target_link_libraries(dbus-1 PRIVATE ${LTTNG_LIBRARIES}) + endif() endif() # target definitions passed to the clients diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c index dd581372..cc4c8ae0 100644 --- a/dbus/dbus-internals.c +++ b/dbus/dbus-internals.c @@ -37,6 +37,8 @@ #ifdef DBUS_USE_OUTPUT_DEBUG_STRING #include #include +#elif defined(HAVE_LTTNG) +#include "dbus-lttng-verbose-tp.h" #endif /** @@ -467,7 +469,7 @@ _dbus_verbose_real ( if (!_dbus_is_verbose_real()) return; -#ifndef DBUS_USE_OUTPUT_DEBUG_STRING +#if !defined(DBUS_USE_OUTPUT_DEBUG_STRING) && !defined(HAVE_LTTNG) /* Print out pid before the line */ if (need_pid) { @@ -517,6 +519,25 @@ out: } _dbus_string_free (&out); } +#elif defined(HAVE_LTTNG) + { + DBusString out = _DBUS_STRING_INIT_INVALID; + const char *message = NULL; + + if (!_dbus_string_init (&out)) + goto out; + +#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS + if (!_dbus_string_append_printf (&out, "[%s(%d):%s] ", _dbus_file_path_extract_elements_from_tail (file, 2), line, function)) + goto out; +#endif + if (!_dbus_string_append_printf_valist (&out, format, args)) + goto out; + message = _dbus_string_get_const_data (&out); +out: + tracepoint(dbus, verbose, message ? message : "Out of memory while formatting verbose message"); + _dbus_string_free (&out); + } #else #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS fprintf (stderr, "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function); diff --git a/dbus/dbus-lttng-verbose.tp b/dbus/dbus-lttng-verbose.tp new file mode 100644 index 00000000..8df93798 --- /dev/null +++ b/dbus/dbus-lttng-verbose.tp @@ -0,0 +1,10 @@ +TRACEPOINT_EVENT( + dbus, + verbose, + TP_ARGS( + const char*, my_string_arg + ), + TP_FIELDS( + ctf_string(my_string_field, my_string_arg) + ) +) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 032ba1f7..2850842a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -74,6 +74,10 @@ set(manual-paths_SOURCES manual-paths.c ) +if(HAVE_LTTNG) + add_test_executable(test-lttng test-lttng.c dbus-testutils ${LTTNG_LIBRARIES}) + add_lttng_tracepoint(test-lttng test-lttng.tp) +endif() add_helper_executable(manual-dir-iter ${manual-dir-iter_SOURCES} ${DBUS_INTERNAL_LIBRARIES}) add_helper_executable(test-service ${test-service_SOURCES} dbus-testutils) add_helper_executable(test-names ${test-names_SOURCES} dbus-testutils) diff --git a/test/test-lttng.c b/test/test-lttng.c new file mode 100644 index 00000000..a59d6cdc --- /dev/null +++ b/test/test-lttng.c @@ -0,0 +1,12 @@ + + +#include + +#include "test-lttng-tp.h" + +int main(int argc, char **argv) +{ + tracef("argc %d, argv[0] %s", argc, argv[0]); + tracepoint(dbus, lttng_test, argc, argv[0]); + return 0; +} diff --git a/test/test-lttng.tp b/test/test-lttng.tp new file mode 100644 index 00000000..d90c83d9 --- /dev/null +++ b/test/test-lttng.tp @@ -0,0 +1,12 @@ +TRACEPOINT_EVENT( + dbus, + lttng_test, + TP_ARGS( + int, my_integer_arg, + const char*, my_string_arg + ), + TP_FIELDS( + ctf_integer(int, my_integer_field, my_integer_arg) + ctf_string(my_string_field, my_string_arg) + ) +)