From a859449aab66f675a89080c5e59c5ff6b2096a72 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 26 May 2025 20:59:02 -0500 Subject: [PATCH 01/33] feat: Add ZeroMQ support for DFTracer - Updated CMakeLists.txt to include ZeroMQ and cppzmq dependencies based on the writer type. - Introduced DFTRACER_WRITER_TYPE_ENV constant for environment variable configuration. - Refactored metadata handling to use MetadataMap type instead of std::unordered_map. - Enhanced DFTracer and DFTLogger classes to accommodate new metadata structure. - Implemented ZeroMQWriter class for sending log messages over ZeroMQ. - Created a base WriterBase class to standardize logging interfaces for different writers. - Updated ChromeWriter to utilize the new base class and refactored JSON conversion methods. - Added configuration management for writer type selection via environment variables. --- CMakeLists.txt | 1161 +++++++++-------- cmake/configure_files/dftracer_config.hpp.in | 7 +- .../dftracer_config_dbg.hpp.in | 7 +- cmake/modules/dftracer-utils.cmake | 108 +- dependency/CMakeLists.txt | 16 +- include/dftracer/core/constants.h | 1 + include/dftracer/core/typedef.h | 9 + include/dftracer/dftracer.h | 8 +- src/dftracer/core/dftracer_main.cpp | 21 +- src/dftracer/core/dftracer_main.h | 2 +- src/dftracer/core/enumeration.h | 15 +- src/dftracer/df_logger.h | 90 +- src/dftracer/dftracer.cpp | 6 +- src/dftracer/utils/configuration_manager.cpp | 9 +- src/dftracer/utils/configuration_manager.h | 1 + src/dftracer/writer/chrome_writer.cpp | 167 +-- src/dftracer/writer/chrome_writer.h | 76 +- src/dftracer/writer/writer_base.cpp | 96 ++ src/dftracer/writer/writer_base.h | 47 + src/dftracer/writer/zeromq_writer.cpp | 80 ++ src/dftracer/writer/zeromq_writer.h | 49 + 21 files changed, 1161 insertions(+), 815 deletions(-) create mode 100644 src/dftracer/writer/writer_base.cpp create mode 100644 src/dftracer/writer/writer_base.h create mode 100644 src/dftracer/writer/zeromq_writer.cpp create mode 100644 src/dftracer/writer/zeromq_writer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 533b118c..14223da3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.5...3.18) -#------------------------------------------------------------------------------ -# Version information -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ +# Version information +# ------------------------------------------------------------------------------ set(DFTRACER_VERSION_MAJOR "3") set(DFTRACER_VERSION_MINOR "1") set(DFTRACER_VERSION_PATCH "0") @@ -22,280 +22,344 @@ project(dftracer LANGUAGES C CXX) string(TOUPPER "${PROJECT_NAME}" UPPER_PROJECT_NAME) string(TOLOWER "${PROJECT_NAME}" LOWER_PROJECT_NAME) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-empty-body -Wno-format-extra-args") -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ # Internal Includes for header and libraries -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Get installation directories -- these get used in various places; # best to just make them available -option (DFTRACER_LIBDIR_AS_LIB OFF) -if (NOT DFTRACER_LIBDIR_AS_LIB) - include(GNUInstallDirs) -endif () +option(DFTRACER_LIBDIR_AS_LIB OFF) + +if(NOT DFTRACER_LIBDIR_AS_LIB) + include(GNUInstallDirs) +endif() + # -if (CMAKE_INSTALL_LIBDIR) - message(STATUS "CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}") - set(DFTRACER_LIBDIR ${CMAKE_INSTALL_LIBDIR}) - set(DFTRACER_INSTALL_INCLUDE_DIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) - set(DFTRACER_INSTALL_DOCDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}) - set(DFTRACER_INSTALL_SYSCONFDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/modulefiles) - set(DFTRACER_INSTALL_BINFDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}) -else () - set(DFTRACER_LIBDIR "lib") - set(DFTRACER_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") - set(DFTRACER_INSTALL_DOCDIR "${CMAKE_INSTALL_PREFIX}/doc") - set(DFTRACER_INSTALL_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc/modulefiles") - set(DFTRACER_INSTALL_BINARYDIR "${CMAKE_INSTALL_PREFIX}/bin") - message(STATUS "DFTRACER_LIBDIR set to ${DFTRACER_LIBDIR}") -endif () - -#------------------------------------------------------------------------------ +if(CMAKE_INSTALL_LIBDIR) + message(STATUS "CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}") + set(DFTRACER_LIBDIR ${CMAKE_INSTALL_LIBDIR}) + set(DFTRACER_INSTALL_INCLUDE_DIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) + set(DFTRACER_INSTALL_DOCDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}) + set(DFTRACER_INSTALL_SYSCONFDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/modulefiles) + set(DFTRACER_INSTALL_BINFDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}) +else() + set(DFTRACER_LIBDIR "lib") + set(DFTRACER_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") + set(DFTRACER_INSTALL_DOCDIR "${CMAKE_INSTALL_PREFIX}/doc") + set(DFTRACER_INSTALL_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc/modulefiles") + set(DFTRACER_INSTALL_BINARYDIR "${CMAKE_INSTALL_PREFIX}/bin") + message(STATUS "DFTRACER_LIBDIR set to ${DFTRACER_LIBDIR}") +endif() + +# ------------------------------------------------------------------------------ # Internal Paths for cmake libraries and Setup install and output Directories -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # This sets where to look for dependent libraries set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_BINARY_DIR} ${CMAKE_INSTALL_PREFIX}) + # This sets where to look for dependent library's cmake files list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/cmake) list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}/share/cmake) -#------------------------------------------------------------------------------ -if (NOT DFTRACER_EXTERNALLY_CONFIGURED) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Single Directory for all Executables.") - set(CMAKE_INCLUDE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/include CACHE PATH "Store the headers.") - set(EXECUTABLE_OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all Libraries") - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all static libraries.") -endif () +# ------------------------------------------------------------------------------ +if(NOT DFTRACER_EXTERNALLY_CONFIGURED) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Single Directory for all Executables.") + set(CMAKE_INCLUDE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/include CACHE PATH "Store the headers.") + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all Libraries") + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all static libraries.") +endif() include_directories(${CMAKE_BINARY_DIR}/include) link_directories(${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Targets built within this project are exported at Install time for use # by other projects. -#----------------------------------------------------------------------------- -if (NOT DFTRACER_EXPORTED_TARGETS) - set(DFTRACER_EXPORTED_TARGETS "dftracer-targets") -endif () +# ----------------------------------------------------------------------------- +if(NOT DFTRACER_EXPORTED_TARGETS) + set(DFTRACER_EXPORTED_TARGETS "dftracer-targets") +endif() include(dftracer-utils) -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ # Build options -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # option(ENABLE_DFTRACER_DEBUG "Include debugging prints and logging" OFF) # This is not needed as we have CMAKE_BUILD_TYPE # This is verbose, maybe an alternate might help simplify -#option(BUILD_URPC "Build DFTRACER's URPC code" OFF) -#option(ENABLE_PERFFLOW "Build with PerfFlow Aspect support" OFF) -#option(ENABLE_UCX_DTL "Build DFTRACER's UCX data transport layer" OFF) +# option(BUILD_URPC "Build DFTRACER's URPC code" OFF) +# option(ENABLE_PERFFLOW "Build with PerfFlow Aspect support" OFF) +# option(ENABLE_UCX_DTL "Build DFTRACER's UCX data transport layer" OFF) # This option is off by default because non-developers should not use # this option under normal circumstances. option(DFTRACER_WARNINGS_AS_ERRORS "Build with warnings promoted to errors." OFF) mark_as_advanced(DFTRACER_WARNINGS_AS_ERRORS) -option (DFTRACER_USE_CLANG_LIBCXX OFF) -if (DFTRACER_USE_CLANG_LIBCXX) - set (GCC_TOOLCHAIN "") -endif (DFTRACER_USE_CLANG_LIBCXX) +option(DFTRACER_USE_CLANG_LIBCXX OFF) + +if(DFTRACER_USE_CLANG_LIBCXX) + set(GCC_TOOLCHAIN "") +endif(DFTRACER_USE_CLANG_LIBCXX) # Options -option (DFTRACER_DISABLE_HWLOC "Disable HWLOC" On) -if (NOT DFTRACER_DISABLE_HWLOC) - set(DFTRACER_HWLOC_ENABLE 1) +option(DFTRACER_DISABLE_HWLOC "Disable HWLOC" On) + +if(NOT DFTRACER_DISABLE_HWLOC) + set(DFTRACER_HWLOC_ENABLE 1) endif() # Options -option (DFTRACER_ENABLE_FTRACING "Enable Function Tracing" OFF) -if (DFTRACER_ENABLE_FTRACING) - set(DFTRACER_FTRACING_ENABLE 1) - set(DFTRACER_FUNCTION_FLAGS "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default") +option(DFTRACER_ENABLE_FTRACING "Enable Function Tracing" OFF) + +if(DFTRACER_ENABLE_FTRACING) + set(DFTRACER_FTRACING_ENABLE 1) + set(DFTRACER_FUNCTION_FLAGS "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default") else() - set(DFTRACER_FUNCTION_FLAGS ) + set(DFTRACER_FUNCTION_FLAGS) endif() -option (DFTRACER_ENABLE_MPI "Enable MPI" OFF) -if (DFTRACER_ENABLE_MPI) - set(DFTRACER_MPI_ENABLE 1) +option(DFTRACER_ENABLE_MPI "Enable MPI" OFF) + +if(DFTRACER_ENABLE_MPI) + set(DFTRACER_MPI_ENABLE 1) endif() -option (DFTRACER_BUILD_PYTHON_BINDINGS "Build python bindings." ON) + +option(DFTRACER_WRITER_TYPE "Writer Type" "CHROME") + +if(DFTRACER_WRITER_TYPE STREQUAL "ZEROMQ") + set(DFTRACER_WRITER_TYPE_CHROME 0) + set(DFTRACER_WRITER_TYPE_ZEROMQ 1) +else() + set(DFTRACER_WRITER_TYPE_CHROME 1) + set(DFTRACER_WRITER_TYPE_ZEROMQ 0) +endif() + +option(DFTRACER_BUILD_PYTHON_BINDINGS "Build python bindings." ON) set(DFTRACER_PYTHON_EXE "python3" CACHE STRING "Python executable to use for building.") set(DFTRACER_PYTHON_SITE $ENV{DFTRACER_PYTHON_SITE} CACHE STRING "Python site packages to use for building.") -if (DFTRACER_BUILD_PYTHON_BINDINGS) - if (DFTRACER_PYTHON_SITE) - set(PYTHON_SITE_PACKAGES "${DFTRACER_PYTHON_SITE}") - set(MAIN_PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES}) - else() - set(PYTHON_SITE_PACKAGES ${CMAKE_INSTALL_PREFIX}) - execute_process (COMMAND ${DFTRACER_PYTHON_EXE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE MAIN_PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() - include_directories(${PYTHON_SITE_PACKAGES}/dftracer/include) - link_directories(${PYTHON_SITE_PACKAGES}/dftracer/lib) +if(DFTRACER_BUILD_PYTHON_BINDINGS) + if(DFTRACER_PYTHON_SITE) + set(PYTHON_SITE_PACKAGES "${DFTRACER_PYTHON_SITE}") + set(MAIN_PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES}) + else() + set(PYTHON_SITE_PACKAGES ${CMAKE_INSTALL_PREFIX}) + execute_process(COMMAND ${DFTRACER_PYTHON_EXE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE MAIN_PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + + include_directories(${PYTHON_SITE_PACKAGES}/dftracer/include) + link_directories(${PYTHON_SITE_PACKAGES}/dftracer/lib) endif() # install dependency -option (DFTRACER_INSTALL_DEPENDENCIES "Install DFTracer dependencies" OFF) +option(DFTRACER_INSTALL_DEPENDENCIES "Install DFTracer dependencies" OFF) # testing -option (DFTRACER_ENABLE_TESTS "Enable tests for DFTRACER." OFF) -option (DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS "Enable dlio_benchmark tests" OFF) -option (DFTRACER_ENABLE_PAPER_TESTS "Enable paper tests" OFF) -set (DFTRACER_TEST_LD_LIBRARY_PATH "" CACHE STRING "Additional LD_LIBRARY_PATH to be included on testing") +option(DFTRACER_ENABLE_TESTS "Enable tests for DFTRACER." OFF) +option(DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS "Enable dlio_benchmark tests" OFF) +option(DFTRACER_ENABLE_PAPER_TESTS "Enable paper tests" OFF) +set(DFTRACER_TEST_LD_LIBRARY_PATH "" CACHE STRING "Additional LD_LIBRARY_PATH to be included on testing") -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Compiler setup -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ include(ExternalProject) + # It requires include(GNUInstallDirs) before if that is needed include(SetupCompiler) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Build Type based configurations -#------------------------------------------------------------------------------ - +# ------------------------------------------------------------------------------ if(CMAKE_BUILD_TYPE STREQUAL "") - set(CMAKE_BUILD_TYPE "Release") # Setting default as Release + set(CMAKE_BUILD_TYPE "Release") # Setting default as Release +endif() + +if(NOT DEFINED BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS ON) endif() -if (NOT DEFINED BUILD_SHARED_LIBS) - set(BUILD_SHARED_LIBS ON) -endif () -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Disallow in-source build -#------------------------------------------------------------------------------ -if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") - message(FATAL_ERROR - "${PROJECT_NAME} requires an out of source Build. " - "Please create a separate binary directory and run CMake there.") -endif () -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ +if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") + message(FATAL_ERROR + "${PROJECT_NAME} requires an out of source Build. " + "Please create a separate binary directory and run CMake there.") +endif() + +# ------------------------------------------------------------------------------ # Set a default build type if none was specified -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ set(CMAKE_POSITION_INDEPENDENT_CODE ON) -if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") - set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) - # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" - "MinSizeRel" "RelWithDebInfo") -endif () -#------------------------------------------------------------------------------ -# Dependencies -#------------------------------------------------------------------------------ -if (DFTRACER_INSTALL_DEPENDENCIES) - message(STATUS "[${PROJECT_NAME}] downloading dependencies. Please run make for downloading depedencies and then do reconfigure without dependency flag.") - message(STATUS "[${PROJECT_NAME}] Installing depedencies at ${CMAKE_INSTALL_PREFIX}") - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/dependency) +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) + + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" + "MinSizeRel" "RelWithDebInfo") +endif() + +# ------------------------------------------------------------------------------ +# Dependencies +# ------------------------------------------------------------------------------ +if(DFTRACER_INSTALL_DEPENDENCIES) + message(STATUS "[${PROJECT_NAME}] downloading dependencies. Please run make for downloading depedencies and then do reconfigure without dependency flag.") + message(STATUS "[${PROJECT_NAME}] Installing depedencies at ${CMAKE_INSTALL_PREFIX}") + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/dependency) else() -# Required Dependencies -# ============================================================================= -set(DEPENDENCY_LIB ${CMAKE_EXE_LINKER_FLAGS} $ENV{LDFLAGS}) -find_package(cpp-logger 1.0.0 REQUIRED) -if (${cpp-logger_FOUND}) + # Required Dependencies + # ============================================================================= + set(DEPENDENCY_LIB ${CMAKE_EXE_LINKER_FLAGS} $ENV{LDFLAGS}) + find_package(cpp-logger 1.0.0 REQUIRED) + + if(${cpp-logger_FOUND}) include_directories(${CPP_LOGGER_INCLUDE_DIRS}) set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${CPP_LOGGER_LIBRARIES}) message(STATUS "[CPP_LOGGER] found cpp-logger at ${CPP_LOGGER_INCLUDE_DIRS}") -else () + else() message(FATAL_ERROR "-- [CPP_LOGGER] is needed for ${PROJECT_NAME} build") -endif () -find_package(brahma 2.1.0 REQUIRED) -if (${brahma_FOUND}) + endif() + + find_package(brahma 2.1.0 REQUIRED) + + if(${brahma_FOUND}) message(STATUS "[BRAHMA] found brahma at ${BRAHMA_INCLUDE_DIRS}") include_directories(${BRAHMA_INCLUDE_DIRS}) set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${BRAHMA_LIBRARIES}) -else () + else() message(FATAL_ERROR "-- [BRAHMA] is needed for ${PROJECT_NAME} build") -endif () -find_package(yaml-cpp REQUIRED) -if (${yaml-cpp_FOUND}) + endif() + + find_package(yaml-cpp REQUIRED) + + if(${yaml-cpp_FOUND}) message(STATUS "[DFTRACER] found yaml-cpp at ${YAML_CPP_INCLUDE_DIR}") include_directories(${YAML_CPP_INCLUDE_DIR}) set(YAML_CPP_LIBRARY_DIR "${YAML_CPP_CMAKE_DIR}/../../") set(DEPENDENCY_LIB ${DEPENDENCY_LIB} -L${YAML_CPP_LIBRARY_DIR} ${YAML_CPP_LIBRARIES}) -else () + else() message(FATAL_ERROR "-- [DFTRACER] yaml-cpp is needed for ${PROJECT_NAME} build") -endif () + endif() -# Optional Dependencies -# ============================================================================= -if (DFTRACER_BUILD_PYTHON_BINDINGS) + # Optional Dependencies + # ============================================================================= + if(DFTRACER_BUILD_PYTHON_BINDINGS) find_package(pybind11 REQUIRED) - #add_subdirectory(dependency/py11bind) -endif() -if (DFTRACER_ENABLE_MPI) - find_package(MPI COMPONENTS CXX REQUIRED) - if (MPI_FOUND) + # add_subdirectory(dependency/py11bind) + endif() + + if(DFTRACER_ENABLE_MPI) + find_package(MPI COMPONENTS CXX REQUIRED) + + if(MPI_FOUND) message(STATUS "[DFTRACER] found mpi.h at ${MPI_CXX_INCLUDE_DIRS}") include_directories(${MPI_CXX_INCLUDE_DIRS}) set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${MPI_CXX_LIBRARIES}) - else () + else() message(FATAL_ERROR "-- [DFTRACER] mpi is needed for ${PROJECT_NAME} build") - endif () -endif() + endif() + endif() -if (NOT DFTRACER_DISABLE_HWLOC) + if(NOT DFTRACER_DISABLE_HWLOC) find_package(HWLOC REQUIRED) - if (${HWLOC_FOUND}) - include_directories(${HWLOC_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HWLOC_LIBRARIES}) - message(STATUS "[DFTRACER] found hwloc at ${HWLOC_INCLUDE_DIRS}") - else () - message(FATAL_ERROR "-- [DFTRACER] hwloc is needed for ${PROJECT_NAME} build with -DDFTRACER_DISABLE_HWLOC-ON option.") - endif () -endif() -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -set(DFTRACER_PRELOAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer_preload.cpp) -set(DFTRACER_PRELOAD_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer_preload.h) - -set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/posix.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/stdio.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/finstrument/functions.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/chrome_writer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/posix_internal.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_main.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/configuration_manager.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/md5.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/df_logger.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/utils.cpp) -set(DFTRACER_CORE_PUBLIC_INCLUDE - ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/dftracer.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/constants.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/typedef.h) -set(DFTRACER_CORE_PRIVATE_INCLUDE - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/posix_internal.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/utils.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/md5.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/finstrument/functions.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/posix.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/stdio.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_main.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/logging.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/singleton.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/configuration_manager.h) -add_library(${PROJECT_NAME} SHARED) -target_compile_definitions(${PROJECT_NAME} PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) -target_link_libraries(${PROJECT_NAME} ${DEPENDENCY_LIB}) -add_library(${PROJECT_NAME}_dbg SHARED) -target_link_libraries(${PROJECT_NAME}_dbg ${DEPENDENCY_LIB}) -add_library(${PROJECT_NAME}_preload SHARED) -target_link_libraries(${PROJECT_NAME}_preload ${DEPENDENCY_LIB} ${PROJECT_NAME}) -add_library(${PROJECT_NAME}_preload_dbg SHARED) -target_link_libraries(${PROJECT_NAME}_preload_dbg ${DEPENDENCY_LIB} ${PROJECT_NAME}_dbg) - -set(DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_dbg ${PROJECT_NAME}_preload_dbg) - -if (DFTRACER_BUILD_PYTHON_BINDINGS) + if(${HWLOC_FOUND}) + include_directories(${HWLOC_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HWLOC_LIBRARIES}) + message(STATUS "[DFTRACER] found hwloc at ${HWLOC_INCLUDE_DIRS}") + else() + message(FATAL_ERROR "-- [DFTRACER] hwloc is needed for ${PROJECT_NAME} build with -DDFTRACER_DISABLE_HWLOC-ON option.") + endif() + endif() + + if(DFTRACER_WRITER_TYPE STREQUAL "ZEROMQ") + find_package(PkgConfig REQUIRED) + pkg_check_modules(ZMQ REQUIRED libzmq) + + if(ZMQ_FOUND) + message(STATUS "[DFTRACER] Found ZeroMQ at ${ZMQ_INCLUDE_DIRS}") + include_directories(${ZMQ_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZMQ_LIBRARIES}) + else() + message(FATAL_ERROR "-- [DFTRACER] ZeroMQ is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'zeromq'") + endif() + + find_path(CPPZMQ_INCLUDE_DIR zmq.hpp) + + if(CPPZMQ_INCLUDE_DIR) + message(STATUS "[DFTRACER] Found cppzmq at ${CPPZMQ_INCLUDE_DIR}") + include_directories(${CPPZMQ_INCLUDE_DIR}) + else() + message(WARNING "[DFTRACER] cppzmq (C++ wrapper) not found — will fallback to C-style API") + endif() + endif() + + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + set(DFTRACER_PRELOAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer_preload.cpp) + set(DFTRACER_PRELOAD_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer_preload.h) + + set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/posix.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/stdio.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/finstrument/functions.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/posix_internal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/configuration_manager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/md5.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/df_logger.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/utils.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/writer_base.cpp) + + if(DFTRACER_WRITER_TYPE_ZEROMQ) + set(DFTRACER_CORE_SRC ${DFTRACER_CORE_SRC} + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/zeromq_writer.cpp) + elseif(DFTRACER_WRITER_TYPE_CHROME) + set(DFTRACER_CORE_SRC ${DFTRACER_CORE_SRC} + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/chrome_writer.cpp) + endif() + + set(DFTRACER_CORE_PUBLIC_INCLUDE + ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/dftracer.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/constants.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/typedef.h) + set(DFTRACER_CORE_PRIVATE_INCLUDE + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/posix_internal.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/utils.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/md5.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/finstrument/functions.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/posix.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/stdio.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_main.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/logging.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/singleton.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/configuration_manager.h) + add_library(${PROJECT_NAME} SHARED) + target_compile_definitions(${PROJECT_NAME} PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) + target_link_libraries(${PROJECT_NAME} ${DEPENDENCY_LIB}) + add_library(${PROJECT_NAME}_dbg SHARED) + target_link_libraries(${PROJECT_NAME}_dbg ${DEPENDENCY_LIB}) + add_library(${PROJECT_NAME}_preload SHARED) + target_link_libraries(${PROJECT_NAME}_preload ${DEPENDENCY_LIB} ${PROJECT_NAME}) + add_library(${PROJECT_NAME}_preload_dbg SHARED) + target_link_libraries(${PROJECT_NAME}_preload_dbg ${DEPENDENCY_LIB} ${PROJECT_NAME}_dbg) + + set(DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_dbg ${PROJECT_NAME}_preload_dbg) + + if(DFTRACER_BUILD_PYTHON_BINDINGS) pybind11_add_module(py${PROJECT_NAME} ${DFTRACER_CORE_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/pydftracer.cpp) target_compile_definitions(py${PROJECT_NAME} PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) target_link_libraries(py${PROJECT_NAME} PRIVATE ${DEPENDENCY_LIB}) @@ -304,85 +368,92 @@ if (DFTRACER_BUILD_PYTHON_BINDINGS) target_compile_definitions(py${PROJECT_NAME}_dbg PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) target_link_libraries(py${PROJECT_NAME}_dbg PRIVATE ${DEPENDENCY_LIB}) list(APPEND DFTRACER_DEBUG_TARGETS py${PROJECT_NAME}_dbg) -endif() -target_sources(${PROJECT_NAME} - PRIVATE - ${DFTRACER_CORE_SRC} - ${DFTRACER_PRELOAD_SRC} - ) -target_sources(${PROJECT_NAME}_dbg - PRIVATE - ${DFTRACER_CORE_SRC} - ${DFTRACER_PRELOAD_SRC} - ) -target_sources(${PROJECT_NAME}_preload - PRIVATE - ${DFTRACER_PRELOAD_SRC} - ) -target_sources(${PROJECT_NAME}_preload_dbg - PRIVATE - ${DFTRACER_PRELOAD_SRC} - ) -target_include_directories(${PROJECT_NAME} - PRIVATE - # where the library itself will look for its internal headers - ${CMAKE_CURRENT_SOURCE_DIR}/src - PUBLIC - # where top-level project will look for the library's public headers - $ - # where external projects will look for the library's public headers - $ - ) -target_include_directories(${PROJECT_NAME}_dbg - PRIVATE - # where the library itself will look for its internal headers - ${CMAKE_CURRENT_SOURCE_DIR}/src - PUBLIC - # where top-level project will look for the library's public headers - $ - # where external projects will look for the library's public headers - $ - ) -set_target_properties(${PROJECT_NAME} - PROPERTIES - DEBUG_OUTPUT_NAME ${PROJECT_NAME} - RELEASE_OUTPUT_NAME ${PROJECT_NAME} - MINSIZEREL_OUTPUT_NAME ${PROJECT_NAME} - RELWITHDEBINFO_OUTPUT_NAME ${PROJECT_NAME} - VERSION ${DFTRACER_PACKAGE_VERSION} - SOVERSION ${DFTRACER_PACKAGE_VERSION} - ) - -dftracer_debug_config("${DFTRACER_DEBUG_TARGETS}") -dftracer_install_headers("${DFTRACER_CORE_PUBLIC_INCLUDE}") -install( - TARGETS ${PROJECT_NAME} - EXPORT ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} -) -install(TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install( - TARGETS ${PROJECT_NAME}_dbg - EXPORT ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} + endif() + + target_sources(${PROJECT_NAME} + PRIVATE + ${DFTRACER_CORE_SRC} + ${DFTRACER_PRELOAD_SRC} + ) + target_sources(${PROJECT_NAME}_dbg + PRIVATE + ${DFTRACER_CORE_SRC} + ${DFTRACER_PRELOAD_SRC} ) -install(TARGETS ${PROJECT_NAME}_dbg - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(TARGETS ${PROJECT_NAME}_preload - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(TARGETS ${PROJECT_NAME}_preload_dbg - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - -install( + target_sources(${PROJECT_NAME}_preload + PRIVATE + ${DFTRACER_PRELOAD_SRC} + ) + target_sources(${PROJECT_NAME}_preload_dbg + PRIVATE + ${DFTRACER_PRELOAD_SRC} + ) + target_include_directories(${PROJECT_NAME} + PRIVATE + + # where the library itself will look for its internal headers + ${CMAKE_CURRENT_SOURCE_DIR}/src + PUBLIC + + # where top-level project will look for the library's public headers + $ + + # where external projects will look for the library's public headers + $ + ) + target_include_directories(${PROJECT_NAME}_dbg + PRIVATE + + # where the library itself will look for its internal headers + ${CMAKE_CURRENT_SOURCE_DIR}/src + PUBLIC + + # where top-level project will look for the library's public headers + $ + + # where external projects will look for the library's public headers + $ + ) + set_target_properties(${PROJECT_NAME} + PROPERTIES + DEBUG_OUTPUT_NAME ${PROJECT_NAME} + RELEASE_OUTPUT_NAME ${PROJECT_NAME} + MINSIZEREL_OUTPUT_NAME ${PROJECT_NAME} + RELWITHDEBINFO_OUTPUT_NAME ${PROJECT_NAME} + VERSION ${DFTRACER_PACKAGE_VERSION} + SOVERSION ${DFTRACER_PACKAGE_VERSION} + ) + + dftracer_debug_config("${DFTRACER_DEBUG_TARGETS}") + dftracer_install_headers("${DFTRACER_CORE_PUBLIC_INCLUDE}") + install( + TARGETS ${PROJECT_NAME} + EXPORT ${DFTRACER_EXPORTED_TARGETS} + LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} + ) + install(TARGETS ${PROJECT_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install( + TARGETS ${PROJECT_NAME}_dbg + EXPORT ${DFTRACER_EXPORTED_TARGETS} + LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} + ) + install(TARGETS ${PROJECT_NAME}_dbg + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(TARGETS ${PROJECT_NAME}_preload + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(TARGETS ${PROJECT_NAME}_preload_dbg + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + install( TARGETS ${PROJECT_NAME}_preload EXPORT @@ -390,8 +461,8 @@ install( LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} -) -install( + ) + install( TARGETS ${PROJECT_NAME}_preload_dbg EXPORT @@ -399,11 +470,12 @@ install( LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} -) -if (DFTRACER_BUILD_PYTHON_BINDINGS) + ) + + if(DFTRACER_BUILD_PYTHON_BINDINGS) install(TARGETS py${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/$") install(CODE "execute_process( COMMAND bash -c \"set -e @@ -412,294 +484,297 @@ if (DFTRACER_BUILD_PYTHON_BINDINGS) \")") install(TARGETS py${PROJECT_NAME}_dbg - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink_dbg.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/$") install(CODE "execute_process( COMMAND bash -c \"set -e chmod +x ${CMAKE_BINARY_DIR}/symlink_dbg.sh . ${CMAKE_BINARY_DIR}/symlink_dbg.sh \")") -endif() -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact - DESTINATION - bin -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact_by_pid ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid - DESTINATION - bin -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_merge ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge - DESTINATION - bin -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_sanitize ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize - DESTINATION - bin -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_anonymize ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize - DESTINATION - bin -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_create_index ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index - DESTINATION - bin -) - - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_pgzip ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip - DESTINATION - bin -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_split ${EXECUTABLE_OUTPUT_PATH}/dftracer_split COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_split - DESTINATION - bin -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_event_count ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count - DESTINATION - bin -) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_validate ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate COPYONLY) -install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate - DESTINATION - bin -) - -#cmake_policy(SET CMP0079 NEW) # In case that we need more control over the target building order - -if(DFTRACER_ENABLE_TESTS) + endif() + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact_by_pid ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_merge ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_sanitize ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_anonymize ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_create_index ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_pgzip ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_split ${EXECUTABLE_OUTPUT_PATH}/dftracer_split COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_split + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_event_count ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count + DESTINATION + bin + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_validate ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate COPYONLY) + install( + FILES + ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate + DESTINATION + bin + ) + + # cmake_policy(SET CMP0079 NEW) # In case that we need more control over the target building order + if(DFTRACER_ENABLE_TESTS) message("-- " "[DFTracer] Enabling Testing") + if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") - message("-- " "[DFTracer] building with CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}") - set(CMAKE_C_FLAGS_PROFILE --coverage) - set(CMAKE_CXX_FLAGS_PROFILE --coverage) + message("-- " "[DFTracer] building with CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}") + set(CMAKE_C_FLAGS_PROFILE --coverage) + set(CMAKE_CXX_FLAGS_PROFILE --coverage) endif() + enable_testing() add_subdirectory(test) + if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") - get_property(COVERAGE_FILE_LIST GLOBAL PROPERTY COVERAGE_FILES) - add_custom_command(OUTPUT default.profdata COMMAND llvm-profdata merge -sparse ${COVERAGE_FILE_LIST} -o default.profdata VERBATIM) - add_custom_target(merged_coverage DEPENDS default.profdata) + get_property(COVERAGE_FILE_LIST GLOBAL PROPERTY COVERAGE_FILES) + add_custom_command(OUTPUT default.profdata COMMAND llvm-profdata merge -sparse ${COVERAGE_FILE_LIST} -o default.profdata VERBATIM) + add_custom_target(merged_coverage DEPENDS default.profdata) endif() -endif() + endif() + + # ----------------------------------------------------------------------------- + # Configure the config.cmake file for the build directory + # ----------------------------------------------------------------------------- + include(CMakePackageConfigHelpers) + configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.build.in + "${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config.cmake" + INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake + PATH_VARS CMAKE_BINARY_DIR + ) + + configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.install.in + "${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake" + INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/install/${PROJECT_NAME}-config.cmake + PATH_VARS CMAKE_BINARY_DIR + ) + install( + FILES + ${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake + DESTINATION + ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} + ) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/dftracer-utils.cmake" + DESTINATION "${DFTRACER_LIBDIR}/cmake/dftracer") + + # ----------------------------------------------------------------------------- + # Configure the ${PROJECT_NAME}-config-version .cmake file for the install directory + # ----------------------------------------------------------------------------- + install( + FILES + ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake + DESTINATION + ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} + ) + + export(EXPORT ${DFTRACER_EXPORTED_TARGETS} + FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake") + + # Write the configure file + configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config.hpp.in" + "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/dftracer_config.hpp" @ONLY) + + configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config_dbg.hpp.in" + "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/dftracer_config_dbg.hpp" @ONLY) + + # ############################################################### + # Install DFTRACER + # ############################################################### + include(CMakePackageConfigHelpers) + + # Write the version file. This is independent of build/install tree. + write_basic_package_version_file( + dftracer-config-version.cmake + VERSION "${DFTRACER_PACKAGE_VERSION}" + COMPATIBILITY SameMajorVersion) + + install(FILES + "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/dftracer_config.hpp" + DESTINATION + ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer) + + install(FILES + "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/dftracer_config_dbg.hpp" + DESTINATION + ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer) + + install(EXPORT + ${DFTRACER_EXPORTED_TARGETS} + DESTINATION + ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} + FILE + ${DFTRACER_EXPORTED_TARGETS}.cmake + ) + + # Install license and readme + install(FILES + "${PROJECT_SOURCE_DIR}/LICENSE" + "${PROJECT_SOURCE_DIR}/README.md" + DESTINATION + ${DFTRACER_INSTALL_DOCDIR}) + + # ############################################################################## + # Print out configuration summary + # ############################################################################## + if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") + set(DFTRACER_GNU_LINUX TRUE) + endif() + + # NOTE: message() outputs to stderr by default. We now use a string to + # maintain this information and then have cmake echo it to stdout. The + # only side effects are that if you use the CMake GUI, you won't see + # this output anymore (they only report stderr) and that if you add + # something to the list, you must remember your newline! + set(_str "\n== DFTRACER Configuration Summary ==\n\n") + string(APPEND _str " PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}\n" + " PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}\n\n" + " CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}\n" + " CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n\n") + + if(CMAKE_BUILD_TYPE MATCHES None) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS}\n") + elseif(CMAKE_BUILD_TYPE MATCHES Release) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\n") + string(APPEND _str + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}\n") + elseif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}\n") + string(APPEND _str + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELWITHDEBINFO}\n") + elseif(CMAKE_BUILD_TYPE MATCHES Debug) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}\n") + string(APPEND _str + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}\n") + endif() + + string(APPEND _str "\n") -#----------------------------------------------------------------------------- -# Configure the config.cmake file for the build directory -#----------------------------------------------------------------------------- -include(CMakePackageConfigHelpers) -configure_package_config_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.build.in - "${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config.cmake" - INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake - PATH_VARS CMAKE_BINARY_DIR -) - -configure_package_config_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.install.in - "${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake" - INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/install/${PROJECT_NAME}-config.cmake - PATH_VARS CMAKE_BINARY_DIR -) -install( - FILES - ${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake - DESTINATION - ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} -) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/dftracer-utils.cmake" - DESTINATION "${DFTRACER_LIBDIR}/cmake/dftracer") -#----------------------------------------------------------------------------- -# Configure the ${PROJECT_NAME}-config-version .cmake file for the install directory -#----------------------------------------------------------------------------- - -install( - FILES - ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake - DESTINATION - ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} -) - -export(EXPORT ${DFTRACER_EXPORTED_TARGETS} - FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake") - -# Write the configure file -configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config.hpp.in" - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/dftracer_config.hpp" @ONLY) - -configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config_dbg.hpp.in" - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/dftracer_config_dbg.hpp" @ONLY) - -################################################################ -# Install DFTRACER -################################################################ - -include(CMakePackageConfigHelpers) - -# Write the version file. This is independent of build/install tree. -write_basic_package_version_file( - dftracer-config-version.cmake - VERSION "${DFTRACER_PACKAGE_VERSION}" - COMPATIBILITY SameMajorVersion) - -install(FILES - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/dftracer_config.hpp" - DESTINATION - ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer) - -install(FILES - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/dftracer_config_dbg.hpp" - DESTINATION - ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer) - -install(EXPORT - ${DFTRACER_EXPORTED_TARGETS} - DESTINATION - ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} - FILE - ${DFTRACER_EXPORTED_TARGETS}.cmake - ) - -# Install license and readme -install(FILES - "${PROJECT_SOURCE_DIR}/LICENSE" - "${PROJECT_SOURCE_DIR}/README.md" - DESTINATION - ${DFTRACER_INSTALL_DOCDIR}) - -############################################################################### -# Print out configuration summary -############################################################################### - -if (CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") - set(DFTRACER_GNU_LINUX TRUE) -endif () - -# NOTE: message() outputs to stderr by default. We now use a string to -# maintain this information and then have cmake echo it to stdout. The -# only side effects are that if you use the CMake GUI, you won't see -# this output anymore (they only report stderr) and that if you add -# something to the list, you must remember your newline! -set(_str "\n== DFTRACER Configuration Summary ==\n\n") -string(APPEND _str " PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}\n" - " PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}\n\n" - " CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}\n" - " CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n\n") -if (CMAKE_BUILD_TYPE MATCHES None) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS}\n") -elseif (CMAKE_BUILD_TYPE MATCHES Release) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\n") - string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}\n") -elseif (CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}\n") + " DFTRACER_PACKAGE_VERSION: ${DFTRACER_PACKAGE_VERSION}\n") string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELWITHDEBINFO}\n") -elseif (CMAKE_BUILD_TYPE MATCHES Debug) + " DFTRACER_GIT_VERSION: ${DFTRACER_GIT_VERSION}\n") string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}\n") + " GLIBC_VERSION: ${GLIBC_VERSION}\n") string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}\n") -endif () -string(APPEND _str "\n") - -string(APPEND _str - " DFTRACER_PACKAGE_VERSION: ${DFTRACER_PACKAGE_VERSION}\n") -string(APPEND _str - " DFTRACER_GIT_VERSION: ${DFTRACER_GIT_VERSION}\n") -string(APPEND _str - " GLIBC_VERSION: ${GLIBC_VERSION}\n") + " DFTRACER_PYTHON_EXE: ${DFTRACER_PYTHON_EXE}\n") string(APPEND _str - " DFTRACER_PYTHON_EXE: ${DFTRACER_PYTHON_EXE}\n") + " DFTRACER_PYTHON_SITE: ${DFTRACER_PYTHON_SITE}\n") string(APPEND _str - " DFTRACER_PYTHON_SITE: ${DFTRACER_PYTHON_SITE}\n") + " MAIN_PYTHON_SITE_PACKAGES: ${MAIN_PYTHON_SITE_PACKAGES}\n") string(APPEND _str - " MAIN_PYTHON_SITE_PACKAGES: ${MAIN_PYTHON_SITE_PACKAGES}\n") + " DEPENDENCY_LIB: ${DEPENDENCY_LIB}\n") + + # Print the true/false variables + append_str_tf(_str + DFTRACER_BUILD_PYTHON_BINDINGS + DFTRACER_DISABLE_HWLOC + DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS + DFTRACER_ENABLE_FTRACING + DFTRACER_ENABLE_MPI + DFTRACER_ENABLE_PAPER_TESTS + DFTRACER_ENABLE_TESTS + DFTRACER_GNU_LINUX + DFTRACER_LIBDIR_AS_LIB + DFTRACER_USE_CLANG_LIBCXX + DFTRACER_WARNINGS_AS_ERRORS + DFTRACER_WRITER_TYPE_CHROME + DFTRACER_WRITER_TYPE_ZEROMQ + ) string(APPEND _str - " DEPENDENCY_LIB: ${DEPENDENCY_LIB}\n") -#Print the true/false variables -append_str_tf(_str - DFTRACER_GNU_LINUX - DFTRACER_LIBDIR_AS_LIB - DFTRACER_ENABLE_FTRACING - DFTRACER_ENABLE_MPI - DFTRACER_DISABLE_HWLOC - DFTRACER_USE_CLANG_LIBCXX - DFTRACER_WARNINGS_AS_ERRORS - DFTRACER_BUILD_PYTHON_BINDINGS - DFTRACER_ENABLE_TESTS - DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS - DFTRACER_ENABLE_PAPER_TESTS -) -string(APPEND _str - "\n== End DFTRACER Configuration Summary ==\n") - -# Output to stdout -execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${_str}") -set(_str) - -############################################################################### -# Write a basic modulefile -############################################################################### - -set(DFTRACER_MODULEFILE_NAME "dftracer-${DFTRACER_PACKAGE_VERSION}.lua") -# CACHE STRING -# "The name of the DFTRACER modulefile to install. Must end in .lua.") - -if (NOT (DFTRACER_MODULEFILE_NAME MATCHES ".+\.lua")) - message(WARNING - "DFTRACER_MODULEFILE_NAME must have extension \".lua\". Appending.") - set(DFTRACER_MODULEFILE_NAME "${DFTRACER_MODULEFILE_NAME}.lua" - CACHE STRING "" FORCE) -endif () - -configure_file( - "${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_module.lua.in" - "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" - @ONLY) - -install(FILES "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" - RENAME "${DFTRACER_MODULEFILE_NAME}" - DESTINATION - "${DFTRACER_INSTALL_SYSCONFDIR}") - + "\n== End DFTRACER Configuration Summary ==\n") + + # Output to stdout + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${_str}") + set(_str) + + # ############################################################################## + # Write a basic modulefile + # ############################################################################## + set(DFTRACER_MODULEFILE_NAME "dftracer-${DFTRACER_PACKAGE_VERSION}.lua") + + # CACHE STRING + # "The name of the DFTRACER modulefile to install. Must end in .lua.") + if(NOT(DFTRACER_MODULEFILE_NAME MATCHES ".+\.lua")) + message(WARNING + "DFTRACER_MODULEFILE_NAME must have extension \".lua\". Appending.") + set(DFTRACER_MODULEFILE_NAME "${DFTRACER_MODULEFILE_NAME}.lua" + CACHE STRING "" FORCE) + endif() + + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_module.lua.in" + "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" + @ONLY) + + install(FILES "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" + RENAME "${DFTRACER_MODULEFILE_NAME}" + DESTINATION + "${DFTRACER_INSTALL_SYSCONFDIR}") endif() diff --git a/cmake/configure_files/dftracer_config.hpp.in b/cmake/configure_files/dftracer_config.hpp.in index 332787a8..31abb2a6 100644 --- a/cmake/configure_files/dftracer_config.hpp.in +++ b/cmake/configure_files/dftracer_config.hpp.in @@ -29,10 +29,13 @@ #cmakedefine DFTRACER_CMAKE_CXX_SHARED_LIBRARY_FLAGS "@CMAKE_CXX_SHARED_LIBRARY_FLAGS@" /* Macro flags */ -#cmakedefine DFTRACER_GNU_LINUX 1 -#cmakedefine DFTRACER_MPI_ENABLE 1 #cmakedefine DFTRACER_FTRACING_ENABLE 1 +#cmakedefine DFTRACER_GNU_LINUX 1 #cmakedefine DFTRACER_HWLOC_ENABLE 1 +#cmakedefine DFTRACER_MPI_ENABLE 1 +#cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" +#cmakedefine01 DFTRACER_WRITER_TYPE_CHROME +#cmakedefine01 DFTRACER_WRITER_TYPE_ZEROMQ //========================== // Common macro definitions diff --git a/cmake/configure_files/dftracer_config_dbg.hpp.in b/cmake/configure_files/dftracer_config_dbg.hpp.in index cd3a6ef6..686223f9 100644 --- a/cmake/configure_files/dftracer_config_dbg.hpp.in +++ b/cmake/configure_files/dftracer_config_dbg.hpp.in @@ -29,10 +29,13 @@ #cmakedefine DFTRACER_CMAKE_CXX_SHARED_LIBRARY_FLAGS "@CMAKE_CXX_SHARED_LIBRARY_FLAGS@" /* Macro flags */ -#cmakedefine DFTRACER_GNU_LINUX 1 -#cmakedefine DFTRACER_MPI_ENABLE 1 #cmakedefine DFTRACER_FTRACING_ENABLE 1 +#cmakedefine DFTRACER_GNU_LINUX 1 #cmakedefine DFTRACER_HWLOC_ENABLE 1 +#cmakedefine DFTRACER_MPI_ENABLE 1 +#cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" +#cmakedefine01 DFTRACER_WRITER_TYPE_CHROME +#cmakedefine01 DFTRACER_WRITER_TYPE_ZEROMQ #define DFTRACER_LOGGER_CPP_LOGGER 1 #define DFTRACER_LOGGER_LEVEL_TRACE 1 diff --git a/cmake/modules/dftracer-utils.cmake b/cmake/modules/dftracer-utils.cmake index 1e50a842..9a7b2ff6 100644 --- a/cmake/modules/dftracer-utils.cmake +++ b/cmake/modules/dftracer-utils.cmake @@ -1,14 +1,16 @@ -################################################################ +# ############################################################### # Utilities -################################################################ +# ############################################################### # A handy macro to add the current source directory to a local # filename. To be used for creating a list of sources. macro(set_full_path VAR) unset(__tmp_names) + foreach(filename ${ARGN}) list(APPEND __tmp_names "${CMAKE_CURRENT_SOURCE_DIR}/${filename}") endforeach() + set(${VAR} "${__tmp_names}") endmacro() @@ -16,37 +18,41 @@ endmacro() function(dftracer_get_space_string OUTPUT_VAR LENGTH) set(_curr_length 0) set(_out_str "") - while (${_curr_length} LESS ${LENGTH}) + + while(${_curr_length} LESS ${LENGTH}) string(APPEND _out_str " ") math(EXPR _curr_length "${_curr_length} + 1") - endwhile () + endwhile() set(${OUTPUT_VAR} "${_out_str}" PARENT_SCOPE) -endfunction () +endfunction() # This computes the maximum length of the things given in "ARGN" # interpreted as simple strings. macro(dftracer_get_max_str_length OUTPUT_VAR) set(${OUTPUT_VAR} 0) + foreach(var ${ARGN}) string(LENGTH "${var}" _var_length) - if (_var_length GREATER _max_length) + + if(_var_length GREATER _max_length) set(${OUTPUT_VAR} ${_var_length}) - endif () - endforeach () -endmacro () + endif() + endforeach() +endmacro() # Check to see if we are in a git repo find_program(__GIT_EXECUTABLE git) mark_as_advanced(__GIT_EXECUTABLE) -if (__GIT_EXECUTABLE) + +if(__GIT_EXECUTABLE) execute_process( COMMAND ${__GIT_EXECUTABLE} rev-parse --is-inside-work-tree WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" OUTPUT_VARIABLE __BUILDING_FROM_GIT_SOURCES OUTPUT_STRIP_TRAILING_WHITESPACE) - if (__BUILDING_FROM_GIT_SOURCES) + if(__BUILDING_FROM_GIT_SOURCES) # Get the git version so that we can embed it into the executable execute_process( COMMAND ${__GIT_EXECUTABLE} rev-parse --show-toplevel @@ -67,12 +73,12 @@ if (__GIT_EXECUTABLE) set(DFTRACER_GIT_VERSION "${__GIT_DESCRIBE_VERSION}" CACHE STRING "DFTRACER's version string as told by git.") - endif (__BUILDING_FROM_GIT_SOURCES) -endif (__GIT_EXECUTABLE) + endif(__BUILDING_FROM_GIT_SOURCES) +endif(__GIT_EXECUTABLE) -################################################################ +# ############################################################### # Configuration summary -################################################################ +# ############################################################### # This creates a formatted string that contains a list of variables, # one per line, with their values interpreted as TRUE or FALSE. The @@ -86,60 +92,63 @@ macro(append_str_tf STRING_VAR) string(LENGTH "${var}" _var_length) math(EXPR _num_spaces "${_max_length} - ${_var_length}") dftracer_get_space_string(_spaces ${_num_spaces}) - if (${var}) + + if(${var}) set(${var} "TRUE") string(APPEND ${STRING_VAR} " ${var}:" "${_spaces}" "TRUE\n") - else () + else() set(${var} "FALSE") string(APPEND ${STRING_VAR} " ${var}:" "${_spaces}" "FALSE\n") - endif () + endif() endforeach() -endmacro () +endmacro() -################################################################ +# ############################################################### # Install Public includes -################################################################ - +# ############################################################### function(dftracer_install_headers public_headers) - message("-- [${PROJECT_NAME}] " "installing headers ${public_headers}") - foreach (header ${public_headers}) - file(RELATIVE_PATH header_file_path "${PROJECT_SOURCE_DIR}/src" "${header}") - message("-- [${PROJECT_NAME}] " "installing header ${header_file_path}") - get_filename_component(header_directory_path "${header_file_path}" DIRECTORY) - install( - FILES ${header} - DESTINATION "include/${header_directory_path}" - ) - file(COPY ${header} - DESTINATION "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/${header_directory_path}") - endforeach () + message("-- [${PROJECT_NAME}] " "installing headers ${public_headers}") + + foreach(header ${public_headers}) + file(RELATIVE_PATH header_file_path "${PROJECT_SOURCE_DIR}/src" "${header}") + message("-- [${PROJECT_NAME}] " "installing header ${header_file_path}") + get_filename_component(header_directory_path "${header_file_path}" DIRECTORY) + install( + FILES ${header} + DESTINATION "include/${header_directory_path}" + ) + file(COPY ${header} + DESTINATION "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/${header_directory_path}") + endforeach() endfunction() -################################################################ +# ############################################################### # External Project configurations -################################################################ - +# ############################################################### include(ExternalProject) + function(install_external_project name version var_name url tag install_prefix configure_args) find_package(${name} ${version} QUIET) set(found_var ${name}_FOUND) - if (${${found_var}}) + + if(${${found_var}}) set(include_var ${${var_name}_INCLUDE_DIRS} ${${var_name}_INCLUDE_DIR}) set(library_var ${${var_name}_LIBRARY_DIRS}) include_directories(${include_var}) link_directories(${library_var}) message(STATUS "[${PROJECT_NAME}] found dependency already installed ${name} with include ${include_var} and library ${library_var}") else() + message(STATUS "[${PROJECT_NAME}] installing dependency ${name} with url ${url} and tag ${tag}") ExternalProject_Add( - ${name} - PREFIX ${CMAKE_BINARY_DIR} - GIT_REPOSITORY ${url} - GIT_TAG ${tag} - TIMEOUT 10 - CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${install_prefix}" ${configure_args} - BUILD_COMMAND make -j - INSTALL_COMMAND make install -j - LOG_DOWNLOAD ON + ${name} + PREFIX ${CMAKE_BINARY_DIR} + GIT_REPOSITORY ${url} + GIT_TAG ${tag} + TIMEOUT 10 + CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${install_prefix}" ${configure_args} + BUILD_COMMAND make -j + INSTALL_COMMAND make install -j + LOG_DOWNLOAD ON ) include_directories(${install_prefix}/include) link_directories(${install_prefix}/lib) @@ -148,10 +157,9 @@ function(install_external_project name version var_name url tag install_prefix c endif() endfunction() -################################################################ +# ############################################################### # Debug configurations -################################################################ - +# ############################################################### function(dftracer_debug_config target_list) foreach(target ${target_list}) target_compile_definitions(${target} PUBLIC DFTRACER_DEBUG) diff --git a/dependency/CMakeLists.txt b/dependency/CMakeLists.txt index 59c8b096..4a189262 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -6,9 +6,23 @@ add_dependencies(brahma cpp-logger) add_dependencies(brahma gotcha) find_package(yaml-cpp QUIET) install_external_project(yaml-cpp "" "YAML_CPP" https://github.com/jbeder/yaml-cpp.git yaml-cpp-0.6.3 ${CMAKE_INSTALL_PREFIX} "-DYAML_CPP_BUILD_TESTS=OFF;-DYAML_BUILD_SHARED_LIBS=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5") -if (NOT ${yaml-cpp_FOUND}) + +if(NOT ${yaml-cpp_FOUND}) add_dependencies(yaml-cpp brahma) add_dependencies(yaml-cpp gotcha) add_dependencies(yaml-cpp cpp-logger) endif() + install_external_project(pybind11 2.12.0 "pybind11" https://github.com/pybind/pybind11.git v2.12.0 ${CMAKE_INSTALL_PREFIX} "-DPYBIND11_TEST=OFF") + +# ZeroMQ setup if selected +if(DFTRACER_WRITER_TYPE STREQUAL "ZEROMQ") + # Install libzmq (C backend) + install_external_project(ZeroMQ 4.3.5 "ZeroMQ" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") + + # Install cppzmq (header-only C++ wrapper) + install_external_project(cppzmq 4.10.0 "cppzmq" https://github.com/zeromq/cppzmq.git v4.9.0 ${CMAKE_INSTALL_PREFIX} "-DCPPZMQ_BUILD_TESTS=OFF") + + add_dependencies(cppzmq ZeroMQ) + add_dependencies(ZeroMQ yaml-cpp) +endif() diff --git a/include/dftracer/core/constants.h b/include/dftracer/core/constants.h index b6b829ed..56c0fbc2 100644 --- a/include/dftracer/core/constants.h +++ b/include/dftracer/core/constants.h @@ -24,6 +24,7 @@ #define DFTRACER_BIND_SIGNALS "DFTRACER_BIND_SIGNALS" #define DFTRACER_WRITE_BUFFER_SIZE "DFTRACER_WRITE_BUFFER_SIZE" #define DFTRACER_ALL_FILES "all" +#define DFTRACER_WRITER_TYPE_ENV "DFTRACER_WRITER_TYPE" static const int EVENT_TYPE_SIZE = 128; static const unsigned int DFT_PATH_MAX = 1024 * 4; diff --git a/include/dftracer/core/typedef.h b/include/dftracer/core/typedef.h index f2af6f5d..17fe8e5c 100644 --- a/include/dftracer/core/typedef.h +++ b/include/dftracer/core/typedef.h @@ -4,10 +4,19 @@ #ifndef DFTRACER_TYPEDEF_H #define DFTRACER_TYPEDEF_H + +#ifdef __cplusplus +#include +#include +#include +using MetadataMap = std::unordered_map; +#endif + typedef unsigned long long int TimeResolution; typedef unsigned long int ThreadID; typedef unsigned long int ProcessID; typedef char* EventNameType; typedef const char* ConstEventNameType; typedef char* HashType; + #endif // DFTRACER_TYPEDEF_H diff --git a/include/dftracer/dftracer.h b/include/dftracer/dftracer.h index beba9de4..e3607c4a 100644 --- a/include/dftracer/dftracer.h +++ b/include/dftracer/dftracer.h @@ -43,7 +43,7 @@ class DFTracer { ConstEventNameType name; ConstEventNameType cat; TimeResolution start_time; - std::unordered_map *metadata; + MetadataMap *metadata; public: DFTracer(ConstEventNameType _name, ConstEventNameType _cat, @@ -67,8 +67,10 @@ class DFTracer { DFTracer profiler_dft_fn = \ DFTracer((char *)__FUNCTION__, CPP_LOG_CATEGORY, DF_DATA_EVENT); -#define DFTRACER_CPP_METADATA(name, key, value) \ - { DFTracer profiler_##name = DFTracer(key, value, DF_METADATA_EVENT); } +#define DFTRACER_CPP_METADATA(name, key, value) \ + { \ + DFTracer profiler_##name = DFTracer(key, value, DF_METADATA_EVENT); \ + } #define DFTRACER_CPP_REGION(name) \ DFTracer profiler_##name = DFTracer(#name, CPP_LOG_CATEGORY, DF_DATA_EVENT); diff --git a/src/dftracer/core/dftracer_main.cpp b/src/dftracer/core/dftracer_main.cpp index 1605eb51..b91d9c97 100644 --- a/src/dftracer/core/dftracer_main.cpp +++ b/src/dftracer/core/dftracer_main.cpp @@ -75,10 +75,11 @@ dftracer::DFTracerCore::DFTracerCore(ProfilerStage stage, ProfileType type, DFTRACER_LOG_DEBUG("DFTracerCore::DFTracerCore type %d", type); } -void dftracer::DFTracerCore::log( - ConstEventNameType event_name, ConstEventNameType category, - TimeResolution start_time, TimeResolution duration, - std::unordered_map *metadata) { +void dftracer::DFTracerCore::log(ConstEventNameType event_name, + ConstEventNameType category, + TimeResolution start_time, + TimeResolution duration, + MetadataMap *metadata) { DFTRACER_LOG_DEBUG("DFTracerCore::log", ""); if (this->is_initialized && conf->enable) { if (logger != nullptr) { @@ -197,14 +198,18 @@ void dftracer::DFTracerCore::initialize(bool _bind, const char *_log_file, } if (_process_id != nullptr && *_process_id != -1) { sprintf(exec_name, "%s-%lu", exec_name, df_getpid()); + DFTRACER_LOG_INFO("Extracted process_name %s", exec_name); } if (_log_file == nullptr) { - DFTRACER_LOG_INFO("Extracted process_name %s", exec_name); if (!conf->log_file.empty()) { DFTRACER_LOG_DEBUG("Conf has log file %s", conf->log_file.c_str()); - this->log_file = std::string(conf->log_file) + "-" + exec_name + "-" + - std::to_string(this->process_id) + "-" + - log_file_suffix + ".pfw"; + if (conf->writer_type == WriterType::CHROME) { + this->log_file = std::string(conf->log_file) + "-" + exec_name + + "-" + std::to_string(this->process_id) + "-" + + log_file_suffix + ".pfw"; + } else { + this->log_file = std::string(conf->log_file); + } } else { // GCOV_EXCL_START DFTRACER_LOG_ERROR(DFTRACER_UNDEFINED_LOG_FILE_MSG, ""); throw std::runtime_error(DFTRACER_UNDEFINED_LOG_FILE_CODE); diff --git a/src/dftracer/core/dftracer_main.h b/src/dftracer/core/dftracer_main.h index 8fc78820..629a53b7 100644 --- a/src/dftracer/core/dftracer_main.h +++ b/src/dftracer/core/dftracer_main.h @@ -54,7 +54,7 @@ class DFTracerCore { void log(ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, TimeResolution duration, - std::unordered_map *metadata); + MetadataMap *metadata); void log_metadata(ConstEventNameType key, ConstEventNameType value); diff --git a/src/dftracer/core/enumeration.h b/src/dftracer/core/enumeration.h index ae6b30f4..735dc146 100644 --- a/src/dftracer/core/enumeration.h +++ b/src/dftracer/core/enumeration.h @@ -4,7 +4,10 @@ #ifndef DFTRACER_ENUMERATION_H #define DFTRACER_ENUMERATION_H -enum WriterType : uint8_t { CHROME = 0 }; +enum WriterType : uint8_t { + CHROME = 0, + ZEROMQ = 1, +}; enum ProfilerStage : uint8_t { PROFILER_INIT = 0, PROFILER_FINI = 1, @@ -45,6 +48,16 @@ inline void convert(const std::string &s, cpplogger::LoggerType &type) { } } +inline void convert(const std::string &s, WriterType &type) { + if (s == "CHROME") { + type = WriterType::CHROME; + } else if (s == "ZEROMQ") { + type = WriterType::ZEROMQ; + } else { + type = WriterType::CHROME; // Default to CHROME + } +} + #define METADATA_NAME_PROCESS "PR" #define METADATA_NAME_PROCESS_NAME "process_name" #define METADATA_NAME_THREAD_NAME "thread_name" diff --git a/src/dftracer/df_logger.h b/src/dftracer/df_logger.h index b7993042..78619861 100644 --- a/src/dftracer/df_logger.h +++ b/src/dftracer/df_logger.h @@ -12,7 +12,11 @@ #include #include #include +#if DFTRACER_WRITER_TYPE_ZEROMQ +#include +#elif DFTRACER_WRITER_TYPE_CHROME #include +#endif #include #include #include @@ -37,6 +41,12 @@ typedef std::chrono::high_resolution_clock chrono; +#if DFTRACER_WRITER_TYPE_ZEROMQ +using DFTWriter = dftracer::ZeroMQWriter; +#elif DFTRACER_WRITER_TYPE_CHROME +using DFTWriter = dftracer::ChromeWriter; +#endif + class DFTLogger { private: std::shared_mutex level_mtx; @@ -44,7 +54,7 @@ class DFTLogger { bool throw_error; bool is_init, dftracer_tid; ProcessID process_id; - std::shared_ptr writer; + std::shared_ptr writer; uint32_t level; std::vector index_stack; std::unordered_map computed_hash; @@ -129,7 +139,7 @@ class DFTLogger { if (dftracer_tid) { tid = df_gettid(); } - this->writer = dftracer::Singleton::get_instance(); + this->writer = dftracer::Singleton::get_instance(); HashType hostname_hash; HashType cmd_hash; HashType exec_hash; @@ -148,28 +158,28 @@ class DFTLogger { current_index, thread_name, METADATA_NAME_THREAD_NAME, METADATA_NAME_THREAD_NAME, this->process_id, tid); this->exit_event(); - std::unordered_map *meta = nullptr; + MetadataMap *metadata = nullptr; if (include_metadata) { - meta = new std::unordered_map(); + metadata = new MetadataMap(); cmd_hash = hash_and_store(cmd.data(), METADATA_NAME_STRING_HASH); exec_hash = hash_and_store(exec_name.data(), METADATA_NAME_STRING_HASH); - meta->insert_or_assign("version", DFTRACER_GIT_VERSION); - meta->insert_or_assign("exec_hash", exec_hash); - meta->insert_or_assign("cmd_hash", cmd_hash); + metadata->insert_or_assign("version", DFTRACER_GIT_VERSION); + metadata->insert_or_assign("exec_hash", exec_hash); + metadata->insert_or_assign("cmd_hash", cmd_hash); time_t ltime; /* calendar time */ ltime = time(NULL); /* get current cal time */ char timestamp[1024]; auto size = sprintf(timestamp, "%s", asctime(localtime(<ime))); timestamp[size - 1] = '\0'; - meta->insert_or_assign("date", std::string(timestamp)); - meta->insert_or_assign("ppid", getppid()); + metadata->insert_or_assign("date", std::string(timestamp)); + metadata->insert_or_assign("ppid", getppid()); } this->enter_event(); - this->log("start", "dftracer", this->get_time(), 0, meta); + this->log("start", "dftracer", this->get_time(), 0, metadata); this->exit_event(); if (include_metadata) { - delete (meta); + delete (metadata); } if (enable_core_affinity) { #ifdef DFTRACER_HWLOC_ENABLE @@ -251,7 +261,7 @@ class DFTLogger { inline TimeResolution get_time() { DFTRACER_LOG_DEBUG("DFTLogger.get_time", ""); - struct timeval tv {}; + struct timeval tv{}; gettimeofday(&tv, NULL); TimeResolution t = 1000000 * tv.tv_sec + tv.tv_usec; return t; @@ -288,7 +298,7 @@ class DFTLogger { inline void log(ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, TimeResolution duration, - std::unordered_map *metadata) { + MetadataMap *metadata) { DFTRACER_LOG_DEBUG("DFTLogger.log", ""); ThreadID tid = 0; if (dftracer_tid) { @@ -397,10 +407,10 @@ class DFTLogger { inline void finalize() { DFTRACER_LOG_DEBUG("DFTLogger.finalize", ""); if (this->writer != nullptr) { - auto meta = std::unordered_map(); - meta.insert_or_assign("num_events", index.load()); + auto metadata = MetadataMap(); + metadata.insert_or_assign("num_events", index.load()); this->enter_event(); - this->log("end", "dftracer", this->get_time(), 0, &meta); + this->log("end", "dftracer", this->get_time(), 0, &metadata); this->exit_event(); writer->finalize(has_entry); DFTRACER_LOG_INFO("Released Logger", ""); @@ -426,31 +436,31 @@ class DFTLogger { DFT_LOGGER_UPDATE(value##_hash); \ } -#define DFT_LOGGER_START(entity) \ - DFTRACER_LOG_DEBUG("Calling function %s", __FUNCTION__); \ - HashType fhash = is_traced(entity, __FUNCTION__); \ - bool trace = fhash != NO_HASH_DEFAULT; \ - TimeResolution start_time = 0; \ - std::unordered_map *metadata = nullptr; \ - if (trace) { \ - if (this->logger->include_metadata) { \ - metadata = new std::unordered_map(); \ - DFT_LOGGER_UPDATE(fhash); \ - } \ - this->logger->enter_event(); \ - start_time = this->logger->get_time(); \ +#define DFT_LOGGER_START(entity) \ + DFTRACER_LOG_DEBUG("Calling function %s", __FUNCTION__); \ + HashType fhash = is_traced(entity, __FUNCTION__); \ + bool trace = fhash != NO_HASH_DEFAULT; \ + TimeResolution start_time = 0; \ + MetadataMap *metadata = nullptr; \ + if (trace) { \ + if (this->logger->include_metadata) { \ + metadata = new MetadataMap(); \ + DFT_LOGGER_UPDATE(fhash); \ + } \ + this->logger->enter_event(); \ + start_time = this->logger->get_time(); \ } -#define DFT_LOGGER_START_ALWAYS() \ - DFTRACER_LOG_DEBUG("Calling function %s", __FUNCTION__); \ - bool trace = true; \ - TimeResolution start_time = 0; \ - std::unordered_map *metadata = nullptr; \ - if (trace) { \ - if (this->logger->include_metadata) { \ - metadata = new std::unordered_map(); \ - } \ - this->logger->enter_event(); \ - start_time = this->logger->get_time(); \ +#define DFT_LOGGER_START_ALWAYS() \ + DFTRACER_LOG_DEBUG("Calling function %s", __FUNCTION__); \ + bool trace = true; \ + TimeResolution start_time = 0; \ + MetadataMap *metadata = nullptr; \ + if (trace) { \ + if (this->logger->include_metadata) { \ + metadata = new MetadataMap(); \ + } \ + this->logger->enter_event(); \ + start_time = this->logger->get_time(); \ } #define DFT_LOGGER_END() \ if (trace) { \ diff --git a/src/dftracer/dftracer.cpp b/src/dftracer/dftracer.cpp index 103327de..8e7956d7 100644 --- a/src/dftracer/dftracer.cpp +++ b/src/dftracer/dftracer.cpp @@ -4,6 +4,7 @@ #include #include +#include #include DFTracer::DFTracer(ConstEventNameType _name, ConstEventNameType _cat, @@ -18,8 +19,9 @@ DFTracer::DFTracer(ConstEventNameType _name, ConstEventNameType _cat, ProfileType::PROFILER_CPP_APP); if (dftracer_core != nullptr) { if (event_type == DF_DATA_EVENT) { - if (dftracer_core->include_metadata) - metadata = new std::unordered_map(); + if (dftracer_core->include_metadata) { + metadata = new MetadataMap(); + } start_time = dftracer_core->get_time(); } } diff --git a/src/dftracer/utils/configuration_manager.cpp b/src/dftracer/utils/configuration_manager.cpp index 00b0ab5a..c209666b 100644 --- a/src/dftracer/utils/configuration_manager.cpp +++ b/src/dftracer/utils/configuration_manager.cpp @@ -57,7 +57,8 @@ dftracer::ConfigurationManager::ConfigurationManager() tids(true), bind_signals(false), throw_error(false), - write_buffer_size(10) { + write_buffer_size(10), + writer_type(WriterType::CHROME) { const char *env_conf = getenv(DFTRACER_CONFIGURATION); YAML::Node config; if (env_conf != nullptr) { @@ -290,6 +291,12 @@ dftracer::ConfigurationManager::ConfigurationManager() } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.write_buffer_size %d", this->write_buffer_size); + const char *writer_type = getenv(DFTRACER_WRITER_TYPE_ENV); + if (writer_type != nullptr) { + convert(writer_type, this->writer_type); + } + DFTRACER_LOG_DEBUG("ENV ConfigurationManager.writer_type %d", + this->writer_type); } DFTRACER_LOG_DEBUG("ENV ConfigurationManager finished", ""); } diff --git a/src/dftracer/utils/configuration_manager.h b/src/dftracer/utils/configuration_manager.h index a2c0f8c5..589c9c55 100644 --- a/src/dftracer/utils/configuration_manager.h +++ b/src/dftracer/utils/configuration_manager.h @@ -28,6 +28,7 @@ class ConfigurationManager { bool bind_signals; bool throw_error; size_t write_buffer_size; + WriterType writer_type; ConfigurationManager(); void finalize() {} }; diff --git a/src/dftracer/writer/chrome_writer.cpp b/src/dftracer/writer/chrome_writer.cpp index f6c0581d..45d02e37 100644 --- a/src/dftracer/writer/chrome_writer.cpp +++ b/src/dftracer/writer/chrome_writer.cpp @@ -21,8 +21,10 @@ std::shared_ptr template <> bool dftracer::Singleton::stop_creating_instances = false; -void dftracer::ChromeWriter::initialize(char *filename, bool throw_error, - HashType hostname_hash) { + +namespace dftracer { +void ChromeWriter::initialize(char *filename, bool throw_error, + HashType hostname_hash) { this->hostname_hash = hostname_hash; this->throw_error = throw_error; this->filename = filename; @@ -40,45 +42,44 @@ void dftracer::ChromeWriter::initialize(char *filename, bool throw_error, DFTRACER_LOG_DEBUG("ChromeWriter.initialize %s", this->filename.c_str()); } -void dftracer::ChromeWriter::log( - int index, ConstEventNameType event_name, ConstEventNameType category, - TimeResolution start_time, TimeResolution duration, - std::unordered_map *metadata, ProcessID process_id, - ThreadID thread_id) { +void ChromeWriter::log(int index, ConstEventNameType event_name, + ConstEventNameType category, TimeResolution start_time, + TimeResolution duration, MetadataMap *metadata, + ProcessID process_id, ThreadID thread_id) { DFTRACER_LOG_DEBUG("ChromeWriter.log", ""); if (fh != nullptr) { - convert_json(index, event_name, category, start_time, duration, metadata, - process_id, thread_id); - write_buffer_op(); + write_event_json_to_buffer(index, event_name, category, start_time, + duration, metadata, process_id, thread_id); + flush_buffer_to_file(false); } else { DFTRACER_LOG_ERROR("ChromeWriter.log invalid", ""); } is_first_write = false; } -void dftracer::ChromeWriter::log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, - ConstEventNameType ph, - ProcessID process_id, ThreadID tid, - bool is_string) { +void ChromeWriter::log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, ConstEventNameType ph, + ProcessID process_id, ThreadID tid, + bool is_string) { DFTRACER_LOG_DEBUG("ChromeWriter.log_metadata", ""); if (fh != nullptr) { - convert_json_metadata(index, name, value, ph, process_id, tid, is_string); - write_buffer_op(); + write_metadata_json_to_buffer(index, name, value, ph, process_id, tid, + is_string); + flush_buffer_to_file(false); } else { DFTRACER_LOG_ERROR("ChromeWriter.log_metadata invalid", ""); } is_first_write = false; } -void dftracer::ChromeWriter::finalize(bool has_entry) { +void ChromeWriter::finalize(bool has_entry) { if (this->init) { DFTRACER_LOG_DEBUG("ChromeWriter.finalize", ""); if (fh != nullptr) { DFTRACER_LOG_INFO("Profiler finalizing writer %s", filename.c_str()); - write_buffer_op(true); + flush_buffer_to_file(true); fflush(fh); int status = fclose(fh); if (status != 0) { @@ -151,116 +152,52 @@ void dftracer::ChromeWriter::finalize(bool has_entry) { } } -void dftracer::ChromeWriter::convert_json( +void ChromeWriter::write_event_json_to_buffer( int index, ConstEventNameType event_name, ConstEventNameType category, - TimeResolution start_time, TimeResolution duration, - std::unordered_map *metadata, ProcessID process_id, - ThreadID thread_id) { + TimeResolution start_time, TimeResolution duration, MetadataMap *metadata, + ProcessID process_id, ThreadID thread_id) { size_t previous_index = 0; (void)previous_index; + char is_first_char[3] = " "; - if (!is_first_write) is_first_char[0] = '\0'; - if (include_metadata && metadata != nullptr) { - std::stringstream all_stream; - bool has_meta = false; - std::stringstream meta_stream; - auto meta_size = metadata->size(); - long unsigned int i = 0; - for (auto item : *metadata) { - has_meta = true; - if (item.second.type() == typeid(unsigned int)) { - meta_stream << "\"" << item.first - << "\":" << std::any_cast(item.second); - if (i < meta_size - 1) meta_stream << ","; - } else if (item.second.type() == typeid(int)) { - meta_stream << "\"" << item.first - << "\":" << std::any_cast(item.second); - if (i < meta_size - 1) meta_stream << ","; - } else if (item.second.type() == typeid(const char *)) { - meta_stream << "\"" << item.first << "\":\"" - << std::any_cast(item.second) << "\""; - if (i < meta_size - 1) meta_stream << ","; - } else if (item.second.type() == typeid(std::string)) { - meta_stream << "\"" << item.first << "\":\"" - << std::any_cast(item.second) << "\""; - if (i < meta_size - 1) meta_stream << ","; - } else if (item.second.type() == typeid(size_t)) { - meta_stream << "\"" << item.first - << "\":" << std::any_cast(item.second) << ""; - if (i < meta_size - 1) meta_stream << ","; - } else if (item.second.type() == typeid(uint16_t)) { - meta_stream << "\"" << item.first - << "\":" << std::any_cast(item.second) << ""; - if (i < meta_size - 1) meta_stream << ","; + if (!is_first_write) { + is_first_char[0] = '\0'; + } - } else if (item.second.type() == typeid(HashType)) { - meta_stream << "\"" << item.first << "\":\"" - << std::any_cast(item.second) << "\""; - if (i < meta_size - 1) meta_stream << ","; + std::string metadata_json_string; + if (include_metadata) { + metadata_json_string = convert_metadata_to_json_string(metadata); + } - } else if (item.second.type() == typeid(long)) { - meta_stream << "\"" << item.first - << "\":" << std::any_cast(item.second) << ""; - if (i < meta_size - 1) meta_stream << ","; - } else if (item.second.type() == typeid(ssize_t)) { - meta_stream << "\"" << item.first - << "\":" << std::any_cast(item.second) << ""; - if (i < meta_size - 1) meta_stream << ","; - } else if (item.second.type() == typeid(off_t)) { - meta_stream << "\"" << item.first - << "\":" << std::any_cast(item.second) << ""; - if (i < meta_size - 1) meta_stream << ","; - } else if (item.second.type() == typeid(off64_t)) { - meta_stream << "\"" << item.first - << "\":" << std::any_cast(item.second) << ""; - if (i < meta_size - 1) meta_stream << ","; - } else { - DFTRACER_LOG_INFO("No conversion for type %s", item.first.c_str()); - } - i++; - } - if (has_meta) { - all_stream << "," << meta_stream.str(); - } - { - std::unique_lock lock(mtx); - previous_index = current_index; - auto written_size = sprintf( - buffer.data() + current_index, - R"(%s{"id":%d,"name":"%s","cat":"%s","pid":%lu,"tid":%lu,"ts":%llu,"dur":%llu,"ph":"X","args":{"hhash":"%s"%s}})", - is_first_char, index, event_name, category, process_id, thread_id, - start_time, duration, this->hostname_hash, all_stream.str().c_str()); - current_index += written_size; - buffer[current_index] = '\n'; - current_index++; - } - } else { - { - std::unique_lock lock(mtx); - previous_index = current_index; - auto written_size = sprintf( - buffer.data() + current_index, - R"(%s{"id":%d,"name":"%s","cat":"%s","pid":%lu,"tid":%lu,"ts":%llu,"dur":%llu,"ph":"X"})", - is_first_char, index, event_name, category, process_id, thread_id, - start_time, duration); - current_index += written_size; - buffer[current_index] = '\n'; - current_index++; - } + { + std::unique_lock lock(mtx); + previous_index = current_index; + auto written_size = sprintf( + buffer.data() + current_index, + R"(%s{"id":%d,"name":"%s","cat":"%s","pid":%lu,"tid":%lu,"ts":%llu,"dur":%llu,"ph":"X"%s})", + is_first_char, index, event_name, category, process_id, thread_id, + start_time, duration, metadata_json_string.c_str()); + current_index += written_size; + buffer[current_index] = '\n'; + current_index++; } - DFTRACER_LOG_DEBUG("ChromeWriter.convert_json %s on %s", + + DFTRACER_LOG_DEBUG("ChromeWriter.write_event_json_to_buffer %s on %s", buffer.data() + previous_index, this->filename.c_str()); } -void dftracer::ChromeWriter::convert_json_metadata( +void ChromeWriter::write_metadata_json_to_buffer( int index, ConstEventNameType name, ConstEventNameType value, ConstEventNameType ph, ProcessID process_id, ThreadID thread_id, bool is_string) { size_t previous_index = 0; - (void)previous_index; + char is_first_char[3] = " "; - if (!is_first_write) is_first_char[0] = '\0'; + if (!is_first_write) { + is_first_char[0] = '\0'; + } + { std::unique_lock lock(mtx); previous_index = current_index; @@ -283,6 +220,8 @@ void dftracer::ChromeWriter::convert_json_metadata( current_index++; } - DFTRACER_LOG_DEBUG("ChromeWriter.convert_json_metadata %s on %s", + DFTRACER_LOG_DEBUG("ChromeWriter.write_metadata_json_to_buffer %s on %s", buffer.data() + previous_index, this->filename.c_str()); } + +} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/writer/chrome_writer.h b/src/dftracer/writer/chrome_writer.h index 45875a47..4b8d77d9 100644 --- a/src/dftracer/writer/chrome_writer.h +++ b/src/dftracer/writer/chrome_writer.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -20,41 +21,20 @@ #include #include #include -namespace dftracer { -class ChromeWriter { - private: - std::unordered_map metadata; - std::mutex mtx; +namespace dftracer { +class ChromeWriter : public WriterBase { protected: - bool throw_error; - std::string filename; - - private: - bool include_metadata, enable_compression; - bool init; - bool enable_core_affinity; - - FILE *fh; - HashType hostname_hash; static const int MAX_LINE_SIZE = 16 * 1024L; + bool enable_compression; + bool is_first_write = true; + FILE *fh; + size_t current_index = 0; size_t write_buffer_size; - - size_t current_index; std::vector buffer; - void convert_json(int index, ConstEventNameType event_name, - ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, - std::unordered_map *metadata, - ProcessID process_id, ThreadID thread_id); - - void convert_json_metadata(int index, ConstEventNameType name, - ConstEventNameType value, ConstEventNameType ph, - ProcessID process_id, ThreadID thread_id, - bool is_string); + std::mutex mtx; - bool is_first_write; - inline size_t write_buffer_op(bool force = false) { + inline size_t flush_buffer_to_file(bool force = false) { std::unique_lock lock(mtx); if (current_index == 0 || (!force && current_index < write_buffer_size)) return 0; @@ -65,32 +45,25 @@ class ChromeWriter { written_elements = fwrite(buffer.data(), current_index, sizeof(char), fh); current_index = 0; funlockfile(fh); - if (written_elements != 1) { // GCOVR_EXCL_START + if (written_elements != 1) { DFTRACER_LOG_ERROR( "unable to log write only %ld of %d trying to write %ld with error " "code " "%d", written_elements, 1, current_index, errno); - } // GCOVR_EXCL_STOP + } return written_elements; } public: ChromeWriter() - : metadata(), - throw_error(false), - filename(), - include_metadata(false), - enable_compression(false), - init(false), - enable_core_affinity(false), + : enable_compression(false), + is_first_write(false), fh(nullptr), - current_index(0), - is_first_write(true) { + write_buffer_size(0) { DFTRACER_LOG_DEBUG("ChromeWriter.ChromeWriter", ""); auto conf = dftracer::Singleton::get_instance(); - include_metadata = conf->metadata; enable_core_affinity = conf->core_affinity; enable_compression = conf->compression; write_buffer_size = conf->write_buffer_size; @@ -102,18 +75,27 @@ class ChromeWriter { } ~ChromeWriter() { DFTRACER_LOG_DEBUG("Destructing ChromeWriter", ""); } void initialize(char *filename, bool throw_error, HashType hostname_hash); - void log(int index, ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, - std::unordered_map *metadata, - ProcessID process_id, ThreadID tid); - + TimeResolution duration, MetadataMap *metadata, ProcessID process_id, + ThreadID tid); void log_metadata(int index, ConstEventNameType name, ConstEventNameType value, ConstEventNameType ph, ProcessID process_id, ThreadID tid, bool is_string = true); - void finalize(bool has_entry); + + private: + void write_event_json_to_buffer(int index, ConstEventNameType event_name, + ConstEventNameType category, + TimeResolution start_time, + TimeResolution duration, + MetadataMap *metadata, ProcessID process_id, + ThreadID thread_id); + void write_metadata_json_to_buffer(int index, ConstEventNameType name, + ConstEventNameType value, + ConstEventNameType ph, + ProcessID process_id, ThreadID thread_id, + bool is_string); }; } // namespace dftracer diff --git a/src/dftracer/writer/writer_base.cpp b/src/dftracer/writer/writer_base.cpp new file mode 100644 index 00000000..06ae9444 --- /dev/null +++ b/src/dftracer/writer/writer_base.cpp @@ -0,0 +1,96 @@ +#include +#include + +#include +#include +#include + +namespace dftracer { + +std::string WriterBase::convert_event_to_json_string( + int index, ConstEventNameType event_name, ConstEventNameType category, + TimeResolution start_time, TimeResolution duration, MetadataMap *metadata, + ProcessID process_id, ThreadID thread_id) { + std::string metadata_json_string; + if (include_metadata) { + metadata_json_string = convert_metadata_to_json_string(metadata); + } + std::stringstream json_stream; + json_stream << "{"; + json_stream << R"("id":)" << index; + json_stream << R"(,"name":")" << event_name; + json_stream << R"(","cat":")" << category; + json_stream << R"(","pid":)" << process_id; + json_stream << R"(,"tid":)" << thread_id; + json_stream << R"(,"ts":)" << start_time; + json_stream << R"(,"dur":)" << duration; + json_stream << R"(,"ph":"X")" << metadata_json_string; + json_stream << "}"; + DFTRACER_LOG_DEBUG("WriterBase.convert_event_to_json_string %s on %s", + json_stream.str().c_str(), this->filename.c_str()); + return json_stream.str(); +} + +std::string WriterBase::convert_metadata_event_to_json_string( + int index, ConstEventNameType name, ConstEventNameType value, + ConstEventNameType ph, ProcessID process_id, ThreadID thread_id) { + MetadataMap metadata; + metadata["name"] = name; + metadata["value"] = value; + std::string metadata_json_string = convert_metadata_to_json_string(&metadata); + std::stringstream json_stream; + json_stream << "{"; + json_stream << R"("id":)" << index; + json_stream << R"(,"name":")" << ph; + json_stream << R"(","cat":")" << "dftracer"; + json_stream << R"(","pid":)" << process_id; + json_stream << R"(,"tid":)" << thread_id; + json_stream << R"(,"ph":"M")" << metadata_json_string; + json_stream << "}"; + DFTRACER_LOG_DEBUG( + "WriterBase.convert_metadata_event_to_json_string %s on %s", + json_stream.str().c_str(), this->filename.c_str()); + return json_stream.str(); +} + +std::string WriterBase::convert_metadata_to_json_string(MetadataMap *metadata) { + std::stringstream metadata_stream; + if (metadata != nullptr && !metadata->empty()) { + metadata_stream << R"(,"args":{"hhash":")" << this->hostname_hash << "\""; + for (const auto &item : *metadata) { + metadata_stream << ","; + metadata_stream << "\"" << item.first << "\":"; + if (item.second.type() == typeid(unsigned int)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(int)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(const char *)) { + metadata_stream << "\"" << std::any_cast(item.second) + << "\""; + } else if (item.second.type() == typeid(std::string)) { + metadata_stream << "\"" << std::any_cast(item.second) + << "\""; + } else if (item.second.type() == typeid(size_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(uint16_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(HashType)) { + metadata_stream << "\"" << std::any_cast(item.second) << "\""; + } else if (item.second.type() == typeid(long)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(ssize_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(off_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(off64_t)) { + metadata_stream << std::any_cast(item.second); + } else { + DFTRACER_LOG_INFO("No conversion for type %s", item.first.c_str()); + } + } + metadata_stream << "}"; + } + return metadata_stream.str(); +} + +} // namespace dftracer diff --git a/src/dftracer/writer/writer_base.h b/src/dftracer/writer/writer_base.h new file mode 100644 index 00000000..a5ef25e2 --- /dev/null +++ b/src/dftracer/writer/writer_base.h @@ -0,0 +1,47 @@ +#ifndef DFTRACER_WRITER_BASE_H +#define DFTRACER_WRITER_BASE_H + +#include + +#include +#include +#include +#include +#include + +namespace dftracer { +class WriterBase { + protected: + std::string filename; + HashType hostname_hash; + bool enable_core_affinity = false; + bool include_metadata = false; + bool init = false; + bool throw_error = false; + + std::string convert_event_to_json_string( + int index, ConstEventNameType event_name, ConstEventNameType category, + TimeResolution start_time, TimeResolution duration, MetadataMap *metadata, + ProcessID process_id, ThreadID thread_id); + std::string convert_metadata_event_to_json_string( + int index, ConstEventNameType name, ConstEventNameType value, + ConstEventNameType ph, ProcessID process_id, ThreadID thread_id); + std::string convert_metadata_to_json_string(MetadataMap *metadata); + + public: + virtual ~WriterBase() = default; + virtual void initialize(char *filename, bool throw_error, + HashType hostname_hash) = 0; + virtual void log(int index, ConstEventNameType event_name, + ConstEventNameType category, TimeResolution start_time, + TimeResolution duration, MetadataMap *metadata, + ProcessID process_id, ThreadID tid) = 0; + virtual void log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, ConstEventNameType ph, + ProcessID process_id, ThreadID tid, + bool is_string = true) = 0; + virtual void finalize(bool has_entry) = 0; +}; +} // namespace dftracer + +#endif // DFTRACER_WRITER_BASE_H \ No newline at end of file diff --git a/src/dftracer/writer/zeromq_writer.cpp b/src/dftracer/writer/zeromq_writer.cpp new file mode 100644 index 00000000..5b211e93 --- /dev/null +++ b/src/dftracer/writer/zeromq_writer.cpp @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +template <> +std::shared_ptr + dftracer::Singleton::instance = nullptr; +template <> +bool dftracer::Singleton::stop_creating_instances = + false; + +namespace dftracer { +void ZeroMQWriter::initialize(char *filename, bool throw_error, + HashType hostname_hash) { + this->hostname_hash = hostname_hash; + this->throw_error = throw_error; + this->filename = filename; + context = std::make_unique(1); + socket = std::make_unique(*context, zmq::socket_type::push); + if (!socket) { + DFTRACER_LOG_ERROR("unable to create ZeroMQ socket %s", filename); + } + socket->connect(filename); + this->init = true; + DFTRACER_LOG_INFO("created ZeroMQ socket and connected to %s", filename); +} + +void ZeroMQWriter::log(int index, ConstEventNameType event_name, + ConstEventNameType category, TimeResolution start_time, + TimeResolution duration, MetadataMap *metadata, + ProcessID process_id, ThreadID thread_id) { + DFTRACER_LOG_DEBUG("ZeroMQWriter.log", ""); + + if (init) { + auto event_json = + convert_event_to_json_string(index, event_name, category, start_time, + duration, metadata, process_id, thread_id); + zmq::message_t message(event_json.data(), event_json.size()); + socket->send(message, zmq::send_flags::dontwait); + } else { + DFTRACER_LOG_ERROR("ZeroMQWriter.log invalid", ""); + } +} + +void ZeroMQWriter::log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, ConstEventNameType ph, + ProcessID process_id, ThreadID thread_id, + bool is_string) { + DFTRACER_LOG_DEBUG("ZeroMQWriter.log_metadata", ""); + if (init) { + auto event_json = convert_metadata_event_to_json_string( + index, name, value, ph, process_id, thread_id); + zmq::message_t message(event_json.data(), event_json.size()); + socket->send(message, zmq::send_flags::dontwait); + } else { + DFTRACER_LOG_ERROR("ZeroMQWriter.log_metadata invalid", ""); + } +} + +void ZeroMQWriter::finalize(bool has_entry) { + DFTRACER_LOG_DEBUG("ZeroMQWriter.finalize", ""); + if (this->init) { + socket->close(); + context->close(); + this->init = false; + } else { + DFTRACER_LOG_ERROR("ZeroMQWriter.finalize invalid", ""); + } +} + +} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/writer/zeromq_writer.h b/src/dftracer/writer/zeromq_writer.h new file mode 100644 index 00000000..df16e874 --- /dev/null +++ b/src/dftracer/writer/zeromq_writer.h @@ -0,0 +1,49 @@ +#ifndef DFTRACER_ZEROMQ_WRITER_H +#define DFTRACER_ZEROMQ_WRITER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dftracer { +class ZeroMQWriter : public WriterBase { + private: + std::unique_ptr context; + std::unique_ptr socket; + + public: + ZeroMQWriter() { + DFTRACER_LOG_DEBUG("ZeroMQWriter.ZeroMQWriter", ""); + auto conf = + dftracer::Singleton::get_instance(); + include_metadata = conf->metadata; + enable_core_affinity = conf->core_affinity; + } + ~ZeroMQWriter() { DFTRACER_LOG_DEBUG("Destructing ZeroMQWriter", ""); } + void initialize(char *filename, bool throw_error, HashType hostname_hash); + void log(int index, ConstEventNameType event_name, + ConstEventNameType category, TimeResolution start_time, + TimeResolution duration, MetadataMap *metadata, ProcessID process_id, + ThreadID tid); + void log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, ConstEventNameType ph, + ProcessID process_id, ThreadID tid, bool is_string = true); + void finalize(bool has_entry); +}; +} // namespace dftracer + +#endif // DFTRACER_ZEROMQ_WRITER_H From 250907b78798e37fa5ee58f0e8388195cf101906 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Sun, 15 Jun 2025 06:58:52 -0700 Subject: [PATCH 02/33] Add ChromeWriter performance test --- test/CMakeLists.txt | 44 ++++++++++---- test/writer/test_chrome_writer.cpp | 97 ++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 test/writer/test_chrome_writer.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8d4e4dff..0ec879fa 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,13 +1,26 @@ set_property(GLOBAL PROPERTY COVERAGE_FILES "") include_directories(${DFTRACER_PROJECT_DIR}/include) -function(df_add_test) - add_test(${ARGV}) - set_tests_properties(${ARGV0} PROPERTIES - ENVIRONMENT "LLVM_PROFILE_FILE=${ARGV0}.profraw") + +function(df_add_test test_fixture_name) # First argument is the test name + set(executable_path ${ARGV1}) # Second argument is the executable + set(executable_args "") + + if(ARGC GREATER 2) # Remaining arguments are for the executable + list(SUBLIST ARGV 2 -1 executable_args_list) + set(executable_args ${executable_args_list}) + endif() + + add_test(NAME ${test_fixture_name} COMMAND ${executable_path} ${executable_args}) + + set_tests_properties(${test_fixture_name} PROPERTIES # Use test_fixture_name + ENVIRONMENT "LLVM_PROFILE_FILE=${test_fixture_name}.profraw") # Use test_fixture_name get_property(OLD_CF GLOBAL PROPERTY COVERAGE_FILES) - set(NEW_CF ${OLD_CF} ${CMAKE_CURRENT_BINARY_DIR}/${ARGV0}.profraw) + + # Use test_fixture_name for constructing the profraw path + set(NEW_CF ${OLD_CF} ${CMAKE_CURRENT_BINARY_DIR}/${test_fixture_name}.profraw) set_property(GLOBAL PROPERTY COVERAGE_FILES ${NEW_CF}) endfunction() + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(test_cpp cpp/test.cpp) @@ -23,6 +36,8 @@ target_link_libraries(test_c ${PROJECT_NAME}_dbg testlib) add_dependencies(test_c ${PROJECT_NAME}_dbg) add_dependencies(test_c ${PROJECT_NAME}_preload_dbg) +add_executable(test_chrome_writer writer/test_chrome_writer.cpp) +target_link_libraries(test_chrome_writer PRIVATE ${PROJECT_NAME}_dbg) function(set_common_properties test_name) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=DEBUG) @@ -34,8 +49,15 @@ function(set_common_properties test_name) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_BIND_SIGNALS=0) endfunction() + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data) +set(chrome_writer_test_name ChromeWriterPerformanceTest) +set(perf_output_file ${CMAKE_CURRENT_BINARY_DIR}/${chrome_writer_test_name}_output.jsonl) +df_add_test(${chrome_writer_test_name} $ ${perf_output_file}) +set_common_properties(${chrome_writer_test_name}) +set_property(TEST ${chrome_writer_test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=ERROR) + set(test_name test_cpp_basic_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data) set_common_properties(${test_name}) @@ -57,14 +79,11 @@ set(test_name test_cpp_basic_app_only_yaml) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ./data 1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_CONFIGURATION=${CMAKE_CURRENT_SOURCE_DIR}/yaml/conf.yaml) - - set(test_name test_cpp_basic_app_compress_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data 1) set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_TRACE_COMPRESSION=1) - set(test_name test_cpp_basic_app_disable_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data 1) set_common_properties(${test_name}) @@ -140,8 +159,8 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=PRELOAD set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) set(TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/util.h) -if (ENABLE_DLIO_BENCHMARK_TESTS) +if(ENABLE_DLIO_BENCHMARK_TESTS) set(test_name python_test_py_disable_only) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/python_test.py --format=npz) set_common_properties(${test_name}) @@ -179,9 +198,10 @@ if (ENABLE_DLIO_BENCHMARK_TESTS) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=all) add_subdirectory(dlio_benchmark) -endif () +endif() -if (ENABLE_PAPER_TESTS) +if(ENABLE_PAPER_TESTS) add_subdirectory(paper) -endif () +endif() + add_subdirectory(dfanalyzer) diff --git a/test/writer/test_chrome_writer.cpp b/test/writer/test_chrome_writer.cpp new file mode 100644 index 00000000..19cf513b --- /dev/null +++ b/test/writer/test_chrome_writer.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dftracer/core/typedef.h" +#include "dftracer/writer/chrome_writer.h" + +static dftracer::ChromeWriter writer_instance; + +int main(int argc, char** argv) { + std::string tmp_output_file = "perf_chrome_trace.json"; + int num_events_to_log = 10000; + + if (argc > 1) { + tmp_output_file = argv[1]; + } + if (argc > 2) { + try { + num_events_to_log = std::stoi(argv[2]); + } catch (const std::invalid_argument& ia) { + std::cerr << "Invalid argument for number of events: " << argv[2] + << std::endl; + return EXIT_FAILURE; + } catch (const std::out_of_range& oor) { + std::cerr << "Number of events out of range: " << argv[2] << std::endl; + return EXIT_FAILURE; + } + } + + writer_instance.initialize(const_cast(tmp_output_file.c_str()), false, + const_cast("test_host_hash_perf")); + + auto start_time = std::chrono::high_resolution_clock::now(); + + for (int i = 0; i < num_events_to_log; ++i) { + std::unordered_map m; + m["iteration"] = i; + m["detail"] = std::string( + "performance_test_event_detail_long_enough_to_test_string_handling"); + m["another_key"] = std::string("another_value_for_metadata_map_testing"); + writer_instance.log( + i, ("event_name_perf_" + std::to_string(i)).c_str(), "perf_category", + std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()) + .count(), + 100 + (i % 75), &m, 12345, 54321); + if (i % 1000 == 0) { + writer_instance.log_metadata(i, "metadata_event_name", + "metadata_event_value", "process_name_perf", + 12345, 54321); + } + } + + writer_instance.finalize(true); + + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration_ms = std::chrono::duration_cast( + end_time - start_time) + .count(); + double duration_s = static_cast(duration_ms) / 1000.0; + + std::cout << std::endl; + std::cout << "[ PERFORMANCE ] ChromeWriter: Logged " << num_events_to_log + << " main events (plus some metadata events) in " << duration_s + << " seconds." << std::endl; + if (duration_s > 0) { + std::cout << "[ PERFORMANCE ] ChromeWriter: Throughput: " + << static_cast(num_events_to_log) / duration_s + << " main events/sec." << std::endl; + } else { + std::cout << "[ PERFORMANCE ] ChromeWriter: Duration too short to " + "calculate throughput accurately." + << std::endl; + } + + std::ifstream file(tmp_output_file); + if (!file.good()) { + std::cerr << "Error: Output file was not created: " << tmp_output_file + << std::endl; + return EXIT_FAILURE; + } + file.seekg(0, std::ios::end); + if (file.tellg() <= 0) { + std::cerr << "Error: Output file is empty: " << tmp_output_file + << std::endl; + file.close(); + return EXIT_FAILURE; + } + file.close(); + + return EXIT_SUCCESS; +} \ No newline at end of file From c7d308010d6cab1711937ac56664fb82b16beb95 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Sun, 15 Jun 2025 07:02:22 -0700 Subject: [PATCH 03/33] Refactor CMake utility functions for consistency and readability --- cmake/modules/dftracer-utils.cmake | 111 ++++++++++++++++------------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/cmake/modules/dftracer-utils.cmake b/cmake/modules/dftracer-utils.cmake index 1e50a842..502c5247 100644 --- a/cmake/modules/dftracer-utils.cmake +++ b/cmake/modules/dftracer-utils.cmake @@ -1,14 +1,16 @@ -################################################################ +# ############################################################### # Utilities -################################################################ +# ############################################################### # A handy macro to add the current source directory to a local # filename. To be used for creating a list of sources. macro(set_full_path VAR) unset(__tmp_names) + foreach(filename ${ARGN}) list(APPEND __tmp_names "${CMAKE_CURRENT_SOURCE_DIR}/${filename}") endforeach() + set(${VAR} "${__tmp_names}") endmacro() @@ -16,37 +18,41 @@ endmacro() function(dftracer_get_space_string OUTPUT_VAR LENGTH) set(_curr_length 0) set(_out_str "") - while (${_curr_length} LESS ${LENGTH}) + + while(${_curr_length} LESS ${LENGTH}) string(APPEND _out_str " ") math(EXPR _curr_length "${_curr_length} + 1") - endwhile () + endwhile() set(${OUTPUT_VAR} "${_out_str}" PARENT_SCOPE) -endfunction () +endfunction() # This computes the maximum length of the things given in "ARGN" # interpreted as simple strings. macro(dftracer_get_max_str_length OUTPUT_VAR) set(${OUTPUT_VAR} 0) + foreach(var ${ARGN}) string(LENGTH "${var}" _var_length) - if (_var_length GREATER _max_length) + + if(_var_length GREATER _max_length) set(${OUTPUT_VAR} ${_var_length}) - endif () - endforeach () -endmacro () + endif() + endforeach() +endmacro() # Check to see if we are in a git repo find_program(__GIT_EXECUTABLE git) mark_as_advanced(__GIT_EXECUTABLE) -if (__GIT_EXECUTABLE) + +if(__GIT_EXECUTABLE) execute_process( COMMAND ${__GIT_EXECUTABLE} rev-parse --is-inside-work-tree WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" OUTPUT_VARIABLE __BUILDING_FROM_GIT_SOURCES OUTPUT_STRIP_TRAILING_WHITESPACE) - if (__BUILDING_FROM_GIT_SOURCES) + if(__BUILDING_FROM_GIT_SOURCES) # Get the git version so that we can embed it into the executable execute_process( COMMAND ${__GIT_EXECUTABLE} rev-parse --show-toplevel @@ -67,12 +73,12 @@ if (__GIT_EXECUTABLE) set(DFTRACER_GIT_VERSION "${__GIT_DESCRIBE_VERSION}" CACHE STRING "DFTRACER's version string as told by git.") - endif (__BUILDING_FROM_GIT_SOURCES) -endif (__GIT_EXECUTABLE) + endif(__BUILDING_FROM_GIT_SOURCES) +endif(__GIT_EXECUTABLE) -################################################################ +# ############################################################### # Configuration summary -################################################################ +# ############################################################### # This creates a formatted string that contains a list of variables, # one per line, with their values interpreted as TRUE or FALSE. The @@ -86,44 +92,46 @@ macro(append_str_tf STRING_VAR) string(LENGTH "${var}" _var_length) math(EXPR _num_spaces "${_max_length} - ${_var_length}") dftracer_get_space_string(_spaces ${_num_spaces}) - if (${var}) + + if(${var}) set(${var} "TRUE") string(APPEND ${STRING_VAR} " ${var}:" "${_spaces}" "TRUE\n") - else () + else() set(${var} "FALSE") string(APPEND ${STRING_VAR} " ${var}:" "${_spaces}" "FALSE\n") - endif () + endif() endforeach() -endmacro () +endmacro() -################################################################ +# ############################################################### # Install Public includes -################################################################ - +# ############################################################### function(dftracer_install_headers public_headers) - message("-- [${PROJECT_NAME}] " "installing headers ${public_headers}") - foreach (header ${public_headers}) - file(RELATIVE_PATH header_file_path "${PROJECT_SOURCE_DIR}/src" "${header}") - message("-- [${PROJECT_NAME}] " "installing header ${header_file_path}") - get_filename_component(header_directory_path "${header_file_path}" DIRECTORY) - install( - FILES ${header} - DESTINATION "include/${header_directory_path}" - ) - file(COPY ${header} - DESTINATION "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/${header_directory_path}") - endforeach () + message("-- [${PROJECT_NAME}] " "installing headers ${public_headers}") + + foreach(header ${public_headers}) + file(RELATIVE_PATH header_file_path "${PROJECT_SOURCE_DIR}/src" "${header}") + message("-- [${PROJECT_NAME}] " "installing header ${header_file_path}") + get_filename_component(header_directory_path "${header_file_path}" DIRECTORY) + install( + FILES ${header} + DESTINATION "include/${header_directory_path}" + ) + file(COPY ${header} + DESTINATION "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/${header_directory_path}") + endforeach() endfunction() -################################################################ +# ############################################################### # External Project configurations -################################################################ - +# ############################################################### include(ExternalProject) + function(install_external_project name version var_name url tag install_prefix configure_args) find_package(${name} ${version} QUIET) set(found_var ${name}_FOUND) - if (${${found_var}}) + + if(${${found_var}}) set(include_var ${${var_name}_INCLUDE_DIRS} ${${var_name}_INCLUDE_DIR}) set(library_var ${${var_name}_LIBRARY_DIRS}) include_directories(${include_var}) @@ -131,15 +139,19 @@ function(install_external_project name version var_name url tag install_prefix c message(STATUS "[${PROJECT_NAME}] found dependency already installed ${name} with include ${include_var} and library ${library_var}") else() ExternalProject_Add( - ${name} - PREFIX ${CMAKE_BINARY_DIR} - GIT_REPOSITORY ${url} - GIT_TAG ${tag} - TIMEOUT 10 - CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${install_prefix}" ${configure_args} - BUILD_COMMAND make -j - INSTALL_COMMAND make install -j - LOG_DOWNLOAD ON + ${name} + PREFIX ${CMAKE_BINARY_DIR} + GIT_REPOSITORY ${url} + GIT_TAG ${tag} + TIMEOUT 10 + CMAKE_ARGS + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_INSTALL_PREFIX=${install_prefix} + ${configure_args} + BUILD_COMMAND make -j + INSTALL_COMMAND make install -j + LOG_DOWNLOAD ON ) include_directories(${install_prefix}/include) link_directories(${install_prefix}/lib) @@ -148,10 +160,9 @@ function(install_external_project name version var_name url tag install_prefix c endif() endfunction() -################################################################ +# ############################################################### # Debug configurations -################################################################ - +# ############################################################### function(dftracer_debug_config target_list) foreach(target ${target_list}) target_compile_definitions(${target} PUBLIC DFTRACER_DEBUG) From ac3cd867d9cca43f30380c6a4bd3c7d9ecc257f5 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 30 Jun 2025 21:26:28 -0700 Subject: [PATCH 04/33] Add Perfetto-based file writers and remove legacy ZeroMQ writer - Introduced `PerfettoChromeFileWriter` for logging events in Perfetto format. - Added `PerfettoProtoFileWriter` to handle ProtoBuf-based logging. - Implemented `PerfettoProtoZMQWriter` for ZeroMQ integration with Perfetto. - Removed the legacy `ZeroMQWriter` and `writer_base` implementations. - Updated test cases to utilize the new `PerfettoChromeFileWriter`. - Adjusted CMake configuration to conditionally compile tests based on writer type. - Enhanced logging and error handling in the new writers. --- CMakeLists.txt | 137 ++++++++----- cmake/configure_files/dftracer_config.hpp.in | 5 +- .../dftracer_config_dbg.hpp.in | 5 +- dependency/CMakeLists.txt | 54 ++++- src/dftracer/df_logger.h | 20 +- ...er.cpp => perfetto_chrome_file_writer.cpp} | 103 +++++++--- ...writer.h => perfetto_chrome_file_writer.h} | 19 +- .../writer/perfetto_proto_file_writer.cpp | 158 +++++++++++++++ ..._writer.h => perfetto_proto_file_writer.h} | 25 +-- .../writer/perfetto_proto_zmq_writer.cpp | 184 ++++++++++++++++++ .../writer/perfetto_proto_zmq_writer.h | 58 ++++++ src/dftracer/writer/writer_base.cpp | 96 --------- src/dftracer/writer/writer_base.h | 9 - src/dftracer/writer/zeromq_writer.cpp | 80 -------- test/CMakeLists.txt | 26 ++- test/writer/test_chrome_writer.cpp | 16 +- 16 files changed, 677 insertions(+), 318 deletions(-) rename src/dftracer/writer/{chrome_writer.cpp => perfetto_chrome_file_writer.cpp} (60%) rename src/dftracer/writer/{chrome_writer.h => perfetto_chrome_file_writer.h} (85%) create mode 100644 src/dftracer/writer/perfetto_proto_file_writer.cpp rename src/dftracer/writer/{zeromq_writer.h => perfetto_proto_file_writer.h} (67%) create mode 100644 src/dftracer/writer/perfetto_proto_zmq_writer.cpp create mode 100644 src/dftracer/writer/perfetto_proto_zmq_writer.h delete mode 100644 src/dftracer/writer/writer_base.cpp delete mode 100644 src/dftracer/writer/zeromq_writer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a9f2ae8..45929670 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,14 +133,20 @@ if(DFTRACER_ENABLE_MPI) set(DFTRACER_MPI_ENABLE 1) endif() -option(DFTRACER_WRITER_TYPE "Writer Type" "CHROME") - -if(DFTRACER_WRITER_TYPE STREQUAL "ZEROMQ") - set(DFTRACER_WRITER_TYPE_CHROME 0) - set(DFTRACER_WRITER_TYPE_ZEROMQ 1) +option(DFTRACER_WRITER_TYPE "Writer Type" "PERFETTO_CHROME_FILE") + +if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") + set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 1) +elseif(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_FILE") + set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 1) + set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 0) else() - set(DFTRACER_WRITER_TYPE_CHROME 1) - set(DFTRACER_WRITER_TYPE_ZEROMQ 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 1) + set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 0) endif() option(DFTRACER_BUILD_PYTHON_BINDINGS "Build python bindings." ON) @@ -253,6 +259,53 @@ else() message(FATAL_ERROR "-- [DFTRACER] yaml-cpp is needed for ${PROJECT_NAME} build") endif() + if(DFTRACER_WRITER_TYPE MATCHES ".*PROTO.*") + find_package(Protobuf REQUIRED) + + if(Protobuf_FOUND) + message(STATUS "[DFTRACER] found protobuf at ${Protobuf_INCLUDE_DIRS}") + include_directories(${Protobuf_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${Protobuf_LIBRARIES}) + else() + message(FATAL_ERROR "-- [DFTRACER] protobuf is needed for ${PROJECT_NAME} build") + endif() + + find_library(PERFETTO_SDK_LIB perfetto_sdk PATHS ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib NO_DEFAULT_PATH) + find_path(PERFETTO_SDK_INCLUDE perfetto.h PATHS ${CMAKE_INSTALL_PREFIX}/include NO_DEFAULT_PATH) + + if(PERFETTO_SDK_LIB AND PERFETTO_SDK_INCLUDE) + message(STATUS "[DFTRACER] Found Perfetto SDK library at ${PERFETTO_SDK_LIB}") + message(STATUS "[DFTRACER] Found Perfetto SDK include at ${PERFETTO_SDK_INCLUDE}") + include_directories(${PERFETTO_SDK_INCLUDE}) + set(PERFETTO_SDK_LIB ${PERFETTO_SDK_LIB} CACHE INTERNAL "Perfetto SDK library") + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${PERFETTO_SDK_LIB}) + else() + message(FATAL_ERROR "[DFTRACER] Perfetto SDK not found. Please install it first.") + endif() + endif() + + if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") + find_package(PkgConfig REQUIRED) + pkg_check_modules(ZMQ REQUIRED libzmq) + + if(ZMQ_FOUND) + message(STATUS "[DFTRACER] Found ZeroMQ at ${ZMQ_INCLUDE_DIRS}") + include_directories(${ZMQ_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZMQ_LIBRARIES}) + else() + message(FATAL_ERROR "-- [DFTRACER] ZeroMQ is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'PERFETTO_PROTO_ZMQ'") + endif() + + find_path(CPPZMQ_INCLUDE_DIR zmq.hpp) + + if(CPPZMQ_INCLUDE_DIR) + message(STATUS "[DFTRACER] Found cppzmq at ${CPPZMQ_INCLUDE_DIR}") + include_directories(${CPPZMQ_INCLUDE_DIR}) + else() + message(WARNING "[DFTRACER] cppzmq (C++ wrapper) not found — will fallback to C-style API") + endif() + endif() + # Optional Dependencies # ============================================================================= if(DFTRACER_BUILD_PYTHON_BINDINGS) @@ -285,34 +338,13 @@ else() endif() endif() - if(DFTRACER_WRITER_TYPE STREQUAL "ZEROMQ") - find_package(PkgConfig REQUIRED) - pkg_check_modules(ZMQ REQUIRED libzmq) - - if(ZMQ_FOUND) - message(STATUS "[DFTRACER] Found ZeroMQ at ${ZMQ_INCLUDE_DIRS}") - include_directories(${ZMQ_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZMQ_LIBRARIES}) - else() - message(FATAL_ERROR "-- [DFTRACER] ZeroMQ is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'zeromq'") - endif() - - find_path(CPPZMQ_INCLUDE_DIR zmq.hpp) - - if(CPPZMQ_INCLUDE_DIR) - message(STATUS "[DFTRACER] Found cppzmq at ${CPPZMQ_INCLUDE_DIR}") - include_directories(${CPPZMQ_INCLUDE_DIR}) - else() - message(WARNING "[DFTRACER] cppzmq (C++ wrapper) not found — will fallback to C-style API") - endif() - endif() - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) set(DFTRACER_PRELOAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer_preload.cpp) set(DFTRACER_PRELOAD_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/dftracer_preload.h) - set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/posix.cpp + set(DFTRACER_CORE_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/posix.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/brahma/stdio.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/finstrument/functions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/posix_internal.cpp @@ -321,15 +353,14 @@ else() ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/configuration_manager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/md5.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/df_logger.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/utils.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/writer_base.cpp) - - if(DFTRACER_WRITER_TYPE_ZEROMQ) - set(DFTRACER_CORE_SRC ${DFTRACER_CORE_SRC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/zeromq_writer.cpp) - elseif(DFTRACER_WRITER_TYPE_CHROME) - set(DFTRACER_CORE_SRC ${DFTRACER_CORE_SRC} - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/chrome_writer.cpp) + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/utils.cpp) + + if(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/perfetto_proto_file_writer.cpp) + elseif(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/perfetto_proto_zmq_writer.cpp) + elseif(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/perfetto_chrome_file_writer.cpp) endif() set(DFTRACER_CORE_PUBLIC_INCLUDE @@ -347,26 +378,33 @@ else() ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/logging.h ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/singleton.h ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/utils/configuration_manager.h) + add_library(${PROJECT_NAME} SHARED) target_compile_definitions(${PROJECT_NAME} PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) - target_link_libraries(${PROJECT_NAME} ${DEPENDENCY_LIB}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${DEPENDENCY_LIB}) + add_library(${PROJECT_NAME}_dbg SHARED) - target_link_libraries(${PROJECT_NAME}_dbg ${DEPENDENCY_LIB}) + target_link_libraries(${PROJECT_NAME}_dbg PUBLIC ${DEPENDENCY_LIB}) + add_library(${PROJECT_NAME}_preload SHARED) - target_link_libraries(${PROJECT_NAME}_preload ${DEPENDENCY_LIB} ${PROJECT_NAME}) + target_link_libraries(${PROJECT_NAME}_preload PRIVATE ${PROJECT_NAME}) + add_library(${PROJECT_NAME}_preload_dbg SHARED) - target_link_libraries(${PROJECT_NAME}_preload_dbg ${DEPENDENCY_LIB} ${PROJECT_NAME}_dbg) + target_link_libraries(${PROJECT_NAME}_preload_dbg PRIVATE ${PROJECT_NAME}_dbg) + # target_link_libraries(${PROJECT_NAME} INTERFACE ${PROJECT_NAME}) + # target_link_libraries(${PROJECT_NAME}_dbg INTERFACE ${PROJECT_NAME}_dbg) set(DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_dbg ${PROJECT_NAME}_preload_dbg) if(DFTRACER_BUILD_PYTHON_BINDINGS) - pybind11_add_module(py${PROJECT_NAME} ${DFTRACER_CORE_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/pydftracer.cpp) + pybind11_add_module(py${PROJECT_NAME} SHARED ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/pydftracer.cpp) target_compile_definitions(py${PROJECT_NAME} PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) - target_link_libraries(py${PROJECT_NAME} PRIVATE ${DEPENDENCY_LIB}) + target_link_libraries(py${PROJECT_NAME} PRIVATE ${PROJECT_NAME}) - pybind11_add_module(py${PROJECT_NAME}_dbg NO_EXTRAS ${DFTRACER_CORE_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/pydftracer_dbg.cpp) + pybind11_add_module(py${PROJECT_NAME}_dbg SHARED ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/pydftracer_dbg.cpp) target_compile_definitions(py${PROJECT_NAME}_dbg PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) - target_link_libraries(py${PROJECT_NAME}_dbg PRIVATE ${DEPENDENCY_LIB}) + target_link_libraries(py${PROJECT_NAME}_dbg PRIVATE ${PROJECT_NAME}_dbg) + list(APPEND DFTRACER_DEBUG_TARGETS py${PROJECT_NAME}_dbg) endif() @@ -744,8 +782,9 @@ else() DFTRACER_LIBDIR_AS_LIB DFTRACER_USE_CLANG_LIBCXX DFTRACER_WARNINGS_AS_ERRORS - DFTRACER_WRITER_TYPE_CHROME - DFTRACER_WRITER_TYPE_ZEROMQ + DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE + DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE + DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZEROMQ ) string(APPEND _str "\n== End DFTRACER Configuration Summary ==\n") diff --git a/cmake/configure_files/dftracer_config.hpp.in b/cmake/configure_files/dftracer_config.hpp.in index 31abb2a6..35624d04 100644 --- a/cmake/configure_files/dftracer_config.hpp.in +++ b/cmake/configure_files/dftracer_config.hpp.in @@ -34,8 +34,9 @@ #cmakedefine DFTRACER_HWLOC_ENABLE 1 #cmakedefine DFTRACER_MPI_ENABLE 1 #cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" -#cmakedefine01 DFTRACER_WRITER_TYPE_CHROME -#cmakedefine01 DFTRACER_WRITER_TYPE_ZEROMQ +#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE +#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE +#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ //========================== // Common macro definitions diff --git a/cmake/configure_files/dftracer_config_dbg.hpp.in b/cmake/configure_files/dftracer_config_dbg.hpp.in index 686223f9..4d3b9be6 100644 --- a/cmake/configure_files/dftracer_config_dbg.hpp.in +++ b/cmake/configure_files/dftracer_config_dbg.hpp.in @@ -34,8 +34,9 @@ #cmakedefine DFTRACER_HWLOC_ENABLE 1 #cmakedefine DFTRACER_MPI_ENABLE 1 #cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" -#cmakedefine01 DFTRACER_WRITER_TYPE_CHROME -#cmakedefine01 DFTRACER_WRITER_TYPE_ZEROMQ +#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE +#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE +#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ #define DFTRACER_LOGGER_CPP_LOGGER 1 #define DFTRACER_LOGGER_LEVEL_TRACE 1 diff --git a/dependency/CMakeLists.txt b/dependency/CMakeLists.txt index 4a189262..723539b9 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -1,13 +1,15 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/dftracer-utils.cmake) + install_external_project(cpp-logger 1.0.0 "CPP_LOGGER" https://github.com/hariharan-devarajan/cpp-logger.git v0.0.4 ${CMAKE_INSTALL_PREFIX} "") install_external_project(gotcha 2.3.2 "gotcha" https://github.com/LLNL/GOTCHA.git 1.0.7 ${CMAKE_INSTALL_PREFIX} "-DCMAKE_POLICY_VERSION_MINIMUM=3.5") install_external_project(brahma 2.1.0 "BRAHMA" https://github.com/hariharan-devarajan/brahma.git v0.0.10 ${CMAKE_INSTALL_PREFIX} "") add_dependencies(brahma cpp-logger) add_dependencies(brahma gotcha) + find_package(yaml-cpp QUIET) -install_external_project(yaml-cpp "" "YAML_CPP" https://github.com/jbeder/yaml-cpp.git yaml-cpp-0.6.3 ${CMAKE_INSTALL_PREFIX} "-DYAML_CPP_BUILD_TESTS=OFF;-DYAML_BUILD_SHARED_LIBS=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5") if(NOT ${yaml-cpp_FOUND}) + install_external_project(yaml-cpp "" "YAML_CPP" https://github.com/jbeder/yaml-cpp.git yaml-cpp-0.6.3 ${CMAKE_INSTALL_PREFIX} "-DYAML_CPP_BUILD_TESTS=OFF;-DYAML_BUILD_SHARED_LIBS=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5") add_dependencies(yaml-cpp brahma) add_dependencies(yaml-cpp gotcha) add_dependencies(yaml-cpp cpp-logger) @@ -15,14 +17,48 @@ endif() install_external_project(pybind11 2.12.0 "pybind11" https://github.com/pybind/pybind11.git v2.12.0 ${CMAKE_INSTALL_PREFIX} "-DPYBIND11_TEST=OFF") -# ZeroMQ setup if selected -if(DFTRACER_WRITER_TYPE STREQUAL "ZEROMQ") - # Install libzmq (C backend) - install_external_project(ZeroMQ 4.3.5 "ZeroMQ" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") +if(DFTRACER_WRITER_TYPE MATCHES ".*PROTO.*") + install_external_project(protobuf 31.1 "protobuf" https://github.com/protocolbuffers/protobuf.git v31.1 ${CMAKE_INSTALL_PREFIX} "-Dprotobuf_BUILD_TESTS=OFF;-Dprotobuf_BUILD_EXAMPLES=OFF;-Dprotobuf_BUILD_LIBPROTOC=ON;-Dprotobuf_BUILD_SHARED_LIBS=ON;-Dprotobuf_WITH_ZLIB=OFF;-DCMAKE_POLICY_VERSION_MINIMUM=3.5") - # Install cppzmq (header-only C++ wrapper) - install_external_project(cppzmq 4.10.0 "cppzmq" https://github.com/zeromq/cppzmq.git v4.9.0 ${CMAKE_INSTALL_PREFIX} "-DCPPZMQ_BUILD_TESTS=OFF") + ExternalProject_Add( + perfetto + PREFIX ${CMAKE_BINARY_DIR} + GIT_REPOSITORY https://github.com/google/perfetto.git + GIT_TAG v51.0 + TIMEOUT 10 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + + set(PERFETTO_OUTPUT_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib64") + set(PERFETTO_OUTPUT_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") + + set(PERFETTO_SDK_DIR "${CMAKE_BINARY_DIR}/src/perfetto/sdk") + set(PERFETTO_SDK_HEADER_PATH "${PERFETTO_OUTPUT_INCLUDE_DIR}/perfetto.h") + set(PERFETTO_SDK_LIB_PATH "${PERFETTO_OUTPUT_LIB_DIR}/libperfetto_sdk.a") - add_dependencies(cppzmq ZeroMQ) - add_dependencies(ZeroMQ yaml-cpp) + add_custom_command( + OUTPUT ${PERFETTO_SDK_LIB_PATH} + COMMAND ${CMAKE_COMMAND} -E make_directory ${PERFETTO_OUTPUT_LIB_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${PERFETTO_OUTPUT_INCLUDE_DIR} + COMMAND ${CMAKE_CXX_COMPILER} -std=c++17 -fPIC -c ${PERFETTO_SDK_DIR}/perfetto.cc -I${PERFETTO_SDK_DIR} -o ${CMAKE_BINARY_DIR}/perfetto.o + COMMAND ${CMAKE_AR} rcs ${PERFETTO_SDK_LIB_PATH} ${CMAKE_BINARY_DIR}/perfetto.o + COMMAND ${CMAKE_COMMAND} -E copy ${PERFETTO_SDK_DIR}/perfetto.h ${PERFETTO_SDK_HEADER_PATH} + DEPENDS perfetto + BYPRODUCTS ${PERFETTO_SDK_HEADER_PATH} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Building and placing Perfetto SDK into ${CMAKE_INSTALL_PREFIX}" + VERBATIM + ) + + add_custom_target(perfetto_sdk ALL DEPENDS ${PERFETTO_SDK_LIB_PATH}) +endif() + +if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") + install_external_project(zeromq 4.3.5 "zeromq" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") + install_external_project(cppzmq 4.10.0 "cppzmq" https://github.com/zeromq/cppzmq.git v4.9.0 ${CMAKE_INSTALL_PREFIX} "-DCPPZMQ_BUILD_TESTS=OFF") + add_dependencies(cppzmq zeromq) + add_dependencies(zeromq yaml-cpp) endif() diff --git a/src/dftracer/df_logger.h b/src/dftracer/df_logger.h index 781f8d0a..18035f7c 100644 --- a/src/dftracer/df_logger.h +++ b/src/dftracer/df_logger.h @@ -12,10 +12,12 @@ #include #include #include -#if DFTRACER_WRITER_TYPE_ZEROMQ -#include -#elif DFTRACER_WRITER_TYPE_CHROME -#include +#if DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE +#include +#elif DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ +#include +#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE +#include #endif #include #include @@ -41,10 +43,12 @@ typedef std::chrono::high_resolution_clock chrono; -#if DFTRACER_WRITER_TYPE_ZEROMQ -using DFTWriter = dftracer::ZeroMQWriter; -#elif DFTRACER_WRITER_TYPE_CHROME -using DFTWriter = dftracer::ChromeWriter; +#if DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE +using DFTWriter = dftracer::PerfettoProtoFileWriter; +#elif DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ +using DFTWriter = dftracer::PerfettoProtoZMQWriter; +#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE +using DFTWriter = dftracer::PerfettoChromeFileWriter; #endif class DFTLogger { diff --git a/src/dftracer/writer/chrome_writer.cpp b/src/dftracer/writer/perfetto_chrome_file_writer.cpp similarity index 60% rename from src/dftracer/writer/chrome_writer.cpp rename to src/dftracer/writer/perfetto_chrome_file_writer.cpp index 45d02e37..b8ce117d 100644 --- a/src/dftracer/writer/chrome_writer.cpp +++ b/src/dftracer/writer/perfetto_chrome_file_writer.cpp @@ -3,7 +3,7 @@ // #include -#include +#include #include #include @@ -16,15 +16,15 @@ #include template <> -std::shared_ptr - dftracer::Singleton::instance = nullptr; +std::shared_ptr + dftracer::Singleton::instance = nullptr; template <> -bool dftracer::Singleton::stop_creating_instances = - false; +bool dftracer::Singleton< + dftracer::PerfettoChromeFileWriter>::stop_creating_instances = false; namespace dftracer { -void ChromeWriter::initialize(char *filename, bool throw_error, - HashType hostname_hash) { +void PerfettoChromeFileWriter::initialize(char *filename, bool throw_error, + HashType hostname_hash) { this->hostname_hash = hostname_hash; this->throw_error = throw_error; this->filename = filename; @@ -39,44 +39,48 @@ void ChromeWriter::initialize(char *filename, bool throw_error, } } init = true; - DFTRACER_LOG_DEBUG("ChromeWriter.initialize %s", this->filename.c_str()); + DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.initialize %s", + this->filename.c_str()); } -void ChromeWriter::log(int index, ConstEventNameType event_name, - ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, MetadataMap *metadata, - ProcessID process_id, ThreadID thread_id) { - DFTRACER_LOG_DEBUG("ChromeWriter.log", ""); +void PerfettoChromeFileWriter::log(int index, ConstEventNameType event_name, + ConstEventNameType category, + TimeResolution start_time, + TimeResolution duration, + MetadataMap *metadata, ProcessID process_id, + ThreadID thread_id) { + DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.log", ""); if (fh != nullptr) { write_event_json_to_buffer(index, event_name, category, start_time, duration, metadata, process_id, thread_id); flush_buffer_to_file(false); } else { - DFTRACER_LOG_ERROR("ChromeWriter.log invalid", ""); + DFTRACER_LOG_ERROR("PerfettoChromeFileWriter.log invalid", ""); } is_first_write = false; } -void ChromeWriter::log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, ConstEventNameType ph, - ProcessID process_id, ThreadID tid, - bool is_string) { - DFTRACER_LOG_DEBUG("ChromeWriter.log_metadata", ""); +void PerfettoChromeFileWriter::log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, + ConstEventNameType ph, + ProcessID process_id, ThreadID tid, + bool is_string) { + DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.log_metadata", ""); if (fh != nullptr) { write_metadata_json_to_buffer(index, name, value, ph, process_id, tid, is_string); flush_buffer_to_file(false); } else { - DFTRACER_LOG_ERROR("ChromeWriter.log_metadata invalid", ""); + DFTRACER_LOG_ERROR("PerfettoChromeFileWriter.log_metadata invalid", ""); } is_first_write = false; } -void ChromeWriter::finalize(bool has_entry) { +void PerfettoChromeFileWriter::finalize(bool has_entry) { if (this->init) { - DFTRACER_LOG_DEBUG("ChromeWriter.finalize", ""); + DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.finalize", ""); if (fh != nullptr) { DFTRACER_LOG_INFO("Profiler finalizing writer %s", filename.c_str()); flush_buffer_to_file(true); @@ -152,7 +156,7 @@ void ChromeWriter::finalize(bool has_entry) { } } -void ChromeWriter::write_event_json_to_buffer( +void PerfettoChromeFileWriter::write_event_json_to_buffer( int index, ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, TimeResolution duration, MetadataMap *metadata, ProcessID process_id, ThreadID thread_id) { @@ -182,11 +186,12 @@ void ChromeWriter::write_event_json_to_buffer( current_index++; } - DFTRACER_LOG_DEBUG("ChromeWriter.write_event_json_to_buffer %s on %s", - buffer.data() + previous_index, this->filename.c_str()); + DFTRACER_LOG_DEBUG( + "PerfettoChromeFileWriter.write_event_json_to_buffer %s on %s", + buffer.data() + previous_index, this->filename.c_str()); } -void ChromeWriter::write_metadata_json_to_buffer( +void PerfettoChromeFileWriter::write_metadata_json_to_buffer( int index, ConstEventNameType name, ConstEventNameType value, ConstEventNameType ph, ProcessID process_id, ThreadID thread_id, bool is_string) { @@ -220,8 +225,50 @@ void ChromeWriter::write_metadata_json_to_buffer( current_index++; } - DFTRACER_LOG_DEBUG("ChromeWriter.write_metadata_json_to_buffer %s on %s", - buffer.data() + previous_index, this->filename.c_str()); + DFTRACER_LOG_DEBUG( + "PerfettoChromeFileWriter.write_metadata_json_to_buffer %s on %s", + buffer.data() + previous_index, this->filename.c_str()); +} + +std::string PerfettoChromeFileWriter::convert_metadata_to_json_string( + MetadataMap *metadata) { + std::stringstream metadata_stream; + if (metadata != nullptr && !metadata->empty()) { + metadata_stream << R"(,"args":{"hhash":")" << this->hostname_hash << "\""; + for (const auto &item : *metadata) { + metadata_stream << ","; + metadata_stream << "\"" << item.first << "\":"; + if (item.second.type() == typeid(unsigned int)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(int)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(const char *)) { + metadata_stream << "\"" << std::any_cast(item.second) + << "\""; + } else if (item.second.type() == typeid(std::string)) { + metadata_stream << "\"" << std::any_cast(item.second) + << "\""; + } else if (item.second.type() == typeid(size_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(uint16_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(HashType)) { + metadata_stream << "\"" << std::any_cast(item.second) << "\""; + } else if (item.second.type() == typeid(long)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(ssize_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(off_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(off64_t)) { + metadata_stream << std::any_cast(item.second); + } else { + DFTRACER_LOG_INFO("No conversion for type %s", item.first.c_str()); + } + } + metadata_stream << "}"; + } + return metadata_stream.str(); } } // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/writer/chrome_writer.h b/src/dftracer/writer/perfetto_chrome_file_writer.h similarity index 85% rename from src/dftracer/writer/chrome_writer.h rename to src/dftracer/writer/perfetto_chrome_file_writer.h index 4b8d77d9..0231a222 100644 --- a/src/dftracer/writer/chrome_writer.h +++ b/src/dftracer/writer/perfetto_chrome_file_writer.h @@ -2,8 +2,8 @@ // Created by haridev on 3/28/23. // -#ifndef DFTRACER_CHROME_WRITER_H -#define DFTRACER_CHROME_WRITER_H +#ifndef DFTRACER_PERFETTO_CHROME_FILE_WRITER_H +#define DFTRACER_PERFETTO_CHROME_FILE_WRITER_H #include #include @@ -23,7 +23,7 @@ #include namespace dftracer { -class ChromeWriter : public WriterBase { +class PerfettoChromeFileWriter : public WriterBase { protected: static const int MAX_LINE_SIZE = 16 * 1024L; bool enable_compression; @@ -38,7 +38,7 @@ class ChromeWriter : public WriterBase { std::unique_lock lock(mtx); if (current_index == 0 || (!force && current_index < write_buffer_size)) return 0; - DFTRACER_LOG_DEBUG("ChromeWriter.write_buffer_op %s", + DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.write_buffer_op %s", this->filename.c_str()); size_t written_elements = 0; flockfile(fh); @@ -56,12 +56,12 @@ class ChromeWriter : public WriterBase { } public: - ChromeWriter() + PerfettoChromeFileWriter() : enable_compression(false), is_first_write(false), fh(nullptr), write_buffer_size(0) { - DFTRACER_LOG_DEBUG("ChromeWriter.ChromeWriter", ""); + DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.PerfettoChromeFileWriter", ""); auto conf = dftracer::Singleton::get_instance(); enable_core_affinity = conf->core_affinity; @@ -73,7 +73,9 @@ class ChromeWriter : public WriterBase { current_index = 0; } } - ~ChromeWriter() { DFTRACER_LOG_DEBUG("Destructing ChromeWriter", ""); } + ~PerfettoChromeFileWriter() { + DFTRACER_LOG_DEBUG("Destructing PerfettoChromeFileWriter", ""); + } void initialize(char *filename, bool throw_error, HashType hostname_hash); void log(int index, ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, @@ -85,6 +87,7 @@ class ChromeWriter : public WriterBase { void finalize(bool has_entry); private: + std::string convert_metadata_to_json_string(MetadataMap *metadata); void write_event_json_to_buffer(int index, ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, @@ -99,4 +102,4 @@ class ChromeWriter : public WriterBase { }; } // namespace dftracer -#endif // DFTRACER_CHROME_WRITER_H +#endif // DFTRACER_PERFETTO_CHROME_FILE_WRITER_H diff --git a/src/dftracer/writer/perfetto_proto_file_writer.cpp b/src/dftracer/writer/perfetto_proto_file_writer.cpp new file mode 100644 index 00000000..2df180e8 --- /dev/null +++ b/src/dftracer/writer/perfetto_proto_file_writer.cpp @@ -0,0 +1,158 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +PERFETTO_DEFINE_CATEGORIES( + perfetto::Category("dftracer").SetDescription("DFTracer Events")); + +PERFETTO_TRACK_EVENT_STATIC_STORAGE(); + +template <> +std::shared_ptr + dftracer::Singleton::instance = nullptr; +template <> +bool dftracer::Singleton< + dftracer::PerfettoProtoFileWriter>::stop_creating_instances = false; + +namespace dftracer { +void PerfettoProtoFileWriter::initialize(char *filename, bool throw_error, + HashType hostname_hash) { + this->hostname_hash = hostname_hash; + this->throw_error = throw_error; + this->filename = filename; + + perfetto::TracingInitArgs tracing_args; + tracing_args.backends = perfetto::kInProcessBackend; + perfetto::Tracing::Initialize(tracing_args); + perfetto::TrackEvent::Register(); + + perfetto::TraceConfig trace_config; + trace_config.add_buffers()->set_size_kb(1024 * 16); // 16MB buffer + auto *data_source_config = trace_config.add_data_sources()->mutable_config(); + data_source_config->set_name("track_event"); + + int trace_fd = open(this->filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644); + if (trace_fd == -1) { + DFTRACER_LOG_ERROR("unable to create log file %s", filename); + if (this->throw_error) { + throw std::runtime_error("unable to create log file"); + } + return; + } + + tracing_session = perfetto::Tracing::NewTrace(); + tracing_session->Setup(trace_config, trace_fd); + tracing_session->StartBlocking(); + + init = true; + + DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.initialize %s", + this->filename.c_str()); +} + +void PerfettoProtoFileWriter::log(int index, ConstEventNameType event_name, + ConstEventNameType category, + TimeResolution start_time, + TimeResolution duration, + MetadataMap *metadata, ProcessID process_id, + ThreadID thread_id) { + DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.log", ""); + if (!init) { + DFTRACER_LOG_ERROR("PerfettoProtoFileWriter not initialized", ""); + return; + } + std::lock_guard lock(mtx); + + perfetto::TrackEvent::Trace([&](perfetto::TrackEvent::TraceContext ctx) { + auto packet = ctx.NewTracePacket(); + packet->set_timestamp(start_time * 1000); + packet->set_timestamp_clock_id( + perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); + + auto event = packet->set_track_event(); + event->add_categories(category); + event->set_name(event_name); + + auto *legacy_event = event->set_legacy_event(); + legacy_event->set_phase('X'); + legacy_event->set_duration_us(duration); + legacy_event->set_thread_duration_us(duration); + legacy_event->set_pid_override(process_id); + legacy_event->set_tid_override(thread_id); + + auto *hostname_annot = event->add_debug_annotations(); + hostname_annot->set_name("hhash"); + hostname_annot->set_string_value(this->hostname_hash); + if (metadata) { + for (auto const &[key, val] : *metadata) { + auto *debug_annot = event->add_debug_annotations(); + debug_annot->set_name(key.c_str()); + if (val.type() == typeid(int)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(unsigned int)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(long)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(unsigned long)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(long long)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(unsigned long long)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(const char *)) { + debug_annot->set_string_value(std::any_cast(val)); + } else if (val.type() == typeid(std::string)) { + debug_annot->set_string_value(std::any_cast(val)); + } else if (val.type() == typeid(HashType)) { + debug_annot->set_string_value(std::any_cast(val)); + } else if (val.type() == typeid(size_t)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(uint16_t)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(ssize_t)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(off_t)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(off64_t)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(float)) { + debug_annot->set_double_value(std::any_cast(val)); + } else if (val.type() == typeid(double)) { + debug_annot->set_double_value(std::any_cast(val)); + } else { + DFTRACER_LOG_WARN("No conversion for type %s", key.c_str()); + } + } + } + }); +} + +void PerfettoProtoFileWriter::log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, + ConstEventNameType ph, + ProcessID process_id, + ThreadID thread_id, bool is_string) { + DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.log_metadata", ""); +} + +void PerfettoProtoFileWriter::finalize(bool has_entry) { + DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.finalize", ""); + if (init) { + tracing_session->StopBlocking(); + + init = false; + } else { + DFTRACER_LOG_ERROR("PerfettoProtoFileWriter.finalize invalid", ""); + } +} + +} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/writer/zeromq_writer.h b/src/dftracer/writer/perfetto_proto_file_writer.h similarity index 67% rename from src/dftracer/writer/zeromq_writer.h rename to src/dftracer/writer/perfetto_proto_file_writer.h index df16e874..ce3a19d5 100644 --- a/src/dftracer/writer/zeromq_writer.h +++ b/src/dftracer/writer/perfetto_proto_file_writer.h @@ -1,5 +1,5 @@ -#ifndef DFTRACER_ZEROMQ_WRITER_H -#define DFTRACER_ZEROMQ_WRITER_H +#ifndef DFTRACER_PERFETTO_PROTO_FILE_WRITER_H +#define DFTRACER_PERFETTO_PROTO_FILE_WRITER_H #include #include @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -17,23 +18,25 @@ #include #include #include -#include - namespace dftracer { -class ZeroMQWriter : public WriterBase { +class PerfettoProtoFileWriter : public WriterBase { private: - std::unique_ptr context; - std::unique_ptr socket; + std::mutex mtx; + std::unique_ptr tracing_session; + + void stream_main(std::unique_ptr session); public: - ZeroMQWriter() { - DFTRACER_LOG_DEBUG("ZeroMQWriter.ZeroMQWriter", ""); + PerfettoProtoFileWriter() { + DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.PerfettoProtoFileWriter", ""); auto conf = dftracer::Singleton::get_instance(); include_metadata = conf->metadata; enable_core_affinity = conf->core_affinity; } - ~ZeroMQWriter() { DFTRACER_LOG_DEBUG("Destructing ZeroMQWriter", ""); } + ~PerfettoProtoFileWriter() { + DFTRACER_LOG_DEBUG("Destructing PerfettoProtoFileWriter", ""); + } void initialize(char *filename, bool throw_error, HashType hostname_hash); void log(int index, ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, @@ -46,4 +49,4 @@ class ZeroMQWriter : public WriterBase { }; } // namespace dftracer -#endif // DFTRACER_ZEROMQ_WRITER_H +#endif // DFTRACER_PERFETTO_PROTO_FILE_WRITER_H diff --git a/src/dftracer/writer/perfetto_proto_zmq_writer.cpp b/src/dftracer/writer/perfetto_proto_zmq_writer.cpp new file mode 100644 index 00000000..9fb2c023 --- /dev/null +++ b/src/dftracer/writer/perfetto_proto_zmq_writer.cpp @@ -0,0 +1,184 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +PERFETTO_DEFINE_CATEGORIES( + perfetto::Category("dftracer").SetDescription("DFTracer Events")); + +PERFETTO_TRACK_EVENT_STATIC_STORAGE(); + +template <> +std::shared_ptr + dftracer::Singleton::instance = nullptr; +template <> +bool dftracer::Singleton< + dftracer::PerfettoProtoZMQWriter>::stop_creating_instances = false; + +namespace dftracer { +void PerfettoProtoZMQWriter::initialize(char *filename, bool throw_error, + HashType hostname_hash) { + this->hostname_hash = hostname_hash; + this->throw_error = throw_error; + this->filename = filename; + + perfetto::TracingInitArgs tracing_args; + tracing_args.backends = perfetto::kInProcessBackend; + // args.shmem_size_kb = (1024 * 16); // 16MB buffer + // args.shmem_page_size_kb = 4; + perfetto::Tracing::Initialize(tracing_args); + perfetto::TrackEvent::Register(); + + perfetto::TraceConfig trace_config; + trace_config.add_buffers()->set_size_kb(1024 * 16); // 16MB buffer + auto *data_source_config = trace_config.add_data_sources()->mutable_config(); + data_source_config->set_name("track_event"); + + tracing_session = perfetto::Tracing::NewTrace(); + tracing_session->Setup(trace_config); + tracing_session->StartBlocking(); + + context = std::make_unique(1); + socket = std::make_unique(*context, zmq::socket_type::push); + if (!socket) { + DFTRACER_LOG_ERROR("unable to create ZeroMQ socket %s", filename); + } + socket->connect(filename); + + stop_stream = false; + stream_thread = std::thread(&PerfettoProtoZMQWriter::stream_main, this, + std::move(tracing_session)); + + init = true; + DFTRACER_LOG_INFO("created ZeroMQ socket and connected to %s", filename); +} + +void PerfettoProtoZMQWriter::log(int index, ConstEventNameType event_name, + ConstEventNameType category, + TimeResolution start_time, + TimeResolution duration, MetadataMap *metadata, + ProcessID process_id, ThreadID thread_id) { + DFTRACER_LOG_DEBUG("PerfettoProtoZMQWriter.log", ""); + if (!init) { + DFTRACER_LOG_ERROR("PerfettoProtoZMQWriter not initialized", ""); + return; + } + std::lock_guard lock(mtx); + + perfetto::TrackEvent::Trace([&](perfetto::TrackEvent::TraceContext ctx) { + auto packet = ctx.NewTracePacket(); + packet->set_timestamp(start_time * 1000); + packet->set_timestamp_clock_id( + perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); + + auto event = packet->set_track_event(); + event->add_categories(category); + event->set_name(event_name); + + auto *legacy_event = event->set_legacy_event(); + legacy_event->set_phase('X'); + legacy_event->set_duration_us(duration); + legacy_event->set_thread_duration_us(duration); + legacy_event->set_pid_override(process_id); + legacy_event->set_tid_override(thread_id); + + auto *hostname_annot = event->add_debug_annotations(); + hostname_annot->set_name("hhash"); + hostname_annot->set_string_value(this->hostname_hash); + if (metadata) { + for (auto const &[key, val] : *metadata) { + auto *debug_annot = event->add_debug_annotations(); + debug_annot->set_name(key.c_str()); + if (val.type() == typeid(int)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(unsigned int)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(long)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(unsigned long)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(long long)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(unsigned long long)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(const char *)) { + debug_annot->set_string_value(std::any_cast(val)); + } else if (val.type() == typeid(std::string)) { + debug_annot->set_string_value(std::any_cast(val)); + } else if (val.type() == typeid(HashType)) { + debug_annot->set_string_value(std::any_cast(val)); + } else if (val.type() == typeid(size_t)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(uint16_t)) { + debug_annot->set_uint_value(std::any_cast(val)); + } else if (val.type() == typeid(ssize_t)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(off_t)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(off64_t)) { + debug_annot->set_int_value(std::any_cast(val)); + } else if (val.type() == typeid(float)) { + debug_annot->set_double_value(std::any_cast(val)); + } else if (val.type() == typeid(double)) { + debug_annot->set_double_value(std::any_cast(val)); + } else { + DFTRACER_LOG_WARN("No conversion for type %s", key.c_str()); + } + } + } + }); +} + +void PerfettoProtoZMQWriter::log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, + ConstEventNameType ph, + ProcessID process_id, + ThreadID thread_id, bool is_string) { + DFTRACER_LOG_DEBUG("PerfettoProtoZMQWriter.log_metadata", ""); +} + +void PerfettoProtoZMQWriter::stream_main( + std::unique_ptr session) { + while (!stop_stream.load(std::memory_order_relaxed)) { + auto trace_data = session->ReadTraceBlocking(); + if (!trace_data.empty()) { + zmq::message_t message(trace_data.data(), trace_data.size()); + socket->send(message, zmq::send_flags::dontwait); + } + } + session->FlushBlocking(); + auto trace_data = session->ReadTraceBlocking(); + if (!trace_data.empty()) { + zmq::message_t message(trace_data.data(), trace_data.size()); + socket->send(message, zmq::send_flags::dontwait); + } +} + +void PerfettoProtoZMQWriter::finalize(bool has_entry) { + DFTRACER_LOG_DEBUG("PerfettoProtoZMQWriter.finalize", ""); + if (init) { + tracing_session->StopBlocking(); + + stop_stream.store(true); + if (stream_thread.joinable()) { + stream_thread.join(); + } + + socket->close(); + context->close(); + + init = false; + } else { + DFTRACER_LOG_ERROR("PerfettoProtoZMQWriter.finalize invalid", ""); + } +} + +} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/writer/perfetto_proto_zmq_writer.h b/src/dftracer/writer/perfetto_proto_zmq_writer.h new file mode 100644 index 00000000..ccd2177a --- /dev/null +++ b/src/dftracer/writer/perfetto_proto_zmq_writer.h @@ -0,0 +1,58 @@ +#ifndef DFTRACER_PERFETTO_PROTO_ZMQ_WRITER_H +#define DFTRACER_PERFETTO_PROTO_ZMQ_WRITER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dftracer { +class PerfettoProtoZMQWriter : public WriterBase { + private: + std::mutex mtx; + std::unique_ptr context; + std::unique_ptr socket; + std::thread stream_thread; + std::atomic stop_stream; + std::unique_ptr tracing_session; + + void stream_main(std::unique_ptr session); + + public: + PerfettoProtoZMQWriter() { + DFTRACER_LOG_DEBUG("PerfettoProtoZMQWriter.PerfettoProtoZMQWriter", ""); + auto conf = + dftracer::Singleton::get_instance(); + include_metadata = conf->metadata; + enable_core_affinity = conf->core_affinity; + } + ~PerfettoProtoZMQWriter() { + DFTRACER_LOG_DEBUG("Destructing PerfettoProtoZMQWriter", ""); + } + void initialize(char *filename, bool throw_error, HashType hostname_hash); + void log(int index, ConstEventNameType event_name, + ConstEventNameType category, TimeResolution start_time, + TimeResolution duration, MetadataMap *metadata, ProcessID process_id, + ThreadID tid); + void log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, ConstEventNameType ph, + ProcessID process_id, ThreadID tid, bool is_string = true); + void finalize(bool has_entry); +}; +} // namespace dftracer + +#endif // DFTRACER_PERFETTO_PROTO_ZMQ_WRITER_H diff --git a/src/dftracer/writer/writer_base.cpp b/src/dftracer/writer/writer_base.cpp deleted file mode 100644 index 06ae9444..00000000 --- a/src/dftracer/writer/writer_base.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include - -#include -#include -#include - -namespace dftracer { - -std::string WriterBase::convert_event_to_json_string( - int index, ConstEventNameType event_name, ConstEventNameType category, - TimeResolution start_time, TimeResolution duration, MetadataMap *metadata, - ProcessID process_id, ThreadID thread_id) { - std::string metadata_json_string; - if (include_metadata) { - metadata_json_string = convert_metadata_to_json_string(metadata); - } - std::stringstream json_stream; - json_stream << "{"; - json_stream << R"("id":)" << index; - json_stream << R"(,"name":")" << event_name; - json_stream << R"(","cat":")" << category; - json_stream << R"(","pid":)" << process_id; - json_stream << R"(,"tid":)" << thread_id; - json_stream << R"(,"ts":)" << start_time; - json_stream << R"(,"dur":)" << duration; - json_stream << R"(,"ph":"X")" << metadata_json_string; - json_stream << "}"; - DFTRACER_LOG_DEBUG("WriterBase.convert_event_to_json_string %s on %s", - json_stream.str().c_str(), this->filename.c_str()); - return json_stream.str(); -} - -std::string WriterBase::convert_metadata_event_to_json_string( - int index, ConstEventNameType name, ConstEventNameType value, - ConstEventNameType ph, ProcessID process_id, ThreadID thread_id) { - MetadataMap metadata; - metadata["name"] = name; - metadata["value"] = value; - std::string metadata_json_string = convert_metadata_to_json_string(&metadata); - std::stringstream json_stream; - json_stream << "{"; - json_stream << R"("id":)" << index; - json_stream << R"(,"name":")" << ph; - json_stream << R"(","cat":")" << "dftracer"; - json_stream << R"(","pid":)" << process_id; - json_stream << R"(,"tid":)" << thread_id; - json_stream << R"(,"ph":"M")" << metadata_json_string; - json_stream << "}"; - DFTRACER_LOG_DEBUG( - "WriterBase.convert_metadata_event_to_json_string %s on %s", - json_stream.str().c_str(), this->filename.c_str()); - return json_stream.str(); -} - -std::string WriterBase::convert_metadata_to_json_string(MetadataMap *metadata) { - std::stringstream metadata_stream; - if (metadata != nullptr && !metadata->empty()) { - metadata_stream << R"(,"args":{"hhash":")" << this->hostname_hash << "\""; - for (const auto &item : *metadata) { - metadata_stream << ","; - metadata_stream << "\"" << item.first << "\":"; - if (item.second.type() == typeid(unsigned int)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(int)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(const char *)) { - metadata_stream << "\"" << std::any_cast(item.second) - << "\""; - } else if (item.second.type() == typeid(std::string)) { - metadata_stream << "\"" << std::any_cast(item.second) - << "\""; - } else if (item.second.type() == typeid(size_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(uint16_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(HashType)) { - metadata_stream << "\"" << std::any_cast(item.second) << "\""; - } else if (item.second.type() == typeid(long)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(ssize_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(off_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(off64_t)) { - metadata_stream << std::any_cast(item.second); - } else { - DFTRACER_LOG_INFO("No conversion for type %s", item.first.c_str()); - } - } - metadata_stream << "}"; - } - return metadata_stream.str(); -} - -} // namespace dftracer diff --git a/src/dftracer/writer/writer_base.h b/src/dftracer/writer/writer_base.h index a5ef25e2..e1ba14cb 100644 --- a/src/dftracer/writer/writer_base.h +++ b/src/dftracer/writer/writer_base.h @@ -19,15 +19,6 @@ class WriterBase { bool init = false; bool throw_error = false; - std::string convert_event_to_json_string( - int index, ConstEventNameType event_name, ConstEventNameType category, - TimeResolution start_time, TimeResolution duration, MetadataMap *metadata, - ProcessID process_id, ThreadID thread_id); - std::string convert_metadata_event_to_json_string( - int index, ConstEventNameType name, ConstEventNameType value, - ConstEventNameType ph, ProcessID process_id, ThreadID thread_id); - std::string convert_metadata_to_json_string(MetadataMap *metadata); - public: virtual ~WriterBase() = default; virtual void initialize(char *filename, bool throw_error, diff --git a/src/dftracer/writer/zeromq_writer.cpp b/src/dftracer/writer/zeromq_writer.cpp deleted file mode 100644 index 5b211e93..00000000 --- a/src/dftracer/writer/zeromq_writer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -template <> -std::shared_ptr - dftracer::Singleton::instance = nullptr; -template <> -bool dftracer::Singleton::stop_creating_instances = - false; - -namespace dftracer { -void ZeroMQWriter::initialize(char *filename, bool throw_error, - HashType hostname_hash) { - this->hostname_hash = hostname_hash; - this->throw_error = throw_error; - this->filename = filename; - context = std::make_unique(1); - socket = std::make_unique(*context, zmq::socket_type::push); - if (!socket) { - DFTRACER_LOG_ERROR("unable to create ZeroMQ socket %s", filename); - } - socket->connect(filename); - this->init = true; - DFTRACER_LOG_INFO("created ZeroMQ socket and connected to %s", filename); -} - -void ZeroMQWriter::log(int index, ConstEventNameType event_name, - ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, MetadataMap *metadata, - ProcessID process_id, ThreadID thread_id) { - DFTRACER_LOG_DEBUG("ZeroMQWriter.log", ""); - - if (init) { - auto event_json = - convert_event_to_json_string(index, event_name, category, start_time, - duration, metadata, process_id, thread_id); - zmq::message_t message(event_json.data(), event_json.size()); - socket->send(message, zmq::send_flags::dontwait); - } else { - DFTRACER_LOG_ERROR("ZeroMQWriter.log invalid", ""); - } -} - -void ZeroMQWriter::log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, ConstEventNameType ph, - ProcessID process_id, ThreadID thread_id, - bool is_string) { - DFTRACER_LOG_DEBUG("ZeroMQWriter.log_metadata", ""); - if (init) { - auto event_json = convert_metadata_event_to_json_string( - index, name, value, ph, process_id, thread_id); - zmq::message_t message(event_json.data(), event_json.size()); - socket->send(message, zmq::send_flags::dontwait); - } else { - DFTRACER_LOG_ERROR("ZeroMQWriter.log_metadata invalid", ""); - } -} - -void ZeroMQWriter::finalize(bool has_entry) { - DFTRACER_LOG_DEBUG("ZeroMQWriter.finalize", ""); - if (this->init) { - socket->close(); - context->close(); - this->init = false; - } else { - DFTRACER_LOG_ERROR("ZeroMQWriter.finalize invalid", ""); - } -} - -} // namespace dftracer \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0ec879fa..d98e2a89 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,20 +24,25 @@ endfunction() include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(test_cpp cpp/test.cpp) -target_link_libraries(test_cpp ${PROJECT_NAME}_dbg) +target_link_libraries(test_cpp PRIVATE ${PROJECT_NAME}_dbg) add_dependencies(test_cpp ${PROJECT_NAME}_dbg) add_dependencies(test_cpp ${PROJECT_NAME}_preload_dbg) add_library(testlib SHARED c/testlib.c) target_compile_options(testlib PRIVATE ${DFTRACER_FUNCTION_FLAGS}) + add_executable(test_c c/test.c) target_compile_options(test_c PRIVATE ${DFTRACER_FUNCTION_FLAGS}) -target_link_libraries(test_c ${PROJECT_NAME}_dbg testlib) +target_link_libraries(test_c PRIVATE testlib ${PROJECT_NAME}_dbg) add_dependencies(test_c ${PROJECT_NAME}_dbg) add_dependencies(test_c ${PROJECT_NAME}_preload_dbg) -add_executable(test_chrome_writer writer/test_chrome_writer.cpp) -target_link_libraries(test_chrome_writer PRIVATE ${PROJECT_NAME}_dbg) +if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_CHROME_FILE") + add_executable(test_chrome_writer writer/test_chrome_writer.cpp) + target_link_libraries(test_chrome_writer PRIVATE ${PROJECT_NAME}_dbg) + add_dependencies(test_chrome_writer ${PROJECT_NAME}_dbg) + add_dependencies(test_chrome_writer ${PROJECT_NAME}_preload_dbg) +endif() function(set_common_properties test_name) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=DEBUG) @@ -48,15 +53,18 @@ function(set_common_properties test_name) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_BIND_SIGNALS=0) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_WRITE_BUFFER_SIZE=4096) endfunction() file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data) -set(chrome_writer_test_name ChromeWriterPerformanceTest) -set(perf_output_file ${CMAKE_CURRENT_BINARY_DIR}/${chrome_writer_test_name}_output.jsonl) -df_add_test(${chrome_writer_test_name} $ ${perf_output_file}) -set_common_properties(${chrome_writer_test_name}) -set_property(TEST ${chrome_writer_test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=ERROR) +if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_CHROME_FILE") + set(chrome_writer_test_name ChromeWriterPerformanceTest) + set(perf_output_file ${CMAKE_CURRENT_BINARY_DIR}/${chrome_writer_test_name}_output.jsonl) + df_add_test(${chrome_writer_test_name} $ ${perf_output_file}) + set_common_properties(${chrome_writer_test_name}) + set_property(TEST ${chrome_writer_test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=ERROR) +endif() set(test_name test_cpp_basic_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data) diff --git a/test/writer/test_chrome_writer.cpp b/test/writer/test_chrome_writer.cpp index 19cf513b..52732b0c 100644 --- a/test/writer/test_chrome_writer.cpp +++ b/test/writer/test_chrome_writer.cpp @@ -8,9 +8,9 @@ #include #include "dftracer/core/typedef.h" -#include "dftracer/writer/chrome_writer.h" +#include "dftracer/writer/perfetto_chrome_file_writer.h" -static dftracer::ChromeWriter writer_instance; +static dftracer::PerfettoChromeFileWriter writer_instance; int main(int argc, char** argv) { std::string tmp_output_file = "perf_chrome_trace.json"; @@ -65,17 +65,19 @@ int main(int argc, char** argv) { double duration_s = static_cast(duration_ms) / 1000.0; std::cout << std::endl; - std::cout << "[ PERFORMANCE ] ChromeWriter: Logged " << num_events_to_log + std::cout << "[ PERFORMANCE ] PerfettoChromeFileWriter: Logged " + << num_events_to_log << " main events (plus some metadata events) in " << duration_s << " seconds." << std::endl; if (duration_s > 0) { - std::cout << "[ PERFORMANCE ] ChromeWriter: Throughput: " + std::cout << "[ PERFORMANCE ] PerfettoChromeFileWriter: Throughput: " << static_cast(num_events_to_log) / duration_s << " main events/sec." << std::endl; } else { - std::cout << "[ PERFORMANCE ] ChromeWriter: Duration too short to " - "calculate throughput accurately." - << std::endl; + std::cout + << "[ PERFORMANCE ] PerfettoChromeFileWriter: Duration too short to " + "calculate throughput accurately." + << std::endl; } std::ifstream file(tmp_output_file); From e3bcadaf4f9b6039d7cf540887192b374987f620 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 30 Jun 2025 21:29:46 -0700 Subject: [PATCH 05/33] Update VSCode settings for CMake configuration --- .vscode/settings.json | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index dbc03a47..f0b44fd5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,16 +1,26 @@ { "cmake.configureArgs": [ - "-DDFTRACER_INSTALL_DEPENDENCIES=OFF", - "-DDFTRACER_ENABLE_TESTS=ON", - "-DENABLE_PAPER_TESTS=OFF", + "-DCMAKE_C_COMPILER=/usr/tce/bin/gcc", + "-DCMAKE_CXX_COMPILER=/usr/tce/bin/g++", + "-DCMAKE_INSTALL_PREFIX=/usr/workspace/izzet/projects/dftracer-streaming/install", + "-DDFTRACER_BUILD_DEPENDENCIES=OFF", + "-DDFTRACER_DISABLE_HWLOC=ON", "-DDFTRACER_ENABLE_DLIO_BENCHMARK_TESTS=OFF", - "-DDFTRACER_DISABLE_HWLOC=OFF", - "-DCMAKE_INSTALL_PREFIX=/usr/workspace/haridev/dftracer/install" + "-DDFTRACER_ENABLE_PAPER_TESTS=OFF", + "-DDFTRACER_ENABLE_TESTS=ON", + "-DDFTRACER_INSTALL_DEPENDENCIES=OFF", + "-DDFTRACER_WRITER_TYPE=PERFETTO_PROTO_FILE" ], "cmake.configureEnvironment": { - "DARSHAN_PRELOAD_LIB": "/usr/WS2/haridev/spack/opt/spack/linux-rhel8-zen2/gcc-10.3.1/darshan-runtime-3.4.4-vckxthkq2hzzxnwmk4owtzcnfmjwl23s/lib/libdarshan.so", + // "DARSHAN_PRELOAD_LIB": "/usr/WS2/haridev/spack/opt/spack/linux-rhel8-zen2/gcc-10.3.1/darshan-runtime-3.4.4-vckxthkq2hzzxnwmk4owtzcnfmjwl23s/lib/libdarshan.so", "DFTRACER_TEST_MACHINE": "corona" }, + "C_Cpp.intelliSenseMemoryLimit": 16384, + "cSpell.words": [ + "DFTRACER", + "dlio" + ], + "editor.formatOnSave": true, "files.associations": { "any": "cpp", "functional": "cpp", @@ -96,9 +106,5 @@ "filesystem": "cpp", "*.in": "cpp" }, - "editor.formatOnSave": true, - "cSpell.words": [ - "DFTRACER", - "dlio" - ] + "git.ignoreLimitWarning": true } \ No newline at end of file From 00696fbf47b3ae087cc2dee23368873539d790b4 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 30 Jun 2025 21:30:03 -0700 Subject: [PATCH 06/33] Add 'tmp/' to .gitignore to exclude temporary files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 58067bac..95f58f5d 100644 --- a/.gitignore +++ b/.gitignore @@ -87,6 +87,7 @@ pydftracer.egg-info # Debug files /*.core +tmp/ dfanalyzer/dask/run_dir dfanalyzer/dask/logs From 85cc44ea3222d2aa96761a6fb0ce5c6a9569973f Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Sun, 6 Jul 2025 08:46:18 -0700 Subject: [PATCH 07/33] Refactor Perfetto writer classes and add file writer test implementation --- dependency/CMakeLists.txt | 4 +-- .../writer/perfetto_chrome_file_writer.h | 16 ++++++--- .../writer/perfetto_proto_file_writer.cpp | 2 +- .../writer/perfetto_proto_file_writer.h | 9 ++++- src/dftracer/writer/writer_base.h | 1 + test/CMakeLists.txt | 22 ++++++------ ...chrome_writer.cpp => test_file_writer.cpp} | 35 ++++++++++++++----- 7 files changed, 60 insertions(+), 29 deletions(-) rename test/writer/{test_chrome_writer.cpp => test_file_writer.cpp} (72%) diff --git a/dependency/CMakeLists.txt b/dependency/CMakeLists.txt index 723539b9..5a44c72d 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -32,10 +32,11 @@ if(DFTRACER_WRITER_TYPE MATCHES ".*PROTO.*") LOG_DOWNLOAD ON ) + set(PERFETTO_SDK_DIR "${CMAKE_BINARY_DIR}/src/perfetto/sdk") + set(PERFETTO_OUTPUT_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib64") set(PERFETTO_OUTPUT_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") - set(PERFETTO_SDK_DIR "${CMAKE_BINARY_DIR}/src/perfetto/sdk") set(PERFETTO_SDK_HEADER_PATH "${PERFETTO_OUTPUT_INCLUDE_DIR}/perfetto.h") set(PERFETTO_SDK_LIB_PATH "${PERFETTO_OUTPUT_LIB_DIR}/libperfetto_sdk.a") @@ -60,5 +61,4 @@ if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") install_external_project(zeromq 4.3.5 "zeromq" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") install_external_project(cppzmq 4.10.0 "cppzmq" https://github.com/zeromq/cppzmq.git v4.9.0 ${CMAKE_INSTALL_PREFIX} "-DCPPZMQ_BUILD_TESTS=OFF") add_dependencies(cppzmq zeromq) - add_dependencies(zeromq yaml-cpp) endif() diff --git a/src/dftracer/writer/perfetto_chrome_file_writer.h b/src/dftracer/writer/perfetto_chrome_file_writer.h index 0231a222..d2ebd9a1 100644 --- a/src/dftracer/writer/perfetto_chrome_file_writer.h +++ b/src/dftracer/writer/perfetto_chrome_file_writer.h @@ -26,13 +26,12 @@ namespace dftracer { class PerfettoChromeFileWriter : public WriterBase { protected: static const int MAX_LINE_SIZE = 16 * 1024L; - bool enable_compression; - bool is_first_write = true; + std::mutex mtx; + std::vector buffer; FILE *fh; size_t current_index = 0; size_t write_buffer_size; - std::vector buffer; - std::mutex mtx; + bool is_first_write = true; inline size_t flush_buffer_to_file(bool force = false) { std::unique_lock lock(mtx); @@ -64,8 +63,9 @@ class PerfettoChromeFileWriter : public WriterBase { DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.PerfettoChromeFileWriter", ""); auto conf = dftracer::Singleton::get_instance(); - enable_core_affinity = conf->core_affinity; enable_compression = conf->compression; + enable_core_affinity = conf->core_affinity; + include_metadata = conf->metadata; write_buffer_size = conf->write_buffer_size; { std::unique_lock lock(mtx); @@ -85,6 +85,12 @@ class PerfettoChromeFileWriter : public WriterBase { ConstEventNameType value, ConstEventNameType ph, ProcessID process_id, ThreadID tid, bool is_string = true); void finalize(bool has_entry); + void set_write_buffer_size(size_t buffer_size) { + std::unique_lock lock(mtx); + write_buffer_size = buffer_size; + buffer = std::vector(write_buffer_size + MAX_LINE_SIZE); + current_index = 0; + } private: std::string convert_metadata_to_json_string(MetadataMap *metadata); diff --git a/src/dftracer/writer/perfetto_proto_file_writer.cpp b/src/dftracer/writer/perfetto_proto_file_writer.cpp index 2df180e8..b88ef612 100644 --- a/src/dftracer/writer/perfetto_proto_file_writer.cpp +++ b/src/dftracer/writer/perfetto_proto_file_writer.cpp @@ -36,7 +36,7 @@ void PerfettoProtoFileWriter::initialize(char *filename, bool throw_error, perfetto::TrackEvent::Register(); perfetto::TraceConfig trace_config; - trace_config.add_buffers()->set_size_kb(1024 * 16); // 16MB buffer + trace_config.add_buffers()->set_size_kb(write_buffer_size / 1024); auto *data_source_config = trace_config.add_data_sources()->mutable_config(); data_source_config->set_name("track_event"); diff --git a/src/dftracer/writer/perfetto_proto_file_writer.h b/src/dftracer/writer/perfetto_proto_file_writer.h index ce3a19d5..498f69a8 100644 --- a/src/dftracer/writer/perfetto_proto_file_writer.h +++ b/src/dftracer/writer/perfetto_proto_file_writer.h @@ -18,11 +18,13 @@ #include #include #include + namespace dftracer { class PerfettoProtoFileWriter : public WriterBase { private: std::mutex mtx; std::unique_ptr tracing_session; + size_t write_buffer_size; void stream_main(std::unique_ptr session); @@ -31,8 +33,10 @@ class PerfettoProtoFileWriter : public WriterBase { DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.PerfettoProtoFileWriter", ""); auto conf = dftracer::Singleton::get_instance(); - include_metadata = conf->metadata; + enable_compression = conf->compression; enable_core_affinity = conf->core_affinity; + include_metadata = conf->metadata; + write_buffer_size = conf->write_buffer_size; } ~PerfettoProtoFileWriter() { DFTRACER_LOG_DEBUG("Destructing PerfettoProtoFileWriter", ""); @@ -46,6 +50,9 @@ class PerfettoProtoFileWriter : public WriterBase { ConstEventNameType value, ConstEventNameType ph, ProcessID process_id, ThreadID tid, bool is_string = true); void finalize(bool has_entry); + void set_write_buffer_size(size_t buffer_size) { + write_buffer_size = buffer_size; + } }; } // namespace dftracer diff --git a/src/dftracer/writer/writer_base.h b/src/dftracer/writer/writer_base.h index e1ba14cb..9f536ec0 100644 --- a/src/dftracer/writer/writer_base.h +++ b/src/dftracer/writer/writer_base.h @@ -14,6 +14,7 @@ class WriterBase { protected: std::string filename; HashType hostname_hash; + bool enable_compression = false; bool enable_core_affinity = false; bool include_metadata = false; bool init = false; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d98e2a89..2b793a79 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,11 +37,11 @@ target_link_libraries(test_c PRIVATE testlib ${PROJECT_NAME}_dbg) add_dependencies(test_c ${PROJECT_NAME}_dbg) add_dependencies(test_c ${PROJECT_NAME}_preload_dbg) -if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_CHROME_FILE") - add_executable(test_chrome_writer writer/test_chrome_writer.cpp) - target_link_libraries(test_chrome_writer PRIVATE ${PROJECT_NAME}_dbg) - add_dependencies(test_chrome_writer ${PROJECT_NAME}_dbg) - add_dependencies(test_chrome_writer ${PROJECT_NAME}_preload_dbg) +if(DFTRACER_WRITER_TYPE MATCHES ".*FILE.*") + add_executable(test_file_writer writer/test_file_writer.cpp) + target_link_libraries(test_file_writer PRIVATE ${PROJECT_NAME}) + add_dependencies(test_file_writer ${PROJECT_NAME}) + add_dependencies(test_file_writer ${PROJECT_NAME}_preload) endif() function(set_common_properties test_name) @@ -58,12 +58,12 @@ endfunction() file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data) -if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_CHROME_FILE") - set(chrome_writer_test_name ChromeWriterPerformanceTest) - set(perf_output_file ${CMAKE_CURRENT_BINARY_DIR}/${chrome_writer_test_name}_output.jsonl) - df_add_test(${chrome_writer_test_name} $ ${perf_output_file}) - set_common_properties(${chrome_writer_test_name}) - set_property(TEST ${chrome_writer_test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=ERROR) +if(DFTRACER_WRITER_TYPE MATCHES ".*FILE.*") + set(file_writer_test_name FileWriterPerformanceTest) + set(perf_output_file ${CMAKE_CURRENT_BINARY_DIR}/${file_writer_test_name}.out) + df_add_test(${file_writer_test_name} $ ${perf_output_file}) + set_common_properties(${file_writer_test_name}) + set_property(TEST ${file_writer_test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=0) endif() set(test_name test_cpp_basic_only) diff --git a/test/writer/test_chrome_writer.cpp b/test/writer/test_file_writer.cpp similarity index 72% rename from test/writer/test_chrome_writer.cpp rename to test/writer/test_file_writer.cpp index 52732b0c..cf373924 100644 --- a/test/writer/test_chrome_writer.cpp +++ b/test/writer/test_file_writer.cpp @@ -7,14 +7,20 @@ #include #include +#include "dftracer/dftracer_config.hpp" #include "dftracer/core/typedef.h" +#if DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE +#include "dftracer/writer/perfetto_proto_file_writer.h" +static dftracer::PerfettoProtoFileWriter writer_instance; +#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE #include "dftracer/writer/perfetto_chrome_file_writer.h" - static dftracer::PerfettoChromeFileWriter writer_instance; +#endif int main(int argc, char** argv) { - std::string tmp_output_file = "perf_chrome_trace.json"; + std::string tmp_output_file = "file_writer.out"; int num_events_to_log = 10000; + size_t writer_buffer_size = 4 * 1024 * 1024; // 4 MB default if (argc > 1) { tmp_output_file = argv[1]; @@ -31,7 +37,20 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } } + if (argc > 3) { + try { + writer_buffer_size = std::stoull(argv[3]); + } catch (const std::invalid_argument& ia) { + std::cerr << "Invalid argument for writer buffer size: " << argv[3] + << std::endl; + return EXIT_FAILURE; + } catch (const std::out_of_range& oor) { + std::cerr << "Writer buffer size out of range: " << argv[3] << std::endl; + return EXIT_FAILURE; + } + } + writer_instance.set_write_buffer_size(writer_buffer_size); writer_instance.initialize(const_cast(tmp_output_file.c_str()), false, const_cast("test_host_hash_perf")); @@ -65,19 +84,17 @@ int main(int argc, char** argv) { double duration_s = static_cast(duration_ms) / 1000.0; std::cout << std::endl; - std::cout << "[ PERFORMANCE ] PerfettoChromeFileWriter: Logged " - << num_events_to_log + std::cout << "[ PERFORMANCE ] FileWriter: Logged " << num_events_to_log << " main events (plus some metadata events) in " << duration_s << " seconds." << std::endl; if (duration_s > 0) { - std::cout << "[ PERFORMANCE ] PerfettoChromeFileWriter: Throughput: " + std::cout << "[ PERFORMANCE ] FileWriter: Throughput: " << static_cast(num_events_to_log) / duration_s << " main events/sec." << std::endl; } else { - std::cout - << "[ PERFORMANCE ] PerfettoChromeFileWriter: Duration too short to " - "calculate throughput accurately." - << std::endl; + std::cout << "[ PERFORMANCE ] FileWriter: Duration too short to " + "calculate throughput accurately." + << std::endl; } std::ifstream file(tmp_output_file); From 3893530c4a6f1611711a66d4b09d043ced08c60a Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Tue, 8 Jul 2025 08:44:45 -0700 Subject: [PATCH 08/33] Remove redundant initialization parameter --- src/dftracer/writer/perfetto_chrome_file_writer.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/dftracer/writer/perfetto_chrome_file_writer.h b/src/dftracer/writer/perfetto_chrome_file_writer.h index d2ebd9a1..5d11b27a 100644 --- a/src/dftracer/writer/perfetto_chrome_file_writer.h +++ b/src/dftracer/writer/perfetto_chrome_file_writer.h @@ -56,10 +56,7 @@ class PerfettoChromeFileWriter : public WriterBase { public: PerfettoChromeFileWriter() - : enable_compression(false), - is_first_write(false), - fh(nullptr), - write_buffer_size(0) { + : is_first_write(false), fh(nullptr), write_buffer_size(0) { DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.PerfettoChromeFileWriter", ""); auto conf = dftracer::Singleton::get_instance(); From 74517a902595cd9c3451e812aa5e5e1fdb555e1f Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Tue, 8 Jul 2025 09:47:55 -0700 Subject: [PATCH 09/33] Fix constructor member initialization order in PerfettoChromeFileWriter --- src/dftracer/writer/perfetto_chrome_file_writer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dftracer/writer/perfetto_chrome_file_writer.h b/src/dftracer/writer/perfetto_chrome_file_writer.h index 5d11b27a..54e92a10 100644 --- a/src/dftracer/writer/perfetto_chrome_file_writer.h +++ b/src/dftracer/writer/perfetto_chrome_file_writer.h @@ -56,7 +56,7 @@ class PerfettoChromeFileWriter : public WriterBase { public: PerfettoChromeFileWriter() - : is_first_write(false), fh(nullptr), write_buffer_size(0) { + : fh(nullptr), write_buffer_size(0), is_first_write(false) { DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.PerfettoChromeFileWriter", ""); auto conf = dftracer::Singleton::get_instance(); From fcea0ed16e50ae29d41c424619c56af5387bc051 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Tue, 8 Jul 2025 09:48:14 -0700 Subject: [PATCH 10/33] Refactor event logging in test_file_writer to use consistent variables and improve clarity --- test/writer/test_file_writer.cpp | 33 ++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/test/writer/test_file_writer.cpp b/test/writer/test_file_writer.cpp index cf373924..3cdfb100 100644 --- a/test/writer/test_file_writer.cpp +++ b/test/writer/test_file_writer.cpp @@ -54,25 +54,30 @@ int main(int argc, char** argv) { writer_instance.initialize(const_cast(tmp_output_file.c_str()), false, const_cast("test_host_hash_perf")); + const std::string detail_str = "performance_test_event_detail"; + const std::string another_key_str = "another_value_for_metadata_map"; + std::vector event_names; + event_names.reserve(num_events_to_log); + for (int i = 0; i < num_events_to_log; ++i) { + event_names.push_back("event_name_perf_" + std::to_string(i)); + } + auto start_time = std::chrono::high_resolution_clock::now(); + unsigned long long current_ts = + std::chrono::duration_cast( + start_time.time_since_epoch()) + .count(); + srand(time(0)); for (int i = 0; i < num_events_to_log; ++i) { std::unordered_map m; m["iteration"] = i; - m["detail"] = std::string( - "performance_test_event_detail_long_enough_to_test_string_handling"); - m["another_key"] = std::string("another_value_for_metadata_map_testing"); - writer_instance.log( - i, ("event_name_perf_" + std::to_string(i)).c_str(), "perf_category", - std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()) - .count(), - 100 + (i % 75), &m, 12345, 54321); - if (i % 1000 == 0) { - writer_instance.log_metadata(i, "metadata_event_name", - "metadata_event_value", "process_name_perf", - 12345, 54321); - } + m["detail"] = detail_str; + m["another_key"] = another_key_str; + int duration = 100 + (rand() % 101); + writer_instance.log(i, event_names[i].c_str(), "perf_category", current_ts, + duration, &m, 12345, 54321); + current_ts += duration + 1; } writer_instance.finalize(true); From 4d2a5cf8bc2f76140394cd8b4e725e5d1cc2b88b Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 14 Jul 2025 11:04:56 -0700 Subject: [PATCH 11/33] Add support for PERFETTO_CHROME_ZMQ writer type - Updated CMakeLists.txt to include new writer type options for PERFETTO_CHROME_ZMQ. - Modified configuration header files to define the new writer type. - Adjusted dependency management to handle ZeroMQ when the new writer type is selected. - Enhanced dftracer core to initialize and manage the new PERFETTO_CHROME_ZMQ writer. - Created new writer class PerfettoChromeZMQWriter that inherits from PerfettoChromeWriterBase. - Implemented buffer flushing and message sending logic for the new writer using ZeroMQ. - Updated logging and metadata handling in the new writer class. - Refactored existing PerfettoChromeFileWriter to share common functionality with the new writer base class. --- CMakeLists.txt | 15 +- cmake/configure_files/dftracer_config.hpp.in | 1 + .../dftracer_config_dbg.hpp.in | 1 + dependency/CMakeLists.txt | 2 +- src/dftracer/core/dftracer_main.cpp | 11 +- src/dftracer/core/enumeration.h | 18 +- src/dftracer/df_logger.h | 4 + src/dftracer/utils/configuration_manager.cpp | 2 +- .../writer/perfetto_chrome_file_writer.cpp | 237 ++++-------------- .../writer/perfetto_chrome_file_writer.h | 80 +----- .../writer/perfetto_chrome_writer_base.cpp | 162 ++++++++++++ .../writer/perfetto_chrome_writer_base.h | 93 +++++++ .../writer/perfetto_chrome_zmq_writer.cpp | 87 +++++++ .../writer/perfetto_chrome_zmq_writer.h | 44 ++++ 14 files changed, 487 insertions(+), 270 deletions(-) create mode 100644 src/dftracer/writer/perfetto_chrome_writer_base.cpp create mode 100644 src/dftracer/writer/perfetto_chrome_writer_base.h create mode 100644 src/dftracer/writer/perfetto_chrome_zmq_writer.cpp create mode 100644 src/dftracer/writer/perfetto_chrome_zmq_writer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 45929670..eda30b70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,14 +137,22 @@ option(DFTRACER_WRITER_TYPE "Writer Type" "PERFETTO_CHROME_FILE") if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ 0) set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 0) set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 1) elseif(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_FILE") set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ 0) set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 1) set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 0) +elseif(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_CHROME_ZMQ") + set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ 1) + set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 0) + set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 0) else() set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 1) + set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ 0) set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 0) set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 0) endif() @@ -284,7 +292,7 @@ else() endif() endif() - if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") + if(DFTRACER_WRITER_TYPE MATCHES ".*ZMQ.*") find_package(PkgConfig REQUIRED) pkg_check_modules(ZMQ REQUIRED libzmq) @@ -360,7 +368,11 @@ else() elseif(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ) list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/perfetto_proto_zmq_writer.cpp) elseif(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/perfetto_chrome_writer_base.cpp) list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/perfetto_chrome_file_writer.cpp) + elseif(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/perfetto_chrome_writer_base.cpp) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/writer/perfetto_chrome_zmq_writer.cpp) endif() set(DFTRACER_CORE_PUBLIC_INCLUDE @@ -783,6 +795,7 @@ else() DFTRACER_USE_CLANG_LIBCXX DFTRACER_WARNINGS_AS_ERRORS DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE + DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZEROMQ ) diff --git a/cmake/configure_files/dftracer_config.hpp.in b/cmake/configure_files/dftracer_config.hpp.in index 35624d04..bcabe57c 100644 --- a/cmake/configure_files/dftracer_config.hpp.in +++ b/cmake/configure_files/dftracer_config.hpp.in @@ -35,6 +35,7 @@ #cmakedefine DFTRACER_MPI_ENABLE 1 #cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" #cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE +#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ #cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE #cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ diff --git a/cmake/configure_files/dftracer_config_dbg.hpp.in b/cmake/configure_files/dftracer_config_dbg.hpp.in index 4d3b9be6..d5ba250e 100644 --- a/cmake/configure_files/dftracer_config_dbg.hpp.in +++ b/cmake/configure_files/dftracer_config_dbg.hpp.in @@ -35,6 +35,7 @@ #cmakedefine DFTRACER_MPI_ENABLE 1 #cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" #cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE +#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ #cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE #cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ diff --git a/dependency/CMakeLists.txt b/dependency/CMakeLists.txt index 5a44c72d..6b53fafa 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -57,7 +57,7 @@ if(DFTRACER_WRITER_TYPE MATCHES ".*PROTO.*") add_custom_target(perfetto_sdk ALL DEPENDS ${PERFETTO_SDK_LIB_PATH}) endif() -if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") +if(DFTRACER_WRITER_TYPE MATCHES ".*ZMQ.*") install_external_project(zeromq 4.3.5 "zeromq" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") install_external_project(cppzmq 4.10.0 "cppzmq" https://github.com/zeromq/cppzmq.git v4.9.0 ${CMAKE_INSTALL_PREFIX} "-DCPPZMQ_BUILD_TESTS=OFF") add_dependencies(cppzmq zeromq) diff --git a/src/dftracer/core/dftracer_main.cpp b/src/dftracer/core/dftracer_main.cpp index b91d9c97..6babe245 100644 --- a/src/dftracer/core/dftracer_main.cpp +++ b/src/dftracer/core/dftracer_main.cpp @@ -203,12 +203,17 @@ void dftracer::DFTracerCore::initialize(bool _bind, const char *_log_file, if (_log_file == nullptr) { if (!conf->log_file.empty()) { DFTRACER_LOG_DEBUG("Conf has log file %s", conf->log_file.c_str()); - if (conf->writer_type == WriterType::CHROME) { + if (conf->writer_type == WriterType::PERFETTO_CHROME_ZMQ || + conf->writer_type == WriterType::PERFETTO_PROTO_ZMQ) { + this->log_file = std::string(conf->log_file); + } else if (conf->writer_type == WriterType::PERFETTO_PROTO_FILE) { this->log_file = std::string(conf->log_file) + "-" + exec_name + "-" + std::to_string(this->process_id) + "-" + - log_file_suffix + ".pfw"; + log_file_suffix + ".ptrace"; } else { - this->log_file = std::string(conf->log_file); + this->log_file = std::string(conf->log_file) + "-" + exec_name + + "-" + std::to_string(this->process_id) + "-" + + log_file_suffix + ".pfw"; } } else { // GCOV_EXCL_START DFTRACER_LOG_ERROR(DFTRACER_UNDEFINED_LOG_FILE_MSG, ""); diff --git a/src/dftracer/core/enumeration.h b/src/dftracer/core/enumeration.h index 735dc146..fdba9a4a 100644 --- a/src/dftracer/core/enumeration.h +++ b/src/dftracer/core/enumeration.h @@ -5,8 +5,10 @@ #ifndef DFTRACER_ENUMERATION_H #define DFTRACER_ENUMERATION_H enum WriterType : uint8_t { - CHROME = 0, - ZEROMQ = 1, + PERFETTO_CHROME_FILE = 0, + PERFETTO_CHROME_ZMQ = 1, + PERFETTO_PROTO_FILE = 2, + PERFETTO_PROTO_ZMQ = 3, }; enum ProfilerStage : uint8_t { PROFILER_INIT = 0, @@ -49,12 +51,14 @@ inline void convert(const std::string &s, cpplogger::LoggerType &type) { } inline void convert(const std::string &s, WriterType &type) { - if (s == "CHROME") { - type = WriterType::CHROME; - } else if (s == "ZEROMQ") { - type = WriterType::ZEROMQ; + if (s == "PERFETTO_CHROME_ZMQ") { + type = WriterType::PERFETTO_CHROME_ZMQ; + } else if (s == "PERFETTO_PROTO_FILE") { + type = WriterType::PERFETTO_PROTO_FILE; + } else if (s == "PERFETTO_PROTO_ZMQ") { + type = WriterType::PERFETTO_PROTO_ZMQ; } else { - type = WriterType::CHROME; // Default to CHROME + type = WriterType::PERFETTO_CHROME_FILE; // Default to CHROME FILE } } diff --git a/src/dftracer/df_logger.h b/src/dftracer/df_logger.h index 18035f7c..97314875 100644 --- a/src/dftracer/df_logger.h +++ b/src/dftracer/df_logger.h @@ -18,6 +18,8 @@ #include #elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE #include +#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ +#include #endif #include #include @@ -49,6 +51,8 @@ using DFTWriter = dftracer::PerfettoProtoFileWriter; using DFTWriter = dftracer::PerfettoProtoZMQWriter; #elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE using DFTWriter = dftracer::PerfettoChromeFileWriter; +#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ +using DFTWriter = dftracer::PerfettoChromeZMQWriter; #endif class DFTLogger { diff --git a/src/dftracer/utils/configuration_manager.cpp b/src/dftracer/utils/configuration_manager.cpp index c209666b..a8def068 100644 --- a/src/dftracer/utils/configuration_manager.cpp +++ b/src/dftracer/utils/configuration_manager.cpp @@ -58,7 +58,7 @@ dftracer::ConfigurationManager::ConfigurationManager() bind_signals(false), throw_error(false), write_buffer_size(10), - writer_type(WriterType::CHROME) { + writer_type(WriterType::PERFETTO_CHROME_FILE) { const char *env_conf = getenv(DFTRACER_CONFIGURATION); YAML::Node config; if (env_conf != nullptr) { diff --git a/src/dftracer/writer/perfetto_chrome_file_writer.cpp b/src/dftracer/writer/perfetto_chrome_file_writer.cpp index b8ce117d..b475c1ab 100644 --- a/src/dftracer/writer/perfetto_chrome_file_writer.cpp +++ b/src/dftracer/writer/perfetto_chrome_file_writer.cpp @@ -23,6 +23,31 @@ bool dftracer::Singleton< dftracer::PerfettoChromeFileWriter>::stop_creating_instances = false; namespace dftracer { + +size_t PerfettoChromeFileWriter::flush_buffer_to_destination(bool force) { + std::unique_lock lock(mtx); + if (current_index == 0 || (!force && current_index < write_buffer_size)) + return 0; + DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.write_buffer_op %s", + this->filename.c_str()); + size_t written_elements = 0; + if (fh != nullptr) { + flockfile(fh); + written_elements = fwrite(buffer.data(), current_index, sizeof(char), fh); + size_t expected_elements = current_index; + current_index = 0; + funlockfile(fh); + if (written_elements != expected_elements) { + DFTRACER_LOG_ERROR( + "unable to log write only %ld of %ld trying to write %ld with error " + "code " + "%d", + written_elements, expected_elements, current_index, errno); + } + } + return written_elements; +} + void PerfettoChromeFileWriter::initialize(char *filename, bool throw_error, HashType hostname_hash) { this->hostname_hash = hostname_hash; @@ -35,6 +60,8 @@ void PerfettoChromeFileWriter::initialize(char *filename, bool throw_error, filename); // GCOVR_EXCL_LINE } else { setvbuf(fh, NULL, _IOLBF, write_buffer_size + 4096); + // Write opening bracket at the beginning + fwrite("[\n", sizeof(char), 2, fh); DFTRACER_LOG_INFO("created log file %s", filename); } } @@ -43,47 +70,12 @@ void PerfettoChromeFileWriter::initialize(char *filename, bool throw_error, this->filename.c_str()); } -void PerfettoChromeFileWriter::log(int index, ConstEventNameType event_name, - ConstEventNameType category, - TimeResolution start_time, - TimeResolution duration, - MetadataMap *metadata, ProcessID process_id, - ThreadID thread_id) { - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.log", ""); - - if (fh != nullptr) { - write_event_json_to_buffer(index, event_name, category, start_time, - duration, metadata, process_id, thread_id); - flush_buffer_to_file(false); - } else { - DFTRACER_LOG_ERROR("PerfettoChromeFileWriter.log invalid", ""); - } - is_first_write = false; -} - -void PerfettoChromeFileWriter::log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, - ConstEventNameType ph, - ProcessID process_id, ThreadID tid, - bool is_string) { - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.log_metadata", ""); - - if (fh != nullptr) { - write_metadata_json_to_buffer(index, name, value, ph, process_id, tid, - is_string); - flush_buffer_to_file(false); - } else { - DFTRACER_LOG_ERROR("PerfettoChromeFileWriter.log_metadata invalid", ""); - } - is_first_write = false; -} - void PerfettoChromeFileWriter::finalize(bool has_entry) { if (this->init) { DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.finalize", ""); if (fh != nullptr) { DFTRACER_LOG_INFO("Profiler finalizing writer %s", filename.c_str()); - flush_buffer_to_file(true); + flush_buffer_to_destination(true); fflush(fh); int status = fclose(fh); if (status != 0) { @@ -96,51 +88,39 @@ void PerfettoChromeFileWriter::finalize(bool has_entry) { df_unlink(filename.c_str()); } else { DFTRACER_LOG_INFO("Profiler writing the final symbol", ""); - fh = fopen(this->filename.c_str(), "r+"); + fh = fopen(this->filename.c_str(), "a"); if (fh != nullptr) { - std::string data = "[\n"; + std::string data = "]"; auto written_elements = fwrite(data.c_str(), sizeof(char), data.size(), fh); - if (written_elements != data.size()) { // GCOVR_EXCL_START + if (written_elements != data.size()) { DFTRACER_LOG_ERROR( - "unable to finalize log write %s for O_WRONLY written only %ld " - "of %ld", - filename.c_str(), data.size(), written_elements); - } // GCOVR_EXCL_STOP - data = "]"; - fseek(fh, 0, SEEK_END); - written_elements = - fwrite(data.c_str(), sizeof(char), data.size(), fh); - if (written_elements != data.size()) { // GCOVR_EXCL_START - DFTRACER_LOG_ERROR( - "unable to finalize log write %s for O_WRONLY written only %ld " - "of %ld", - filename.c_str(), data.size(), written_elements); - } // GCOVR_EXCL_STOP + "unable to finalize log write %s written only %zu of %zu", + filename.c_str(), written_elements, data.size()); + } status = fclose(fh); if (status != 0) { - DFTRACER_LOG_ERROR("unable to close log file %s for O_WRONLY", - filename.c_str()); // GCOVR_EXCL_LINE + DFTRACER_LOG_ERROR("unable to close log file %s for append", + filename.c_str()); } fh = nullptr; } - if (enable_compression) { - if (system("which gzip > /dev/null 2>&1")) { - DFTRACER_LOG_ERROR("Gzip compression does not exists", - ""); // GCOVR_EXCL_LINE - } else { - DFTRACER_LOG_INFO("Applying Gzip compression on file %s", + } + if (enable_compression) { + if (system("which gzip > /dev/null 2>&1")) { + DFTRACER_LOG_ERROR("Gzip compression does not exists", + ""); // GCOVR_EXCL_LINE + } else { + DFTRACER_LOG_INFO("Applying Gzip compression on file %s", + filename.c_str()); + char cmd[2048]; + sprintf(cmd, "gzip -f %s", filename.c_str()); + int ret = system(cmd); + if (ret == 0) { + DFTRACER_LOG_INFO("Successfully compressed file %s.gz", filename.c_str()); - char cmd[2048]; - sprintf(cmd, "gzip -f %s", filename.c_str()); - int ret = system(cmd); - if (ret == 0) { - DFTRACER_LOG_INFO("Successfully compressed file %s.gz", - filename.c_str()); - } else { - DFTRACER_LOG_ERROR("Unable to compress file %s", - filename.c_str()); - } + } else { + DFTRACER_LOG_ERROR("Unable to compress file %s", filename.c_str()); } } } @@ -156,119 +136,4 @@ void PerfettoChromeFileWriter::finalize(bool has_entry) { } } -void PerfettoChromeFileWriter::write_event_json_to_buffer( - int index, ConstEventNameType event_name, ConstEventNameType category, - TimeResolution start_time, TimeResolution duration, MetadataMap *metadata, - ProcessID process_id, ThreadID thread_id) { - size_t previous_index = 0; - (void)previous_index; - - char is_first_char[3] = " "; - if (!is_first_write) { - is_first_char[0] = '\0'; - } - - std::string metadata_json_string; - if (include_metadata) { - metadata_json_string = convert_metadata_to_json_string(metadata); - } - - { - std::unique_lock lock(mtx); - previous_index = current_index; - auto written_size = sprintf( - buffer.data() + current_index, - R"(%s{"id":%d,"name":"%s","cat":"%s","pid":%lu,"tid":%lu,"ts":%llu,"dur":%llu,"ph":"X"%s})", - is_first_char, index, event_name, category, process_id, thread_id, - start_time, duration, metadata_json_string.c_str()); - current_index += written_size; - buffer[current_index] = '\n'; - current_index++; - } - - DFTRACER_LOG_DEBUG( - "PerfettoChromeFileWriter.write_event_json_to_buffer %s on %s", - buffer.data() + previous_index, this->filename.c_str()); -} - -void PerfettoChromeFileWriter::write_metadata_json_to_buffer( - int index, ConstEventNameType name, ConstEventNameType value, - ConstEventNameType ph, ProcessID process_id, ThreadID thread_id, - bool is_string) { - size_t previous_index = 0; - (void)previous_index; - - char is_first_char[3] = " "; - if (!is_first_write) { - is_first_char[0] = '\0'; - } - - { - std::unique_lock lock(mtx); - previous_index = current_index; - auto written_size = 0; - if (is_string) { - written_size = sprintf( - buffer.data() + current_index, - R"(%s{"id":%d,"name":"%s","cat":"dftracer","pid":%lu,"tid":%lu,"ph":"M","args":{"hhash":"%s","name":"%s","value":"%s"}})", - is_first_char, index, ph, process_id, thread_id, this->hostname_hash, - name, value); - } else { - written_size = sprintf( - buffer.data() + current_index, - R"(%s{"id":%d,"name":"%s","cat":"dftracer","pid":%lu,"tid":%lu,"ph":"M","args":{"hhash":"%s","name":"%s","value":%s}})", - is_first_char, index, ph, process_id, thread_id, this->hostname_hash, - name, value); - } - current_index += written_size; - buffer[current_index] = '\n'; - current_index++; - } - - DFTRACER_LOG_DEBUG( - "PerfettoChromeFileWriter.write_metadata_json_to_buffer %s on %s", - buffer.data() + previous_index, this->filename.c_str()); -} - -std::string PerfettoChromeFileWriter::convert_metadata_to_json_string( - MetadataMap *metadata) { - std::stringstream metadata_stream; - if (metadata != nullptr && !metadata->empty()) { - metadata_stream << R"(,"args":{"hhash":")" << this->hostname_hash << "\""; - for (const auto &item : *metadata) { - metadata_stream << ","; - metadata_stream << "\"" << item.first << "\":"; - if (item.second.type() == typeid(unsigned int)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(int)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(const char *)) { - metadata_stream << "\"" << std::any_cast(item.second) - << "\""; - } else if (item.second.type() == typeid(std::string)) { - metadata_stream << "\"" << std::any_cast(item.second) - << "\""; - } else if (item.second.type() == typeid(size_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(uint16_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(HashType)) { - metadata_stream << "\"" << std::any_cast(item.second) << "\""; - } else if (item.second.type() == typeid(long)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(ssize_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(off_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.type() == typeid(off64_t)) { - metadata_stream << std::any_cast(item.second); - } else { - DFTRACER_LOG_INFO("No conversion for type %s", item.first.c_str()); - } - } - metadata_stream << "}"; - } - return metadata_stream.str(); -} - } // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/writer/perfetto_chrome_file_writer.h b/src/dftracer/writer/perfetto_chrome_file_writer.h index 54e92a10..0fb29048 100644 --- a/src/dftracer/writer/perfetto_chrome_file_writer.h +++ b/src/dftracer/writer/perfetto_chrome_file_writer.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include @@ -23,85 +23,23 @@ #include namespace dftracer { -class PerfettoChromeFileWriter : public WriterBase { - protected: - static const int MAX_LINE_SIZE = 16 * 1024L; - std::mutex mtx; - std::vector buffer; +class PerfettoChromeFileWriter : public PerfettoChromeWriterBase { + private: FILE *fh; - size_t current_index = 0; - size_t write_buffer_size; - bool is_first_write = true; - inline size_t flush_buffer_to_file(bool force = false) { - std::unique_lock lock(mtx); - if (current_index == 0 || (!force && current_index < write_buffer_size)) - return 0; - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.write_buffer_op %s", - this->filename.c_str()); - size_t written_elements = 0; - flockfile(fh); - written_elements = fwrite(buffer.data(), current_index, sizeof(char), fh); - current_index = 0; - funlockfile(fh); - if (written_elements != 1) { - DFTRACER_LOG_ERROR( - "unable to log write only %ld of %d trying to write %ld with error " - "code " - "%d", - written_elements, 1, current_index, errno); - } - return written_elements; - } + protected: + size_t flush_buffer_to_destination(bool force = false) override; public: - PerfettoChromeFileWriter() - : fh(nullptr), write_buffer_size(0), is_first_write(false) { + PerfettoChromeFileWriter() : fh(nullptr) { DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.PerfettoChromeFileWriter", ""); - auto conf = - dftracer::Singleton::get_instance(); - enable_compression = conf->compression; - enable_core_affinity = conf->core_affinity; - include_metadata = conf->metadata; - write_buffer_size = conf->write_buffer_size; - { - std::unique_lock lock(mtx); - buffer = std::vector(write_buffer_size + MAX_LINE_SIZE); - current_index = 0; - } } ~PerfettoChromeFileWriter() { DFTRACER_LOG_DEBUG("Destructing PerfettoChromeFileWriter", ""); } - void initialize(char *filename, bool throw_error, HashType hostname_hash); - void log(int index, ConstEventNameType event_name, - ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, MetadataMap *metadata, ProcessID process_id, - ThreadID tid); - void log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, ConstEventNameType ph, - ProcessID process_id, ThreadID tid, bool is_string = true); - void finalize(bool has_entry); - void set_write_buffer_size(size_t buffer_size) { - std::unique_lock lock(mtx); - write_buffer_size = buffer_size; - buffer = std::vector(write_buffer_size + MAX_LINE_SIZE); - current_index = 0; - } - - private: - std::string convert_metadata_to_json_string(MetadataMap *metadata); - void write_event_json_to_buffer(int index, ConstEventNameType event_name, - ConstEventNameType category, - TimeResolution start_time, - TimeResolution duration, - MetadataMap *metadata, ProcessID process_id, - ThreadID thread_id); - void write_metadata_json_to_buffer(int index, ConstEventNameType name, - ConstEventNameType value, - ConstEventNameType ph, - ProcessID process_id, ThreadID thread_id, - bool is_string); + void initialize(char *filename, bool throw_error, + HashType hostname_hash) override; + void finalize(bool has_entry) override; }; } // namespace dftracer diff --git a/src/dftracer/writer/perfetto_chrome_writer_base.cpp b/src/dftracer/writer/perfetto_chrome_writer_base.cpp new file mode 100644 index 00000000..c52592f3 --- /dev/null +++ b/src/dftracer/writer/perfetto_chrome_writer_base.cpp @@ -0,0 +1,162 @@ +// +// Created for shared Chrome writer functionality +// + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace dftracer { + +void PerfettoChromeWriterBase::log(int index, ConstEventNameType event_name, + ConstEventNameType category, + TimeResolution start_time, + TimeResolution duration, + MetadataMap *metadata, ProcessID process_id, + ThreadID thread_id) { + DFTRACER_LOG_DEBUG("PerfettoChromeWriterBase.log", ""); + + write_event_json_to_buffer(index, event_name, category, start_time, duration, + metadata, process_id, thread_id); + flush_buffer_to_destination(false); + is_first_write = false; +} + +void PerfettoChromeWriterBase::log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, + ConstEventNameType ph, + ProcessID process_id, ThreadID tid, + bool is_string) { + DFTRACER_LOG_DEBUG("PerfettoChromeWriterBase.log_metadata", ""); + + write_metadata_json_to_buffer(index, name, value, ph, process_id, tid, + is_string); + flush_buffer_to_destination(false); + is_first_write = false; +} + +void PerfettoChromeWriterBase::write_event_json_to_buffer( + int index, ConstEventNameType event_name, ConstEventNameType category, + TimeResolution start_time, TimeResolution duration, MetadataMap *metadata, + ProcessID process_id, ThreadID thread_id) { + size_t previous_index = 0; + (void)previous_index; + + char is_first_char[3] = ""; + if (!is_first_write) { + strcpy(is_first_char, ","); + } + + std::string metadata_json_string; + if (include_metadata) { + metadata_json_string = convert_metadata_to_json_string(metadata); + } + + { + std::unique_lock lock(mtx); + previous_index = current_index; + auto written_size = sprintf( + buffer.data() + current_index, + R"(%s{"id":%d,"name":"%s","cat":"%s","pid":%lu,"tid":%lu,"ts":%llu,"dur":%llu,"ph":"X"%s})", + is_first_char, index, event_name, category, process_id, thread_id, + start_time, duration, metadata_json_string.c_str()); + current_index += written_size; + buffer[current_index] = '\n'; + current_index++; + } + + DFTRACER_LOG_DEBUG( + "PerfettoChromeWriterBase.write_event_json_to_buffer %s on %s", + buffer.data() + previous_index, this->filename.c_str()); +} + +void PerfettoChromeWriterBase::write_metadata_json_to_buffer( + int index, ConstEventNameType name, ConstEventNameType value, + ConstEventNameType ph, ProcessID process_id, ThreadID thread_id, + bool is_string) { + size_t previous_index = 0; + (void)previous_index; + + char is_first_char[3] = ""; + if (!is_first_write) { + strcpy(is_first_char, ","); + } + + { + std::unique_lock lock(mtx); + previous_index = current_index; + auto written_size = 0; + if (is_string) { + written_size = sprintf( + buffer.data() + current_index, + R"(%s{"id":%d,"name":"%s","cat":"dftracer","pid":%lu,"tid":%lu,"ph":"M","args":{"hhash":"%s","name":"%s","value":"%s"}})", + is_first_char, index, ph, process_id, thread_id, this->hostname_hash, + name, value); + } else { + written_size = sprintf( + buffer.data() + current_index, + R"(%s{"id":%d,"name":"%s","cat":"dftracer","pid":%lu,"tid":%lu,"ph":"M","args":{"hhash":"%s","name":"%s","value":%s}})", + is_first_char, index, ph, process_id, thread_id, this->hostname_hash, + name, value); + } + current_index += written_size; + buffer[current_index] = '\n'; + current_index++; + } + + DFTRACER_LOG_DEBUG( + "PerfettoChromeWriterBase.write_metadata_json_to_buffer %s on %s", + buffer.data() + previous_index, this->filename.c_str()); +} + +std::string PerfettoChromeWriterBase::convert_metadata_to_json_string( + MetadataMap *metadata) { + std::stringstream metadata_stream; + if (metadata != nullptr && !metadata->empty()) { + metadata_stream << R"(,"args":{"hhash":")" << this->hostname_hash << "\""; + for (const auto &item : *metadata) { + metadata_stream << ","; + metadata_stream << "\"" << item.first << "\":"; + if (item.second.type() == typeid(unsigned int)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(int)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(const char *)) { + metadata_stream << "\"" << std::any_cast(item.second) + << "\""; + } else if (item.second.type() == typeid(std::string)) { + metadata_stream << "\"" << std::any_cast(item.second) + << "\""; + } else if (item.second.type() == typeid(size_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(uint16_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(HashType)) { + metadata_stream << "\"" << std::any_cast(item.second) << "\""; + } else if (item.second.type() == typeid(long)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(ssize_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(off_t)) { + metadata_stream << std::any_cast(item.second); + } else if (item.second.type() == typeid(off64_t)) { + metadata_stream << std::any_cast(item.second); + } else { + DFTRACER_LOG_INFO("No conversion for type %s", item.first.c_str()); + } + } + metadata_stream << "}"; + } + return metadata_stream.str(); +} + +} // namespace dftracer diff --git a/src/dftracer/writer/perfetto_chrome_writer_base.h b/src/dftracer/writer/perfetto_chrome_writer_base.h new file mode 100644 index 00000000..386e400c --- /dev/null +++ b/src/dftracer/writer/perfetto_chrome_writer_base.h @@ -0,0 +1,93 @@ +// +// Created for shared Chrome writer functionality +// + +#ifndef DFTRACER_PERFETTO_CHROME_WRITER_BASE_H +#define DFTRACER_PERFETTO_CHROME_WRITER_BASE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace dftracer { +class PerfettoChromeWriterBase : public WriterBase { + protected: + static const int MAX_LINE_SIZE = 16 * 1024L; + std::mutex mtx; + std::vector buffer; + size_t current_index = 0; + size_t write_buffer_size; + bool is_first_write = true; + + // Pure virtual method for flushing buffer - to be implemented by derived + // classes + virtual size_t flush_buffer_to_destination(bool force = false) = 0; + + public: + PerfettoChromeWriterBase() : write_buffer_size(0), is_first_write(true) { + DFTRACER_LOG_DEBUG("PerfettoChromeWriterBase.PerfettoChromeWriterBase", ""); + auto conf = + dftracer::Singleton::get_instance(); + enable_compression = conf->compression; + enable_core_affinity = conf->core_affinity; + include_metadata = conf->metadata; + write_buffer_size = conf->write_buffer_size; + { + std::unique_lock lock(mtx); + buffer = std::vector(write_buffer_size + MAX_LINE_SIZE); + current_index = 0; + } + } + + virtual ~PerfettoChromeWriterBase() { + DFTRACER_LOG_DEBUG("Destructing PerfettoChromeWriterBase", ""); + } + + void log(int index, ConstEventNameType event_name, + ConstEventNameType category, TimeResolution start_time, + TimeResolution duration, MetadataMap *metadata, ProcessID process_id, + ThreadID tid) override; + + void log_metadata(int index, ConstEventNameType name, + ConstEventNameType value, ConstEventNameType ph, + ProcessID process_id, ThreadID tid, + bool is_string = true) override; + + void set_write_buffer_size(size_t buffer_size) { + std::unique_lock lock(mtx); + write_buffer_size = buffer_size; + buffer = std::vector(write_buffer_size + MAX_LINE_SIZE); + current_index = 0; + } + + protected: + std::string convert_metadata_to_json_string(MetadataMap *metadata); + void write_event_json_to_buffer(int index, ConstEventNameType event_name, + ConstEventNameType category, + TimeResolution start_time, + TimeResolution duration, + MetadataMap *metadata, ProcessID process_id, + ThreadID thread_id); + void write_metadata_json_to_buffer(int index, ConstEventNameType name, + ConstEventNameType value, + ConstEventNameType ph, + ProcessID process_id, ThreadID thread_id, + bool is_string); +}; +} // namespace dftracer + +#endif // DFTRACER_PERFETTO_CHROME_WRITER_BASE_H diff --git a/src/dftracer/writer/perfetto_chrome_zmq_writer.cpp b/src/dftracer/writer/perfetto_chrome_zmq_writer.cpp new file mode 100644 index 00000000..9d855238 --- /dev/null +++ b/src/dftracer/writer/perfetto_chrome_zmq_writer.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +template <> +std::shared_ptr + dftracer::Singleton::instance = nullptr; +template <> +bool dftracer::Singleton< + dftracer::PerfettoChromeZMQWriter>::stop_creating_instances = false; + +namespace dftracer { + +size_t PerfettoChromeZMQWriter::flush_buffer_to_destination(bool force) { + std::unique_lock lock(mtx); + if (current_index == 0 || (!force && current_index < write_buffer_size)) + return 0; + DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter.flush_buffer_to_stream %s", + this->filename.c_str()); + + size_t bytes_to_send = current_index; + if (socket && bytes_to_send > 0) { + try { + // Create ZMQ message from buffer content + zmq::message_t message(buffer.data(), bytes_to_send); + auto result = socket->send(message, zmq::send_flags::dontwait); + if (result) { + DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter sent %zu bytes", + bytes_to_send); + current_index = 0; // Reset buffer after successful send + return bytes_to_send; + } else { + DFTRACER_LOG_ERROR("PerfettoChromeZMQWriter failed to send message", + ""); + return 0; + } + } catch (const zmq::error_t& e) { + DFTRACER_LOG_ERROR("PerfettoChromeZMQWriter ZMQ error: %s", e.what()); + return 0; + } + } + return 0; +} + +void PerfettoChromeZMQWriter::initialize(char* filename, bool throw_error, + HashType hostname_hash) { + this->hostname_hash = hostname_hash; + this->throw_error = throw_error; + this->filename = filename; + + context = std::make_unique(1); + socket = std::make_unique(*context, zmq::socket_type::push); + if (!socket) { + DFTRACER_LOG_ERROR("unable to create ZeroMQ socket %s", filename); + } + socket->connect(filename); + + init = true; + DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter.initialize %s", + this->filename.c_str()); +} + +void PerfettoChromeZMQWriter::finalize(bool has_entry) { + if (init) { + DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter.finalize", ""); + + socket->close(); + context->close(); + + init = false; + + DFTRACER_LOG_DEBUG("Finished writer finalization", ""); + } else { + DFTRACER_LOG_DEBUG("Already finalized writer", ""); + } +} + +} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/writer/perfetto_chrome_zmq_writer.h b/src/dftracer/writer/perfetto_chrome_zmq_writer.h new file mode 100644 index 00000000..1a725a0a --- /dev/null +++ b/src/dftracer/writer/perfetto_chrome_zmq_writer.h @@ -0,0 +1,44 @@ +#ifndef DFTRACER_PERFETTO_CHROME_ZMQ_WRITER_H +#define DFTRACER_PERFETTO_CHROME_ZMQ_WRITER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dftracer { +class PerfettoChromeZMQWriter : public PerfettoChromeWriterBase { + private: + std::unique_ptr context; + std::unique_ptr socket; + + protected: + size_t flush_buffer_to_destination(bool force = false) override; + + public: + PerfettoChromeZMQWriter() { + DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter.PerfettoChromeZMQWriter", ""); + } + ~PerfettoChromeZMQWriter() { + DFTRACER_LOG_DEBUG("Destructing PerfettoChromeZMQWriter", ""); + } + void initialize(char *filename, bool throw_error, + HashType hostname_hash) override; + void finalize(bool has_entry) override; +}; +} // namespace dftracer + +#endif // DFTRACER_PERFETTO_CHROME_ZMQ_WRITER_H From 512b94ea2a5ba78edfec30d021a20fb7fd28a875 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 14 Jul 2025 11:05:12 -0700 Subject: [PATCH 12/33] Update PerfettoProtoFileWriter initialization and remove redundant mutex --- src/dftracer/writer/perfetto_proto_file_writer.cpp | 5 +++-- src/dftracer/writer/perfetto_proto_file_writer.h | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dftracer/writer/perfetto_proto_file_writer.cpp b/src/dftracer/writer/perfetto_proto_file_writer.cpp index b88ef612..61ae51fe 100644 --- a/src/dftracer/writer/perfetto_proto_file_writer.cpp +++ b/src/dftracer/writer/perfetto_proto_file_writer.cpp @@ -36,7 +36,9 @@ void PerfettoProtoFileWriter::initialize(char *filename, bool throw_error, perfetto::TrackEvent::Register(); perfetto::TraceConfig trace_config; - trace_config.add_buffers()->set_size_kb(write_buffer_size / 1024); + trace_config.set_flush_period_ms(200); + auto *buffer_config = trace_config.add_buffers(); + buffer_config->set_size_kb(write_buffer_size / 1024); auto *data_source_config = trace_config.add_data_sources()->mutable_config(); data_source_config->set_name("track_event"); @@ -70,7 +72,6 @@ void PerfettoProtoFileWriter::log(int index, ConstEventNameType event_name, DFTRACER_LOG_ERROR("PerfettoProtoFileWriter not initialized", ""); return; } - std::lock_guard lock(mtx); perfetto::TrackEvent::Trace([&](perfetto::TrackEvent::TraceContext ctx) { auto packet = ctx.NewTracePacket(); diff --git a/src/dftracer/writer/perfetto_proto_file_writer.h b/src/dftracer/writer/perfetto_proto_file_writer.h index 498f69a8..7b60995b 100644 --- a/src/dftracer/writer/perfetto_proto_file_writer.h +++ b/src/dftracer/writer/perfetto_proto_file_writer.h @@ -22,7 +22,6 @@ namespace dftracer { class PerfettoProtoFileWriter : public WriterBase { private: - std::mutex mtx; std::unique_ptr tracing_session; size_t write_buffer_size; From 21791a2b381824510ea76cecc5bc777d537b3bb0 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 28 Jul 2025 12:18:11 -0700 Subject: [PATCH 13/33] Update default writer type to PERFETTO_CHROME_ZMQ --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eda30b70..fc9bf15b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,7 +133,7 @@ if(DFTRACER_ENABLE_MPI) set(DFTRACER_MPI_ENABLE 1) endif() -option(DFTRACER_WRITER_TYPE "Writer Type" "PERFETTO_CHROME_FILE") +option(DFTRACER_WRITER_TYPE "Writer Type" "PERFETTO_CHROME_ZMQ") if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) From 0051fd4e9d1f923555e8018a29184aafb8d19309 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 28 Jul 2025 13:08:21 -0700 Subject: [PATCH 14/33] Set default CMake policy version for external project installations --- cmake/modules/dftracer-utils.cmake | 1 + dependency/CMakeLists.txt | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/modules/dftracer-utils.cmake b/cmake/modules/dftracer-utils.cmake index f4b8076f..7d8d82dc 100644 --- a/cmake/modules/dftracer-utils.cmake +++ b/cmake/modules/dftracer-utils.cmake @@ -149,6 +149,7 @@ function(install_external_project name version var_name url tag install_prefix c -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_INSTALL_PREFIX=${install_prefix} + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ${configure_args} BUILD_COMMAND make -j INSTALL_COMMAND make install -j diff --git a/dependency/CMakeLists.txt b/dependency/CMakeLists.txt index 6b53fafa..5433ba6f 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -1,7 +1,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/dftracer-utils.cmake) install_external_project(cpp-logger 1.0.0 "CPP_LOGGER" https://github.com/hariharan-devarajan/cpp-logger.git v0.0.4 ${CMAKE_INSTALL_PREFIX} "") -install_external_project(gotcha 2.3.2 "gotcha" https://github.com/LLNL/GOTCHA.git 1.0.7 ${CMAKE_INSTALL_PREFIX} "-DCMAKE_POLICY_VERSION_MINIMUM=3.5") +install_external_project(gotcha 2.3.2 "gotcha" https://github.com/LLNL/GOTCHA.git 1.0.7 ${CMAKE_INSTALL_PREFIX} "") install_external_project(brahma 2.1.0 "BRAHMA" https://github.com/hariharan-devarajan/brahma.git v0.0.10 ${CMAKE_INSTALL_PREFIX} "") add_dependencies(brahma cpp-logger) add_dependencies(brahma gotcha) @@ -9,7 +9,7 @@ add_dependencies(brahma gotcha) find_package(yaml-cpp QUIET) if(NOT ${yaml-cpp_FOUND}) - install_external_project(yaml-cpp "" "YAML_CPP" https://github.com/jbeder/yaml-cpp.git yaml-cpp-0.6.3 ${CMAKE_INSTALL_PREFIX} "-DYAML_CPP_BUILD_TESTS=OFF;-DYAML_BUILD_SHARED_LIBS=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5") + install_external_project(yaml-cpp "" "YAML_CPP" https://github.com/jbeder/yaml-cpp.git yaml-cpp-0.6.3 ${CMAKE_INSTALL_PREFIX} "-DYAML_CPP_BUILD_TESTS=OFF;-DYAML_BUILD_SHARED_LIBS=ON;") add_dependencies(yaml-cpp brahma) add_dependencies(yaml-cpp gotcha) add_dependencies(yaml-cpp cpp-logger) @@ -18,7 +18,7 @@ endif() install_external_project(pybind11 2.12.0 "pybind11" https://github.com/pybind/pybind11.git v2.12.0 ${CMAKE_INSTALL_PREFIX} "-DPYBIND11_TEST=OFF") if(DFTRACER_WRITER_TYPE MATCHES ".*PROTO.*") - install_external_project(protobuf 31.1 "protobuf" https://github.com/protocolbuffers/protobuf.git v31.1 ${CMAKE_INSTALL_PREFIX} "-Dprotobuf_BUILD_TESTS=OFF;-Dprotobuf_BUILD_EXAMPLES=OFF;-Dprotobuf_BUILD_LIBPROTOC=ON;-Dprotobuf_BUILD_SHARED_LIBS=ON;-Dprotobuf_WITH_ZLIB=OFF;-DCMAKE_POLICY_VERSION_MINIMUM=3.5") + install_external_project(protobuf 31.1 "protobuf" https://github.com/protocolbuffers/protobuf.git v31.1 ${CMAKE_INSTALL_PREFIX} "-Dprotobuf_BUILD_TESTS=OFF;-Dprotobuf_BUILD_EXAMPLES=OFF;-Dprotobuf_BUILD_LIBPROTOC=ON;-Dprotobuf_BUILD_SHARED_LIBS=ON;-Dprotobuf_WITH_ZLIB=OFF;") ExternalProject_Add( perfetto From 4565449fc02f3ee0945e92628184c90523e77200 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 28 Jul 2025 14:12:45 -0700 Subject: [PATCH 15/33] Refactor ZeroMQ references to use 'zmq' for consistency and clarity in CMake configuration --- CMakeLists.txt | 4 ++-- dependency/CMakeLists.txt | 4 ++-- setup.py | 14 ++++++++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc9bf15b..6b9a6abf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,11 +297,11 @@ else() pkg_check_modules(ZMQ REQUIRED libzmq) if(ZMQ_FOUND) - message(STATUS "[DFTRACER] Found ZeroMQ at ${ZMQ_INCLUDE_DIRS}") + message(STATUS "[DFTRACER] Found zmq at ${ZMQ_INCLUDE_DIRS}") include_directories(${ZMQ_INCLUDE_DIRS}) set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZMQ_LIBRARIES}) else() - message(FATAL_ERROR "-- [DFTRACER] ZeroMQ is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'PERFETTO_PROTO_ZMQ'") + message(FATAL_ERROR "-- [DFTRACER] zmq is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'PERFETTO_*_ZMQ'") endif() find_path(CPPZMQ_INCLUDE_DIR zmq.hpp) diff --git a/dependency/CMakeLists.txt b/dependency/CMakeLists.txt index 5433ba6f..733f0d24 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -58,7 +58,7 @@ if(DFTRACER_WRITER_TYPE MATCHES ".*PROTO.*") endif() if(DFTRACER_WRITER_TYPE MATCHES ".*ZMQ.*") - install_external_project(zeromq 4.3.5 "zeromq" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") + install_external_project(zmq 4.3.5 "zmq" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") install_external_project(cppzmq 4.10.0 "cppzmq" https://github.com/zeromq/cppzmq.git v4.9.0 ${CMAKE_INSTALL_PREFIX} "-DCPPZMQ_BUILD_TESTS=OFF") - add_dependencies(cppzmq zeromq) + add_dependencies(cppzmq zmq) endif() diff --git a/setup.py b/setup.py index 62d21dbb..da0686cf 100644 --- a/setup.py +++ b/setup.py @@ -18,10 +18,9 @@ } - - def myversion_func(version: ScmVersion) -> str: from setuptools_scm.version import only_version + return version.format_next_version(only_version, fmt="{tag}.dev{distance}") @@ -78,7 +77,9 @@ def build_extension(self, ext: CMakeExtension) -> None: # Using this requires trailing slash for auto-detection & inclusion of # auxiliary "native" libs - build_type = os.environ.get("DFTRACER_BUILD_TYPE", "Release") # Setting this to release causes memory issues with GCC-13. + build_type = os.environ.get( + "DFTRACER_BUILD_TYPE", "Release" + ) # Setting this to release causes memory issues with GCC-13. cmake_args += [f"-DCMAKE_BUILD_TYPE={build_type}"] enable_ftracing = os.environ.get("DFTRACER_ENABLE_FTRACING", "OFF") cmake_args += [f"-DDFTRACER_ENABLE_FTRACING={enable_ftracing}"] @@ -109,6 +110,9 @@ def build_extension(self, ext: CMakeExtension) -> None: test_ld_library_path = os.environ.get("DFTRACER_TEST_LD_LIBRARY_PATH", "") cmake_args += [f"-DDFTRACER_TEST_LD_LIBRARY_PATH={test_ld_library_path}"] + writer_type = os.environ.get("DFTRACER_WRITER_TYPE", "PERFETTO_CHROME_FILE") + cmake_args += [f"-DDFTRACER_WRITER_TYPE={writer_type}"] + # CMake lets you override the generator - we need to check this. # Can be set with Conda-Build, for example. cmake_generator = os.environ.get("CMAKE_GENERATOR", "") @@ -177,7 +181,9 @@ def build_extension(self, ext: CMakeExtension) -> None: name="pydftracer", use_scm_version={"version_scheme": myversion_func}, packages=( - find_namespace_packages(include=["dftracer", "dftracer.dbg", "dftracer.logger", "dfanalyzer"]) + find_namespace_packages( + include=["dftracer", "dftracer.dbg", "dftracer.logger", "dfanalyzer"] + ) ), ext_modules=[ CMakeExtension("dftracer.pydftracer"), From 231a63c6e2f72581226f7c8a0503981a6733a18d Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 28 Jul 2025 14:20:51 -0700 Subject: [PATCH 16/33] Rename ZMQ references to ZeroMQ for consistency in CMake configuration --- CMakeLists.txt | 12 ++++++------ dependency/CMakeLists.txt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b9a6abf..7c2f7ceb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,14 +294,14 @@ else() if(DFTRACER_WRITER_TYPE MATCHES ".*ZMQ.*") find_package(PkgConfig REQUIRED) - pkg_check_modules(ZMQ REQUIRED libzmq) + pkg_check_modules(ZeroMQ REQUIRED libzmq) - if(ZMQ_FOUND) - message(STATUS "[DFTRACER] Found zmq at ${ZMQ_INCLUDE_DIRS}") - include_directories(${ZMQ_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZMQ_LIBRARIES}) + if(ZeroMQ_FOUND) + message(STATUS "[DFTRACER] Found ZeroMQ at ${ZeroMQ_INCLUDE_DIRS}") + include_directories(${ZeroMQ_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZeroMQ_LIBRARIES}) else() - message(FATAL_ERROR "-- [DFTRACER] zmq is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'PERFETTO_*_ZMQ'") + message(FATAL_ERROR "-- [DFTRACER] ZeroMQ is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'PERFETTO_*_ZMQ'") endif() find_path(CPPZMQ_INCLUDE_DIR zmq.hpp) diff --git a/dependency/CMakeLists.txt b/dependency/CMakeLists.txt index 733f0d24..369b69cb 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -58,7 +58,7 @@ if(DFTRACER_WRITER_TYPE MATCHES ".*PROTO.*") endif() if(DFTRACER_WRITER_TYPE MATCHES ".*ZMQ.*") - install_external_project(zmq 4.3.5 "zmq" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") + install_external_project(ZeroMQ 4.3.5 "ZeroMQ" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") install_external_project(cppzmq 4.10.0 "cppzmq" https://github.com/zeromq/cppzmq.git v4.9.0 ${CMAKE_INSTALL_PREFIX} "-DCPPZMQ_BUILD_TESTS=OFF") - add_dependencies(cppzmq zmq) + add_dependencies(cppzmq ZeroMQ) endif() From 5977455375e12b6a4a9fa468c01e488fb623150d Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 28 Jul 2025 20:06:29 -0700 Subject: [PATCH 17/33] Implement fork handling for ZeroMQ socket reinitialization in child processes --- .../writer/perfetto_chrome_zmq_writer.cpp | 49 ++++++++++++++++++- .../writer/perfetto_chrome_zmq_writer.h | 6 +++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/dftracer/writer/perfetto_chrome_zmq_writer.cpp b/src/dftracer/writer/perfetto_chrome_zmq_writer.cpp index 9d855238..d3d2e702 100644 --- a/src/dftracer/writer/perfetto_chrome_zmq_writer.cpp +++ b/src/dftracer/writer/perfetto_chrome_zmq_writer.cpp @@ -20,6 +20,15 @@ bool dftracer::Singleton< namespace dftracer { +static PerfettoChromeZMQWriter* writer_instance = nullptr; + +void on_fork_child() { + if (writer_instance) { + DFTRACER_LOG_DEBUG("Fork child: re-initializing ZMQ socket.", ""); + writer_instance->reconnect(); + } +} + size_t PerfettoChromeZMQWriter::flush_buffer_to_destination(bool force) { std::unique_lock lock(mtx); if (current_index == 0 || (!force && current_index < write_buffer_size)) @@ -64,9 +73,14 @@ void PerfettoChromeZMQWriter::initialize(char* filename, bool throw_error, } socket->connect(filename); + writer_instance = this; + + pthread_atfork(nullptr, nullptr, on_fork_child); + init = true; - DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter.initialize %s", - this->filename.c_str()); + DFTRACER_LOG_DEBUG( + "PerfettoChromeZMQWriter.initialize on %s with fork handling", + this->filename.c_str()); } void PerfettoChromeZMQWriter::finalize(bool has_entry) { @@ -76,6 +90,10 @@ void PerfettoChromeZMQWriter::finalize(bool has_entry) { socket->close(); context->close(); + if (writer_instance == this) { + writer_instance = nullptr; + } + init = false; DFTRACER_LOG_DEBUG("Finished writer finalization", ""); @@ -84,4 +102,31 @@ void PerfettoChromeZMQWriter::finalize(bool has_entry) { } } +void PerfettoChromeZMQWriter::reconnect() { + DFTRACER_LOG_DEBUG("Child process starting ZMQ reconnect", ""); + + // Release ownership of the inherited pointers. + // This prevents the destructor (and zmq_close) from being called. + // The old state is invalid and must be abandoned. + if (socket) socket.release(); + if (context) context.release(); + + DFTRACER_LOG_DEBUG("Child process abandoned inherited ZMQ state", ""); + + // Create a brand new context and socket for this child process. + context = std::make_unique(1); + socket = std::make_unique(*context, zmq::socket_type::push); + + if (!socket) { + DFTRACER_LOG_ERROR("Unable to create new ZeroMQ socket in child for %s", + this->filename.c_str()); + return; + } + + // Connect the new socket to the original destination. + socket->connect(this->filename.c_str()); + DFTRACER_LOG_DEBUG("Child process successfully reconnected ZMQ socket to %s", + this->filename.c_str()); +} + } // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/writer/perfetto_chrome_zmq_writer.h b/src/dftracer/writer/perfetto_chrome_zmq_writer.h index 1a725a0a..36c7960c 100644 --- a/src/dftracer/writer/perfetto_chrome_zmq_writer.h +++ b/src/dftracer/writer/perfetto_chrome_zmq_writer.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,11 @@ class PerfettoChromeZMQWriter : public PerfettoChromeWriterBase { void initialize(char *filename, bool throw_error, HashType hostname_hash) override; void finalize(bool has_entry) override; + /** + * @brief Re-initializes the ZMQ socket. This is intended to be called + * in a child process after a fork(). + */ + void reconnect(); }; } // namespace dftracer From 4635ced9eff3990b14139377f10d697c5034db2c Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 28 Jul 2025 20:17:18 -0700 Subject: [PATCH 18/33] Add DFTRACER_WRITER_TYPE environment variable and update logging initialization logic --- dftracer/dbg/logger/logger.py | 7 +++++-- dftracer/logger/logger.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dftracer/dbg/logger/logger.py b/dftracer/dbg/logger/logger.py index 47956cea..d410f4d2 100644 --- a/dftracer/dbg/logger/logger.py +++ b/dftracer/dbg/logger/logger.py @@ -6,10 +6,12 @@ DFTRACER_ENABLE_ENV = "DFTRACER_ENABLE" DFTRACER_INIT_ENV = "DFTRACER_INIT" DFTRACER_LOG_LEVEL_ENV = "DFTRACER_LOG_LEVEL" +DFTRACER_WRITER_TYPE_ENV = "DFTRACER_WRITER_TYPE" DFTRACER_ENABLE = True if os.getenv(DFTRACER_ENABLE_ENV, '0') == '1' else False DFTRACER_INIT_PRELOAD = True if os.getenv(DFTRACER_INIT_ENV, 'PRELOAD') == 'PRELOAD' else False DFTRACER_LOG_LEVEL = os.getenv(DFTRACER_LOG_LEVEL_ENV, 'ERROR') +DFTRACER_WRITER_TYPE = os.getenv(DFTRACER_WRITER_TYPE_ENV, 'PERFETTO_CHROME_FILE') from pathlib import Path import inspect @@ -55,12 +57,13 @@ def get_instance(cls): @staticmethod def initialize_log(logfile, data_dir, process_id): + is_streaming = 'ZMQ' in DFTRACER_WRITER_TYPE log_file_path = None - if logfile: + if logfile and not is_streaming: log_file_path = Path(logfile) outfile = "dft.log" if DFTRACER_ENABLE: - if log_file_path: + if log_file_path and not is_streaming: os.makedirs(log_file_path.parent, exist_ok=True) outfile = os.path.join(log_file_path.parent, "dft.log") log_level = logging.ERROR diff --git a/dftracer/logger/logger.py b/dftracer/logger/logger.py index 69eced8a..1523c3b5 100644 --- a/dftracer/logger/logger.py +++ b/dftracer/logger/logger.py @@ -6,10 +6,12 @@ DFTRACER_ENABLE_ENV = "DFTRACER_ENABLE" DFTRACER_INIT_ENV = "DFTRACER_INIT" DFTRACER_LOG_LEVEL_ENV = "DFTRACER_LOG_LEVEL" +DFTRACER_WRITER_TYPE_ENV = "DFTRACER_WRITER_TYPE" DFTRACER_ENABLE = True if os.getenv(DFTRACER_ENABLE_ENV, '0') == '1' else False DFTRACER_INIT_PRELOAD = True if os.getenv(DFTRACER_INIT_ENV, 'PRELOAD') == 'PRELOAD' else False DFTRACER_LOG_LEVEL = os.getenv(DFTRACER_LOG_LEVEL_ENV, 'ERROR') +DFTRACER_WRITER_TYPE = os.getenv(DFTRACER_WRITER_TYPE_ENV, 'PERFETTO_CHROME_FILE') from pathlib import Path import inspect @@ -55,12 +57,13 @@ def get_instance(cls): @staticmethod def initialize_log(logfile, data_dir, process_id): + is_streaming = 'ZMQ' in DFTRACER_WRITER_TYPE log_file_path = None - if logfile: + if logfile and not is_streaming: log_file_path = Path(logfile) outfile = "dft.log" if DFTRACER_ENABLE: - if log_file_path: + if log_file_path and not is_streaming: os.makedirs(log_file_path.parent, exist_ok=True) outfile = os.path.join(log_file_path.parent, "dft.log") log_level = logging.ERROR From 4143c5ed75d854439b607d48f9e4843fa23f49bf Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Sun, 4 Jan 2026 17:19:33 +0300 Subject: [PATCH 19/33] feat: Replace ZMQ writer with a new Mofka writer and introduce a writer interface. --- CMakeLists.txt | 1136 +++++++---------- cmake/configure_files/dftracer_config.hpp.in | 6 +- .../dftracer_config_dbg.hpp.in | 6 +- dependency/CMakeLists.txt | 58 +- setup.py | 3 +- src/dftracer/core/buffer/buffer.cpp | 25 +- src/dftracer/core/buffer/buffer.h | 10 +- src/dftracer/core/common/dftracer_main.cpp | 20 +- src/dftracer/core/common/enumeration.h | 33 +- src/dftracer/core/df_logger.h | 59 +- src/dftracer/core/serialization/json_line.cpp | 50 +- .../core/utils/configuration_manager.cpp | 68 +- src/dftracer/core/writer/mofka_writer.cpp | 95 ++ src/dftracer/core/writer/mofka_writer.h | 32 + .../writer/perfetto_chrome_file_writer.cpp | 175 --- .../core/writer/perfetto_chrome_file_writer.h | 47 - .../writer/perfetto_chrome_writer_base.cpp | 160 --- .../core/writer/perfetto_chrome_writer_base.h | 94 -- .../writer/perfetto_chrome_zmq_writer.cpp | 132 -- .../core/writer/perfetto_chrome_zmq_writer.h | 51 - .../writer/perfetto_proto_file_writer.cpp | 159 --- .../core/writer/perfetto_proto_file_writer.h | 59 - .../core/writer/perfetto_proto_zmq_writer.cpp | 184 --- .../core/writer/perfetto_proto_zmq_writer.h | 59 - src/dftracer/core/writer/stdio_writer.h | 10 +- src/dftracer/core/writer/writer_base.h | 40 - src/dftracer/core/writer/writer_interface.h | 16 + test/CMakeLists.txt | 151 +-- test/c/test.c | 6 +- test/check_mofka_topic.py | 141 ++ test/cpp/test.cpp | 5 +- test/mofka.config.json | 61 + test/mofka.flock.json | 12 + test/mofka_server_start.sh | 6 + test/mofka_server_stop.sh | 3 + test/writer/test_file_writer.cpp | 121 -- 36 files changed, 1062 insertions(+), 2231 deletions(-) create mode 100644 src/dftracer/core/writer/mofka_writer.cpp create mode 100644 src/dftracer/core/writer/mofka_writer.h delete mode 100644 src/dftracer/core/writer/perfetto_chrome_file_writer.cpp delete mode 100644 src/dftracer/core/writer/perfetto_chrome_file_writer.h delete mode 100644 src/dftracer/core/writer/perfetto_chrome_writer_base.cpp delete mode 100644 src/dftracer/core/writer/perfetto_chrome_writer_base.h delete mode 100644 src/dftracer/core/writer/perfetto_chrome_zmq_writer.cpp delete mode 100644 src/dftracer/core/writer/perfetto_chrome_zmq_writer.h delete mode 100644 src/dftracer/core/writer/perfetto_proto_file_writer.cpp delete mode 100644 src/dftracer/core/writer/perfetto_proto_file_writer.h delete mode 100644 src/dftracer/core/writer/perfetto_proto_zmq_writer.cpp delete mode 100644 src/dftracer/core/writer/perfetto_proto_zmq_writer.h delete mode 100644 src/dftracer/core/writer/writer_base.h create mode 100644 src/dftracer/core/writer/writer_interface.h create mode 100644 test/check_mofka_topic.py create mode 100644 test/mofka.config.json create mode 100644 test/mofka.flock.json create mode 100755 test/mofka_server_start.sh create mode 100755 test/mofka_server_stop.sh delete mode 100644 test/writer/test_file_writer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index df546344..dcf76ea0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 3.5...3.18) +#------------------------------------------------------------------------------ +# Version information +#------------------------------------------------------------------------------ set(DFTRACER_VERSION_MAJOR "4") set(DFTRACER_VERSION_MINOR "0") @@ -19,395 +22,352 @@ project(dftracer LANGUAGES C CXX) string(TOUPPER "${PROJECT_NAME}" UPPER_PROJECT_NAME) string(TOLOWER "${PROJECT_NAME}" LOWER_PROJECT_NAME) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-empty-body -Wno-format-extra-args") - -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ # Internal Includes for header and libraries -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ # Get installation directories -- these get used in various places; # best to just make them available -option(DFTRACER_LIBDIR_AS_LIB OFF) - -if(NOT DFTRACER_LIBDIR_AS_LIB) - include(GNUInstallDirs) -endif() - +option (DFTRACER_LIBDIR_AS_LIB OFF) +if (NOT DFTRACER_LIBDIR_AS_LIB) + include(GNUInstallDirs) +endif () # -if(CMAKE_INSTALL_LIBDIR) - message(STATUS "CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}") - set(DFTRACER_LIBDIR ${CMAKE_INSTALL_LIBDIR}) - set(DFTRACER_INSTALL_INCLUDE_DIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) - set(DFTRACER_INSTALL_DOCDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}) - set(DFTRACER_INSTALL_SYSCONFDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/modulefiles) - set(DFTRACER_INSTALL_BINFDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}) -else() - set(DFTRACER_LIBDIR "lib") - set(DFTRACER_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") - set(DFTRACER_INSTALL_DOCDIR "${CMAKE_INSTALL_PREFIX}/doc") - set(DFTRACER_INSTALL_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc/modulefiles") - set(DFTRACER_INSTALL_BINARYDIR "${CMAKE_INSTALL_PREFIX}/bin") - message(STATUS "DFTRACER_LIBDIR set to ${DFTRACER_LIBDIR}") -endif() - -# ------------------------------------------------------------------------------ +if (CMAKE_INSTALL_LIBDIR) + message(STATUS "CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}") + set(DFTRACER_LIBDIR ${CMAKE_INSTALL_LIBDIR}) + set(DFTRACER_INSTALL_INCLUDE_DIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) + set(DFTRACER_INSTALL_DOCDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}) + set(DFTRACER_INSTALL_SYSCONFDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/modulefiles) + set(DFTRACER_INSTALL_BINFDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}) +else () + set(DFTRACER_LIBDIR "lib") + set(DFTRACER_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") + set(DFTRACER_INSTALL_DOCDIR "${CMAKE_INSTALL_PREFIX}/doc") + set(DFTRACER_INSTALL_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc/modulefiles") + set(DFTRACER_INSTALL_BINARYDIR "${CMAKE_INSTALL_PREFIX}/bin") + message(STATUS "DFTRACER_LIBDIR set to ${DFTRACER_LIBDIR}") +endif () + +#------------------------------------------------------------------------------ # Internal Paths for cmake libraries and Setup install and output Directories -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ # This sets where to look for dependent libraries set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_BINARY_DIR} ${CMAKE_INSTALL_PREFIX}) - # This sets where to look for dependent library's cmake files list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/cmake) list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}/share/cmake) -# ------------------------------------------------------------------------------ -if(NOT DFTRACER_EXTERNALLY_CONFIGURED) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Single Directory for all Executables.") - set(CMAKE_INCLUDE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/include CACHE PATH "Store the headers.") - set(EXECUTABLE_OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all Libraries") - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all static libraries.") -endif() +#------------------------------------------------------------------------------ +if (NOT DFTRACER_EXTERNALLY_CONFIGURED) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Single Directory for all Executables.") + set(CMAKE_INCLUDE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/include CACHE PATH "Store the headers.") + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all Libraries") + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all static libraries.") +endif () include_directories(${CMAKE_BINARY_DIR}/include) link_directories(${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -# ----------------------------------------------------------------------------- +#----------------------------------------------------------------------------- # Targets built within this project are exported at Install time for use # by other projects. -# ----------------------------------------------------------------------------- -if(NOT DFTRACER_EXPORTED_TARGETS) - set(DFTRACER_EXPORTED_TARGETS "dftracer-targets") -endif() +#----------------------------------------------------------------------------- +if (NOT DFTRACER_EXPORTED_TARGETS) + set(DFTRACER_EXPORTED_TARGETS "dftracer-targets") +endif () include(dftracer-utils) - -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ # Build options -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ # option(ENABLE_DFTRACER_DEBUG "Include debugging prints and logging" OFF) # This is not needed as we have CMAKE_BUILD_TYPE # This is verbose, maybe an alternate might help simplify -# option(BUILD_URPC "Build DFTRACER's URPC code" OFF) -# option(ENABLE_PERFFLOW "Build with PerfFlow Aspect support" OFF) -# option(ENABLE_UCX_DTL "Build DFTRACER's UCX data transport layer" OFF) +#option(BUILD_URPC "Build DFTRACER's URPC code" OFF) +#option(ENABLE_PERFFLOW "Build with PerfFlow Aspect support" OFF) +#option(ENABLE_UCX_DTL "Build DFTRACER's UCX data transport layer" OFF) # This option is off by default because non-developers should not use # this option under normal circumstances. option(DFTRACER_WARNINGS_AS_ERRORS "Build with warnings promoted to errors." OFF) mark_as_advanced(DFTRACER_WARNINGS_AS_ERRORS) -option(DFTRACER_USE_CLANG_LIBCXX OFF) - -if(DFTRACER_USE_CLANG_LIBCXX) - set(GCC_TOOLCHAIN "") -endif(DFTRACER_USE_CLANG_LIBCXX) +option (DFTRACER_USE_CLANG_LIBCXX OFF) +if (DFTRACER_USE_CLANG_LIBCXX) + set (GCC_TOOLCHAIN "") +endif (DFTRACER_USE_CLANG_LIBCXX) # Options -option(DFTRACER_DISABLE_HWLOC "Disable HWLOC" On) - -if(NOT DFTRACER_DISABLE_HWLOC) - set(DFTRACER_HWLOC_ENABLE 1) +option (DFTRACER_DISABLE_HWLOC "Disable HWLOC" On) +if (NOT DFTRACER_DISABLE_HWLOC) + set(DFTRACER_HWLOC_ENABLE 1) endif() # Options -option(DFTRACER_ENABLE_FTRACING "Enable Function Tracing" OFF) - -if(DFTRACER_ENABLE_FTRACING) - set(DFTRACER_FTRACING_ENABLE 1) - set(DFTRACER_FUNCTION_FLAGS "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default") +option (DFTRACER_ENABLE_FTRACING "Enable Function Tracing" OFF) +if (DFTRACER_ENABLE_FTRACING) + set(DFTRACER_FTRACING_ENABLE 1) + set(DFTRACER_FUNCTION_FLAGS "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default") else() - set(DFTRACER_FUNCTION_FLAGS) + set(DFTRACER_FUNCTION_FLAGS ) endif() # Options -option(DFTRACER_ENABLE_HIP_TRACING "Enable HIP Tracing" OFF) - -if(DFTRACER_ENABLE_HIP_TRACING) - set(DFTRACER_HIP_TRACING_ENABLE 1) +option (DFTRACER_ENABLE_HIP_TRACING "Enable HIP Tracing" OFF) +if (DFTRACER_ENABLE_HIP_TRACING) + set(DFTRACER_HIP_TRACING_ENABLE 1) endif() -option(DFTRACER_ENABLE_MPI "Enable MPI" OFF) - -if(DFTRACER_ENABLE_MPI) - set(DFTRACER_MPI_ENABLE 1) +option (DFTRACER_ENABLE_MPI "Enable MPI" OFF) +if (DFTRACER_ENABLE_MPI) + set(DFTRACER_MPI_ENABLE 1) endif() - -option(DFTRACER_WRITER_TYPE "Writer Type" "PERFETTO_CHROME_ZMQ") - -if(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_ZMQ") - set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 1) -elseif(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_PROTO_FILE") - set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 1) - set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 0) -elseif(DFTRACER_WRITER_TYPE STREQUAL "PERFETTO_CHROME_ZMQ") - set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ 1) - set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 0) -else() - set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE 1) - set(DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE 0) - set(DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ 0) +option (DFTRACER_BUILD_PYTHON_BINDINGS "Build python bindings." ON) +set(DFTRACER_PYTHON_EXE "python3" CACHE STRING "Python executable to use for building.") +if(DEFINED ENV{DFTRACER_PYTHON_EXE}) + set(DFTRACER_PYTHON_EXE $ENV{DFTRACER_PYTHON_EXE} CACHE STRING "Python executable to use for building." FORCE) endif() -option(DFTRACER_BUILD_PYTHON_BINDINGS "Build python bindings." ON) -set(DFTRACER_PYTHON_EXE "python3" CACHE STRING "Python executable to use for building.") set(DFTRACER_PYTHON_SITE $ENV{DFTRACER_PYTHON_SITE} CACHE STRING "Python site packages to use for building.") - -if(NOT DFTRACER_PYTHON_EXEC STREQUAL "OFF") - set(PYTHON_EXECUTABLE ${DFTRACER_PYTHON_EXEC}) +if(NOT DFTRACER_PYTHON_SITE AND DEFINED ENV{DFTRACER_PYTHON_SITE}) + set(DFTRACER_PYTHON_SITE $ENV{DFTRACER_PYTHON_SITE} CACHE STRING "Python site packages to use for building." FORCE) endif() -if(DFTRACER_BUILD_PYTHON_BINDINGS) - if(DFTRACER_PYTHON_SITE) - set(PYTHON_SITE_PACKAGES "${DFTRACER_PYTHON_SITE}") - set(MAIN_PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES}) - else() - set(PYTHON_SITE_PACKAGES ${CMAKE_INSTALL_PREFIX}) - execute_process(COMMAND ${DFTRACER_PYTHON_EXE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE MAIN_PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() - - include_directories(${PYTHON_SITE_PACKAGES}/dftracer/include) - link_directories(${PYTHON_SITE_PACKAGES}/dftracer/lib) +if (DFTRACER_BUILD_PYTHON_BINDINGS) + if (DFTRACER_PYTHON_SITE) + set(PYTHON_SITE_PACKAGES "${DFTRACER_PYTHON_SITE}") + set(MAIN_PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES}) + else() + set(PYTHON_SITE_PACKAGES ${CMAKE_INSTALL_PREFIX}) + execute_process (COMMAND ${DFTRACER_PYTHON_EXE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE MAIN_PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + include_directories(${PYTHON_SITE_PACKAGES}/dftracer/include) + link_directories(${PYTHON_SITE_PACKAGES}/dftracer/lib) endif() # install dependency -option(DFTRACER_INSTALL_DEPENDENCIES "Install DFTracer dependencies" OFF) +option (DFTRACER_INSTALL_DEPENDENCIES "Install DFTracer dependencies" OFF) # testing -option(DFTRACER_ENABLE_TESTS "Enable tests for DFTRACER." OFF) -option(DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS "Enable dlio_benchmark tests" OFF) -option(DFTRACER_ENABLE_PAPER_TESTS "Enable paper tests" OFF) -set(DFTRACER_TEST_LD_LIBRARY_PATH "" CACHE STRING "Additional LD_LIBRARY_PATH to be included on testing") +option (DFTRACER_ENABLE_TESTS "Enable tests for DFTRACER." OFF) +option (DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS "Enable dlio_benchmark tests" OFF) +option (DFTRACER_ENABLE_PAPER_TESTS "Enable paper tests" OFF) +set (DFTRACER_TEST_LD_LIBRARY_PATH "" CACHE STRING "Additional LD_LIBRARY_PATH to be included on testing") option(DFTRACER_ENABLE_NATIVE_SCRIPT "Build with native scripting support." OFF) -# ------------------------------------------------------------------------------ +option(DFTRACER_WRITER_TYPE "Writer Type" "STDIO") +if(DFTRACER_WRITER_TYPE STREQUAL "MOFKA") + set(DFTRACER_WRITER_TYPE_STDIO 0) + set(DFTRACER_WRITER_TYPE_MOFKA 1) +else() + set(DFTRACER_WRITER_TYPE_STDIO 1) + set(DFTRACER_WRITER_TYPE_MOFKA 0) +endif() + +#------------------------------------------------------------------------------ # Compiler setup -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ include(ExternalProject) - # It requires include(GNUInstallDirs) before if that is needed include(SetupCompiler) -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ # Build Type based configurations -# ------------------------------------------------------------------------------ -if(CMAKE_BUILD_TYPE STREQUAL "") - set(CMAKE_BUILD_TYPE "Release") # Setting default as Release -endif() +#------------------------------------------------------------------------------ -if(NOT DEFINED BUILD_SHARED_LIBS) - set(BUILD_SHARED_LIBS ON) +if(CMAKE_BUILD_TYPE STREQUAL "") + set(CMAKE_BUILD_TYPE "Release") # Setting default as Release endif() -# ------------------------------------------------------------------------------ +if (NOT DEFINED BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS ON) +endif () +#------------------------------------------------------------------------------ # Disallow in-source build -# ------------------------------------------------------------------------------ -if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") - message(FATAL_ERROR - "${PROJECT_NAME} requires an out of source Build. " - "Please create a separate binary directory and run CMake there.") -endif() - -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ +if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") + message(FATAL_ERROR + "${PROJECT_NAME} requires an out of source Build. " + "Please create a separate binary directory and run CMake there.") +endif () +#------------------------------------------------------------------------------ # Set a default build type if none was specified -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") - set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) - - # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" - "MinSizeRel" "RelWithDebInfo") -endif() - -# ------------------------------------------------------------------------------ +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" + "MinSizeRel" "RelWithDebInfo") +endif () +#------------------------------------------------------------------------------ # Dependencies -# ------------------------------------------------------------------------------ -if(DFTRACER_INSTALL_DEPENDENCIES) - message(STATUS "[${PROJECT_NAME}] downloading dependencies. Please run make for downloading depedencies and then do reconfigure without dependency flag.") - message(STATUS "[${PROJECT_NAME}] Installing depedencies at ${CMAKE_INSTALL_PREFIX}") - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/dependency) -else() - # Required Dependencies - # ============================================================================= - set(DEPENDENCY_LIB ${CMAKE_EXE_LINKER_FLAGS} $ENV{LDFLAGS} -lpthread) - set(DEPENDENCY_LIBRARY_DIRS "") +#------------------------------------------------------------------------------ - find_package(cpp-logger 1.0.0 REQUIRED) +if (DFTRACER_INSTALL_DEPENDENCIES) + message(STATUS "[${PROJECT_NAME}] downloading dependencies. Please run make for downloading depedencies and then do reconfigure without dependency flag.") + message(STATUS "[${PROJECT_NAME}] Installing depedencies at ${CMAKE_INSTALL_PREFIX}") + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/dependency) +else() +# Required Dependencies +# ============================================================================= +set(DEPENDENCY_LIB ${CMAKE_EXE_LINKER_FLAGS} $ENV{LDFLAGS} -lpthread) +set(DEPENDENCY_LIBRARY_DIRS "") - if(${cpp-logger_FOUND}) +find_package(cpp-logger 1.0.0 REQUIRED) +if (${cpp-logger_FOUND}) include_directories(${CPP_LOGGER_INCLUDE_DIRS}) set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${CPP_LOGGER_LIBRARIES}) set(CPP_LOGGER_LIBRARY_DIR ${cpp-logger_DIR}/../../) - # Get absolute path for CPP_LOGGER_LIBRARY_DIR get_filename_component(CPP_LOGGER_LIBRARY_DIR "${CPP_LOGGER_LIBRARY_DIR}" ABSOLUTE) - - if(DEFINED CPP_LOGGER_LIBRARY_DIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${CPP_LOGGER_LIBRARY_DIR}) + if (DEFINED CPP_LOGGER_LIBRARY_DIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${CPP_LOGGER_LIBRARY_DIR}) endif() - message(STATUS "[CPP_LOGGER] found cpp-logger at ${CPP_LOGGER_INCLUDE_DIRS}") - else() - message(FATAL_ERROR "-- [CPP_LOGGER] is needed for ${PROJECT_NAME} build") - endif() +else () + message(FATAL_ERROR "-- [CPP_LOGGER] is needed for ${PROJECT_NAME} build") +endif () - find_package(brahma 3.0.0 REQUIRED) - - if(${brahma_FOUND}) +find_package(brahma 3.0.0 REQUIRED) +if (${brahma_FOUND}) message(STATUS "[BRAHMA] found brahma at ${BRAHMA_INCLUDE_DIRS}") include_directories(${BRAHMA_INCLUDE_DIRS}) set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${BRAHMA_LIBRARIES}) set(BRAHMA_LIBRARY_DIR ${brahma_DIR}/../../) - # Get absolute path for BRAHMA_LIBRARY_DIR get_filename_component(BRAHMA_LIBRARY_DIR "${BRAHMA_LIBRARY_DIR}" ABSOLUTE) - - if(DEFINED BRAHMA_LIBRARY_DIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${BRAHMA_LIBRARY_DIR}) + if (DEFINED BRAHMA_LIBRARY_DIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${BRAHMA_LIBRARY_DIR}) endif() - else() +else () message(FATAL_ERROR "-- [BRAHMA] is needed for ${PROJECT_NAME} build") - endif() +endif () - find_package(yaml-cpp REQUIRED) - - if(${yaml-cpp_FOUND}) +find_package(yaml-cpp REQUIRED) +if (${yaml-cpp_FOUND}) message(STATUS "[DFTRACER] found yaml-cpp at ${YAML_CPP_INCLUDE_DIR}") include_directories(${YAML_CPP_INCLUDE_DIR}) set(YAML_CPP_LIBRARY_DIR ${yaml-cpp_DIR}/../../) - # Get absolute path for YAML_CPP_LIBRARY_DIR get_filename_component(YAML_CPP_LIBRARY_DIR "${YAML_CPP_LIBRARY_DIR}" ABSOLUTE) - - if(DEFINED YAML_CPP_LIBRARY_DIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${YAML_CPP_LIBRARY_DIR}) + if (DEFINED YAML_CPP_LIBRARY_DIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${YAML_CPP_LIBRARY_DIR}) endif() - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} -L${YAML_CPP_LIBRARY_DIR} ${YAML_CPP_LIBRARIES}) list(APPEND DEPENDENCY_LIBRARY_DIRS ${YAML_CPP_LIBRARY_DIR}) - else() +else () message(FATAL_ERROR "-- [DFTRACER] yaml-cpp is needed for ${PROJECT_NAME} build") - endif() +endif () - # Optional Dependencies - # ============================================================================= - if(DFTRACER_BUILD_PYTHON_BINDINGS) +# Optional Dependencies +# ============================================================================= +if (DFTRACER_BUILD_PYTHON_BINDINGS) find_package(pybind11 REQUIRED) + #add_subdirectory(dependency/py11bind) +endif() - # add_subdirectory(dependency/py11bind) - endif() - if(DFTRACER_ENABLE_MPI) +if (DFTRACER_ENABLE_MPI) find_package(MPI COMPONENTS CXX REQUIRED) - - if(MPI_FOUND) - message(STATUS "[DFTRACER] found mpi.h at ${MPI_CXX_INCLUDE_DIRS}") - include_directories(${MPI_CXX_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${MPI_CXX_LIBRARIES}) - - # Get the directory of each MPI_CXX_LIBRARY and append to MPI_CXX_LIBRARY_DIRS - set(MPI_CXX_LIBRARY_DIRS "") - - foreach(_lib ${MPI_CXX_LIBRARIES}) - get_filename_component(_lib_dir "${_lib}" DIRECTORY) - - if(_lib_dir) - list(APPEND MPI_CXX_LIBRARY_DIRS "${_lib_dir}") + if (MPI_FOUND) + message(STATUS "[DFTRACER] found mpi.h at ${MPI_CXX_INCLUDE_DIRS}") + include_directories(${MPI_CXX_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${MPI_CXX_LIBRARIES}) + # Get the directory of each MPI_CXX_LIBRARY and append to MPI_CXX_LIBRARY_DIRS + set(MPI_CXX_LIBRARY_DIRS "") + foreach(_lib ${MPI_CXX_LIBRARIES}) + get_filename_component(_lib_dir "${_lib}" DIRECTORY) + if (_lib_dir) + list(APPEND MPI_CXX_LIBRARY_DIRS "${_lib_dir}") + endif() + endforeach() + list(REMOVE_DUPLICATES MPI_CXX_LIBRARY_DIRS) + if (DEFINED MPI_CXX_LIBRARY_DIRS) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${MPI_CXX_LIBRARY_DIRS}) endif() - endforeach() - - list(REMOVE_DUPLICATES MPI_CXX_LIBRARY_DIRS) - - if(DEFINED MPI_CXX_LIBRARY_DIRS) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${MPI_CXX_LIBRARY_DIRS}) - endif() - else() - message(FATAL_ERROR "-- [DFTRACER] mpi is needed for ${PROJECT_NAME} build") - endif() - endif() + else () + message(FATAL_ERROR "-- [DFTRACER] mpi is needed for ${PROJECT_NAME} build") + endif () +endif() - if(NOT DFTRACER_DISABLE_HWLOC) +if (NOT DFTRACER_DISABLE_HWLOC) find_package(HWLOC REQUIRED) + if (${HWLOC_FOUND}) + include_directories(${HWLOC_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HWLOC_LIBRARIES}) + if (DEFINED HWLOC_LIBDIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${HWLOC_LIBDIR}) + endif() + message(STATUS "[DFTRACER] found hwloc at ${HWLOC_INCLUDE_DIRS}") + else () + message(FATAL_ERROR "-- [DFTRACER] hwloc is needed for ${PROJECT_NAME} build with -DDFTRACER_DISABLE_HWLOC-ON option.") + endif () +endif() - if(${HWLOC_FOUND}) - include_directories(${HWLOC_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HWLOC_LIBRARIES}) - - if(DEFINED HWLOC_LIBDIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${HWLOC_LIBDIR}) - endif() - - message(STATUS "[DFTRACER] found hwloc at ${HWLOC_INCLUDE_DIRS}") - else() - message(FATAL_ERROR "-- [DFTRACER] hwloc is needed for ${PROJECT_NAME} build with -DDFTRACER_DISABLE_HWLOC-ON option.") - endif() - endif() - - find_package(ZLIB REQUIRED) - - if(ZLIB_FOUND) +find_package(ZLIB REQUIRED) +if (ZLIB_FOUND) message(STATUS "[DFTRACER] found zlib at ${ZLIB_INCLUDE_DIRS}") include_directories(${ZLIB_INCLUDE_DIRS}) set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZLIB_LIBRARIES}) get_filename_component(ZLIB_LIBRARY "${ZLIB_LIBRARIES}" DIRECTORY) set(ZLIB_LIBRARY_DIR "${ZLIB_LIBRARY}") - # Get absolute path for ZLIB_LIBRARY_DIR get_filename_component(ZLIB_LIBRARY_DIR "${ZLIB_LIBRARY_DIR}" ABSOLUTE) - - if(DEFINED ZLIB_LIBRARY_DIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIR}) + if (DEFINED ZLIB_LIBRARY_DIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIR}) endif() - - if(DEFINED ZLIB_LIBRARY_DIRS) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIRS}) + if (DEFINED ZLIB_LIBRARY_DIRS) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIRS}) endif() - else() +else () message(FATAL_ERROR "-- [DFTRACER] zlib is needed for ${PROJECT_NAME} build") - endif() +endif () - if(DFTRACER_ENABLE_HIP_TRACING) +if (DFTRACER_ENABLE_HIP_TRACING) find_package(rocprofiler-sdk REQUIRED) + if (rocprofiler-sdk_FOUND) + message(STATUS "[DFTRACER] found rocprofiler-sdk at ${ROCPROFILER_SDK_INCLUDE_DIRS}") + set(HIP_TRACING_LIBRARIES rocprofiler-sdk::rocprofiler-sdk) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HIP_TRACING_LIBRARIES}) + else() + message(FATAL_ERROR "-- [DFTRACER] rocprofiler-sdk is needed for ${PROJECT_NAME} build") + endif() +endif() - if(rocprofiler-sdk_FOUND) - message(STATUS "[DFTRACER] found rocprofiler-sdk at ${ROCPROFILER_SDK_INCLUDE_DIRS}") - set(HIP_TRACING_LIBRARIES rocprofiler-sdk::rocprofiler-sdk) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HIP_TRACING_LIBRARIES}) +if(DFTRACER_WRITER_TYPE_MOFKA) + find_package(mofka REQUIRED) + if (${mofka_FOUND}) + message(STATUS "[DFTRACER] found mofka") + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} mofka::client) else() - message(FATAL_ERROR "-- [DFTRACER] rocprofiler-sdk is needed for ${PROJECT_NAME} build") + message(FATAL_ERROR "-- [DFTRACER] mofka is needed for ${PROJECT_NAME} build") endif() - endif() - - # Set RPATH to all dependency library dirs - list(REMOVE_DUPLICATES DEPENDENCY_LIBRARY_DIRS) - set(CMAKE_INSTALL_RPATH "${DEPENDENCY_LIBRARY_DIRS}") - set(CMAKE_BUILD_RPATH "${DEPENDENCY_LIBRARY_DIRS}") - set(CMAKE_SKIP_BUILD_RPATH OFF) - set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) - - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - set(DFTRACER_PRELOAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_preload.cpp) - set(DFTRACER_PRELOAD_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_preload.h) - - set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/posix.cpp +endif() + +# Set RPATH to all dependency library dirs +list(REMOVE_DUPLICATES DEPENDENCY_LIBRARY_DIRS) +set(CMAKE_INSTALL_RPATH "${DEPENDENCY_LIBRARY_DIRS}") +set(CMAKE_BUILD_RPATH "${DEPENDENCY_LIBRARY_DIRS}") +set(CMAKE_SKIP_BUILD_RPATH OFF) +set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) +set(DFTRACER_PRELOAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_preload.cpp) +set(DFTRACER_PRELOAD_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_preload.h) + +set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/posix.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/stdio.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/finstrument/functions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/function/hip/intercept.cpp @@ -422,15 +382,14 @@ else() ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/serialization/json_line.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/compression/zlib_compression.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/buffer/buffer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/stdio_writer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/aggregator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/datastructure.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/rules.cpp) - set(DFTRACER_CORE_PUBLIC_INCLUDE +set(DFTRACER_CORE_PUBLIC_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/dftracer.h ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/common/constants.h ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/common/typedef.h) - set(DFTRACER_CORE_PRIVATE_INCLUDE +set(DFTRACER_CORE_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/posix_internal.h ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/utils.h ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/md5.h @@ -445,25 +404,31 @@ else() ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/configuration_manager.h ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/aggregator.h ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/datastructure.h) - add_library(${PROJECT_NAME}_core SHARED) - target_compile_definitions(${PROJECT_NAME}_core PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) - target_link_libraries(${PROJECT_NAME}_core ${DEPENDENCY_LIB}) - add_library(${PROJECT_NAME}_core_dbg SHARED) - target_link_libraries(${PROJECT_NAME}_core_dbg ${DEPENDENCY_LIB}) - add_library(${PROJECT_NAME}_preload SHARED) - target_link_libraries(${PROJECT_NAME}_preload ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) - add_library(${PROJECT_NAME}_preload_dbg SHARED) - target_link_libraries(${PROJECT_NAME}_preload_dbg ${DEPENDENCY_LIB} ${PROJECT_NAME}_core_dbg) - set(DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_core_dbg ${PROJECT_NAME}_preload_dbg) +if(DFTRACER_WRITER_TYPE_MOFKA) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/mofka_writer.cpp) +else() + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/stdio_writer.cpp) +endif() - set(DFTRACER_SERVICE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/service/service.cpp) +add_library(${PROJECT_NAME}_core SHARED) +target_compile_definitions(${PROJECT_NAME}_core PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) +target_link_libraries(${PROJECT_NAME}_core ${DEPENDENCY_LIB}) +add_library(${PROJECT_NAME}_core_dbg SHARED) +target_link_libraries(${PROJECT_NAME}_core_dbg ${DEPENDENCY_LIB}) +add_library(${PROJECT_NAME}_preload SHARED) +target_link_libraries(${PROJECT_NAME}_preload ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) +add_library(${PROJECT_NAME}_preload_dbg SHARED) +target_link_libraries(${PROJECT_NAME}_preload_dbg ${DEPENDENCY_LIB} ${PROJECT_NAME}_core_dbg) - add_executable(${PROJECT_NAME}_service ${DFTRACER_SERVICE_SRC}) - target_compile_definitions(${PROJECT_NAME}_service PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) - target_link_libraries(${PROJECT_NAME}_service ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) +set(DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_core_dbg ${PROJECT_NAME}_preload_dbg) +set(DFTRACER_SERVICE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/service/service.cpp) - if(DFTRACER_BUILD_PYTHON_BINDINGS) +add_executable(${PROJECT_NAME}_service ${DFTRACER_SERVICE_SRC}) +target_compile_definitions(${PROJECT_NAME}_service PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) +target_link_libraries(${PROJECT_NAME}_service ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) + +if (DFTRACER_BUILD_PYTHON_BINDINGS) pybind11_add_module(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/python/dftracer.cpp) target_compile_definitions(${PROJECT_NAME} PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) target_link_libraries(${PROJECT_NAME} PRIVATE ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) @@ -472,55 +437,32 @@ else() target_compile_definitions(${PROJECT_NAME}_dbg PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) target_link_libraries(${PROJECT_NAME}_dbg PRIVATE ${DEPENDENCY_LIB} ${PROJECT_NAME}_core_dbg) list(APPEND DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_dbg) - endif() - - target_sources(${PROJECT_NAME}_core - PRIVATE - ${DFTRACER_CORE_SRC} - ) - target_sources(${PROJECT_NAME}_core_dbg - PRIVATE - ${DFTRACER_CORE_SRC} - ) - target_sources(${PROJECT_NAME}_preload - PRIVATE - ${DFTRACER_PRELOAD_SRC} - ) - target_sources(${PROJECT_NAME}_preload_dbg - PRIVATE - ${DFTRACER_PRELOAD_SRC} - ) - target_sources(${PROJECT_NAME}_service - PRIVATE - ${DFTRACER_SERVICE_SRC} - ) - target_include_directories(${PROJECT_NAME}_core - PRIVATE +endif() +target_sources(${PROJECT_NAME}_core PRIVATE ${DFTRACER_CORE_SRC}) +target_sources(${PROJECT_NAME}_core_dbg PRIVATE ${DFTRACER_CORE_SRC}) +target_sources(${PROJECT_NAME}_preload PRIVATE ${DFTRACER_PRELOAD_SRC}) +target_sources(${PROJECT_NAME}_preload_dbg PRIVATE ${DFTRACER_PRELOAD_SRC}) +target_sources(${PROJECT_NAME}_service PRIVATE ${DFTRACER_SERVICE_SRC}) +target_include_directories(${PROJECT_NAME}_core PRIVATE # where the library itself will look for its internal headers ${CMAKE_CURRENT_SOURCE_DIR}/src PUBLIC - # where top-level project will look for the library's public headers $ - # where external projects will look for the library's public headers $ - ) - target_include_directories(${PROJECT_NAME}_core_dbg - PRIVATE - +) +target_include_directories(${PROJECT_NAME}_core_dbg PRIVATE # where the library itself will look for its internal headers ${CMAKE_CURRENT_SOURCE_DIR}/src PUBLIC - # where top-level project will look for the library's public headers $ - # where external projects will look for the library's public headers $ - ) - set_target_properties(${PROJECT_NAME}_core +) +set_target_properties(${PROJECT_NAME}_core PROPERTIES DEBUG_OUTPUT_NAME ${PROJECT_NAME}_core RELEASE_OUTPUT_NAME ${PROJECT_NAME}_core @@ -528,124 +470,57 @@ else() RELWITHDEBINFO_OUTPUT_NAME ${PROJECT_NAME}_core VERSION ${DFTRACER_PACKAGE_VERSION} SOVERSION ${DFTRACER_PACKAGE_VERSION} - ) +) - dftracer_debug_config("${DFTRACER_DEBUG_TARGETS}") - dftracer_install_headers("${DFTRACER_CORE_PUBLIC_INCLUDE}") - install( +dftracer_debug_config("${DFTRACER_DEBUG_TARGETS}") +dftracer_install_headers("${DFTRACER_CORE_PUBLIC_INCLUDE}") +install( TARGETS ${PROJECT_NAME}_core EXPORT ${DFTRACER_EXPORTED_TARGETS} LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} - ) - install( +) +install( TARGETS ${PROJECT_NAME}_core_dbg EXPORT ${DFTRACER_EXPORTED_TARGETS} LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} - ) - install( +) +install( TARGETS ${PROJECT_NAME}_service EXPORT ${DFTRACER_EXPORTED_TARGETS} LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} - ) - install(TARGETS ${PROJECT_NAME}_preload +) +install(TARGETS ${PROJECT_NAME}_preload LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - install(TARGETS ${PROJECT_NAME}_preload_dbg +install(TARGETS ${PROJECT_NAME}_preload_dbg LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - # where the library itself will look for its internal headers - ${CMAKE_CURRENT_SOURCE_DIR}/src - PUBLIC - - # where top-level project will look for the library's public headers - $ - - # where external projects will look for the library's public headers - $ - ) - - target_include_directories(${PROJECT_NAME}_dbg - PRIVATE - - # where the library itself will look for its internal headers - ${CMAKE_CURRENT_SOURCE_DIR}/src - PUBLIC - - # where top-level project will look for the library's public headers - $ - - # where external projects will look for the library's public headers - $ - ) - set_target_properties(${PROJECT_NAME} - PROPERTIES - DEBUG_OUTPUT_NAME ${PROJECT_NAME} - RELEASE_OUTPUT_NAME ${PROJECT_NAME} - MINSIZEREL_OUTPUT_NAME ${PROJECT_NAME} - RELWITHDEBINFO_OUTPUT_NAME ${PROJECT_NAME} - VERSION ${DFTRACER_PACKAGE_VERSION} - SOVERSION ${DFTRACER_PACKAGE_VERSION} - ) - - dftracer_debug_config("${DFTRACER_DEBUG_TARGETS}") - dftracer_install_headers("${DFTRACER_CORE_PUBLIC_INCLUDE}") - install( - TARGETS ${PROJECT_NAME} +install(TARGETS ${PROJECT_NAME}_preload EXPORT ${DFTRACER_EXPORTED_TARGETS} LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} - ) - install(TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - install( - TARGETS ${PROJECT_NAME}_dbg +) +install(TARGETS ${PROJECT_NAME}_preload_dbg EXPORT ${DFTRACER_EXPORTED_TARGETS} LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} - ) - install(TARGETS ${PROJECT_NAME}_dbg - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - install(TARGETS ${PROJECT_NAME}_preload - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - install(TARGETS ${PROJECT_NAME}_preload_dbg - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - - install( - TARGETS - ${PROJECT_NAME}_preload - EXPORT - ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} - ) - install( - TARGETS - ${PROJECT_NAME}_preload_dbg - EXPORT - ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} - ) +) - if(DFTRACER_BUILD_PYTHON_BINDINGS) - install(TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +if (DFTRACER_BUILD_PYTHON_BINDINGS) + install( + TARGETS ${PROJECT_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") install(CODE "execute_process( COMMAND bash -c \"set -e @@ -653,323 +528,236 @@ else() . ${CMAKE_BINARY_DIR}/symlink.sh \")") - install(TARGETS ${PROJECT_NAME}_dbg - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install( + TARGETS ${PROJECT_NAME}_dbg + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink_dbg.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") install(CODE "execute_process( COMMAND bash -c \"set -e chmod +x ${CMAKE_BINARY_DIR}/symlink_dbg.sh . ${CMAKE_BINARY_DIR}/symlink_dbg.sh \")") - endif() +endif() - if(DFTRACER_ENABLE_NATIVE_SCRIPT) +if(DFTRACER_ENABLE_NATIVE_SCRIPT) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact_by_pid ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_merge ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_sanitize ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_anonymize ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_create_index ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_pgzip ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_split ${EXECUTABLE_OUTPUT_PATH}/dftracer_split COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_split - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_split DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_event_count ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count - DESTINATION - bin - ) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count DESTINATION bin) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_validate ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate - DESTINATION - bin - ) - endif() - - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/git_sparse_clone_interactive ${EXECUTABLE_OUTPUT_PATH}/git_sparse_clone_interactive COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/git_sparse_clone_interactive - DESTINATION - bin - ) - - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/git_sparse_push_interactive ${EXECUTABLE_OUTPUT_PATH}/git_sparse_push_interactive COPYONLY) - install( - FILES - ${EXECUTABLE_OUTPUT_PATH}/git_sparse_push_interactive - DESTINATION - bin - ) - - # cmake_policy(SET CMP0079 NEW) # In case that we need more control over the target building order - if(DFTRACER_ENABLE_TESTS) - message("-- " "[DFTracer] Enabling Testing") + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate DESTINATION bin) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/git_sparse_clone_interactive ${EXECUTABLE_OUTPUT_PATH}/git_sparse_clone_interactive COPYONLY) +install(FILES ${EXECUTABLE_OUTPUT_PATH}/git_sparse_clone_interactive DESTINATION bin) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/git_sparse_push_interactive ${EXECUTABLE_OUTPUT_PATH}/git_sparse_push_interactive COPYONLY) +install(FILES ${EXECUTABLE_OUTPUT_PATH}/git_sparse_push_interactive DESTINATION bin) +#cmake_policy(SET CMP0079 NEW) # In case that we need more control over the target building order + +if(DFTRACER_ENABLE_TESTS) + message("-- " "[DFTracer] Enabling Testing") if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") - message("-- " "[DFTracer] building with CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}") - set(CMAKE_C_FLAGS_PROFILE --coverage) - set(CMAKE_CXX_FLAGS_PROFILE --coverage) + message("-- " "[DFTracer] building with CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}") + set(CMAKE_C_FLAGS_PROFILE --coverage) + set(CMAKE_CXX_FLAGS_PROFILE --coverage) endif() - enable_testing() add_subdirectory(test) - if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") - get_property(COVERAGE_FILE_LIST GLOBAL PROPERTY COVERAGE_FILES) - add_custom_command(OUTPUT default.profdata COMMAND llvm-profdata merge -sparse ${COVERAGE_FILE_LIST} -o default.profdata VERBATIM) - add_custom_target(merged_coverage DEPENDS default.profdata) + get_property(COVERAGE_FILE_LIST GLOBAL PROPERTY COVERAGE_FILES) + add_custom_command(OUTPUT default.profdata COMMAND llvm-profdata merge -sparse ${COVERAGE_FILE_LIST} -o default.profdata VERBATIM) + add_custom_target(merged_coverage DEPENDS default.profdata) endif() - endif() +endif() - # ----------------------------------------------------------------------------- - # Configure the config.cmake file for the build directory - # ----------------------------------------------------------------------------- - include(CMakePackageConfigHelpers) - configure_package_config_file( +#----------------------------------------------------------------------------- +# Configure the config.cmake file for the build directory +#----------------------------------------------------------------------------- +include(CMakePackageConfigHelpers) +configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.build.in "${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config.cmake" INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake PATH_VARS CMAKE_BINARY_DIR - ) +) - configure_package_config_file( +configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.install.in "${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake" INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/install/${PROJECT_NAME}-config.cmake PATH_VARS CMAKE_BINARY_DIR - ) - install( - FILES - ${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake - DESTINATION - ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} - ) - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/dftracer-utils.cmake" - DESTINATION "${DFTRACER_LIBDIR}/cmake/dftracer") - - # ----------------------------------------------------------------------------- - # Configure the ${PROJECT_NAME}-config-version .cmake file for the install directory - # ----------------------------------------------------------------------------- - install( - FILES - ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake - DESTINATION - ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} - ) - - export(EXPORT ${DFTRACER_EXPORTED_TARGETS} - FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake") - - # Write the configure file - configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config.hpp.in" - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config.hpp" @ONLY) - - configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config_dbg.hpp.in" - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config_dbg.hpp" @ONLY) - - # ############################################################### - # Install DFTRACER - # ############################################################### - include(CMakePackageConfigHelpers) - - # Write the version file. This is independent of build/install tree. - write_basic_package_version_file( - dftracer-config-version.cmake - VERSION "${DFTRACER_PACKAGE_VERSION}" - COMPATIBILITY SameMajorVersion) - - install(FILES - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config.hpp" - DESTINATION - ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer/core) - - install(FILES - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config_dbg.hpp" - DESTINATION - ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer/core) - - install(EXPORT - ${DFTRACER_EXPORTED_TARGETS} - DESTINATION - ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} - FILE - ${DFTRACER_EXPORTED_TARGETS}.cmake - ) - - # Install license and readme - install(FILES - "${PROJECT_SOURCE_DIR}/LICENSE" - "${PROJECT_SOURCE_DIR}/README.md" - DESTINATION - ${DFTRACER_INSTALL_DOCDIR}) - - # ############################################################################## - # Print out configuration summary - # ############################################################################## - if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") - set(DFTRACER_GNU_LINUX TRUE) - endif() - - # NOTE: message() outputs to stderr by default. We now use a string to - # maintain this information and then have cmake echo it to stdout. The - # only side effects are that if you use the CMake GUI, you won't see - # this output anymore (they only report stderr) and that if you add - # something to the list, you must remember your newline! - set(_str "\n== DFTRACER Configuration Summary ==\n\n") - string(APPEND _str " PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}\n" - " PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}\n\n" - " CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}\n" - " CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n\n") - - if(CMAKE_BUILD_TYPE MATCHES None) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS}\n") - elseif(CMAKE_BUILD_TYPE MATCHES Release) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\n") - string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}\n") - elseif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}\n") - string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELWITHDEBINFO}\n") - elseif(CMAKE_BUILD_TYPE MATCHES Debug) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}\n") - string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}\n") - endif() - - string(APPEND _str "\n") - +) +install(FILES ${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME}) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/dftracer-utils.cmake" DESTINATION "${DFTRACER_LIBDIR}/cmake/dftracer") +#----------------------------------------------------------------------------- +# Configure the ${PROJECT_NAME}-config-version .cmake file for the install directory +#----------------------------------------------------------------------------- + +install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME}) + +export(EXPORT ${DFTRACER_EXPORTED_TARGETS} FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake") + +# Write the configure file +configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config.hpp.in" + "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config.hpp" @ONLY) + +configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config_dbg.hpp.in" + "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config_dbg.hpp" @ONLY) + +################################################################ +# Install DFTRACER +################################################################ + +include(CMakePackageConfigHelpers) + +# Write the version file. This is independent of build/install tree. +write_basic_package_version_file( + dftracer-config-version.cmake + VERSION "${DFTRACER_PACKAGE_VERSION}" + COMPATIBILITY SameMajorVersion +) + +install(FILES "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config.hpp" DESTINATION ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer/core) +install(FILES "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config_dbg.hpp" DESTINATION ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer/core) + +install(EXPORT ${DFTRACER_EXPORTED_TARGETS} DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} FILE ${DFTRACER_EXPORTED_TARGETS}.cmake) + +# Install license and readme +install(FILES "${PROJECT_SOURCE_DIR}/LICENSE" "${PROJECT_SOURCE_DIR}/README.md" DESTINATION ${DFTRACER_INSTALL_DOCDIR}) + +############################################################################### +# Print out configuration summary +############################################################################### + +if (CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") + set(DFTRACER_GNU_LINUX TRUE) +endif () + +# NOTE: message() outputs to stderr by default. We now use a string to +# maintain this information and then have cmake echo it to stdout. The +# only side effects are that if you use the CMake GUI, you won't see +# this output anymore (they only report stderr) and that if you add +# something to the list, you must remember your newline! +set(_str "\n== DFTRACER Configuration Summary ==\n\n") +string(APPEND _str " PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}\n" + " PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}\n\n" + " CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}\n" + " CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n\n") +if (CMAKE_BUILD_TYPE MATCHES None) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS}\n") +elseif (CMAKE_BUILD_TYPE MATCHES Release) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\n") string(APPEND _str - " DFTRACER_PACKAGE_VERSION: ${DFTRACER_PACKAGE_VERSION}\n") + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}\n") +elseif (CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) string(APPEND _str - " DFTRACER_GIT_VERSION: ${DFTRACER_GIT_VERSION}\n") + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}\n") string(APPEND _str - " GLIBC_VERSION: ${GLIBC_VERSION}\n") + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELWITHDEBINFO}\n") +elseif (CMAKE_BUILD_TYPE MATCHES Debug) string(APPEND _str - " DFTRACER_PYTHON_EXE: ${DFTRACER_PYTHON_EXE}\n") + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}\n") string(APPEND _str - " DFTRACER_PYTHON_SITE: ${DFTRACER_PYTHON_SITE}\n") + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}\n") +endif () +string(APPEND _str "\n") + +string(APPEND _str + " DFTRACER_PACKAGE_VERSION: ${DFTRACER_PACKAGE_VERSION}\n") +string(APPEND _str + " DFTRACER_GIT_VERSION: ${DFTRACER_GIT_VERSION}\n") +string(APPEND _str + " GLIBC_VERSION: ${GLIBC_VERSION}\n") string(APPEND _str - " MAIN_PYTHON_SITE_PACKAGES: ${MAIN_PYTHON_SITE_PACKAGES}\n") + " DFTRACER_PYTHON_EXE: ${DFTRACER_PYTHON_EXE}\n") string(APPEND _str - " DEPENDENCY_LIB: ${DEPENDENCY_LIB}\n") + " DFTRACER_PYTHON_SITE: ${DFTRACER_PYTHON_SITE}\n") string(APPEND _str - " CMAKE_BUILD_RPATH: ${CMAKE_BUILD_RPATH}\n") + " MAIN_PYTHON_SITE_PACKAGES: ${MAIN_PYTHON_SITE_PACKAGES}\n") string(APPEND _str - " CMAKE_INSTALL_RPATH: ${CMAKE_INSTALL_RPATH}\n") - - # Print the true/false variables - append_str_tf(_str - DFTRACER_GNU_LINUX - DFTRACER_LIBDIR_AS_LIB - DFTRACER_ENABLE_FTRACING - DFTRACER_ENABLE_HIP_TRACING - DFTRACER_ENABLE_MPI - DFTRACER_DISABLE_HWLOC - DFTRACER_USE_CLANG_LIBCXX - DFTRACER_WARNINGS_AS_ERRORS - DFTRACER_BUILD_PYTHON_BINDINGS - DFTRACER_ENABLE_TESTS - DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS - DFTRACER_ENABLE_PAPER_TESTS - DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE - DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ - DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE - DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZEROMQ - ) + " DEPENDENCY_LIB: ${DEPENDENCY_LIB}\n") string(APPEND _str - "\n== End DFTRACER Configuration Summary ==\n") - - # Output to stdout - execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${_str}") - set(_str) - - # ############################################################################## - # Write a basic modulefile - # ############################################################################## - set(DFTRACER_MODULEFILE_NAME "dftracer-${DFTRACER_PACKAGE_VERSION}.lua") - - # CACHE STRING - # "The name of the DFTRACER modulefile to install. Must end in .lua.") - if(NOT(DFTRACER_MODULEFILE_NAME MATCHES ".+\.lua")) - message(WARNING - "DFTRACER_MODULEFILE_NAME must have extension \".lua\". Appending.") - set(DFTRACER_MODULEFILE_NAME "${DFTRACER_MODULEFILE_NAME}.lua" - CACHE STRING "" FORCE) - endif() - - configure_file( - "${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_module.lua.in" - "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" - @ONLY) - - install(FILES "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" - RENAME "${DFTRACER_MODULEFILE_NAME}" - DESTINATION - "${DFTRACER_INSTALL_SYSCONFDIR}") + " CMAKE_BUILD_RPATH: ${CMAKE_BUILD_RPATH}\n") + string(APPEND _str + " CMAKE_INSTALL_RPATH: ${CMAKE_INSTALL_RPATH}\n") + +# Print the true/false variables +append_str_tf(_str + DFTRACER_GNU_LINUX + DFTRACER_LIBDIR_AS_LIB + DFTRACER_ENABLE_FTRACING + DFTRACER_ENABLE_HIP_TRACING + DFTRACER_ENABLE_MPI + DFTRACER_DISABLE_HWLOC + DFTRACER_USE_CLANG_LIBCXX + DFTRACER_WARNINGS_AS_ERRORS + DFTRACER_BUILD_PYTHON_BINDINGS + DFTRACER_ENABLE_TESTS + DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS + DFTRACER_ENABLE_PAPER_TESTS + DFTRACER_WRITER_TYPE_STDIO + DFTRACER_WRITER_TYPE_MOFKA +) +string(APPEND _str + "\n== End DFTRACER Configuration Summary ==\n") + +# Output to stdout +execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${_str}") +set(_str) + +############################################################################### +# Write a basic modulefile +############################################################################### + +set(DFTRACER_MODULEFILE_NAME "dftracer-${DFTRACER_PACKAGE_VERSION}.lua") + +# CACHE STRING +# "The name of the DFTRACER modulefile to install. Must end in .lua." +if (NOT (DFTRACER_MODULEFILE_NAME MATCHES ".+\.lua")) + message(WARNING + "DFTRACER_MODULEFILE_NAME must have extension \".lua\". Appending.") + set(DFTRACER_MODULEFILE_NAME "${DFTRACER_MODULEFILE_NAME}.lua" + CACHE STRING "" FORCE) +endif () + +configure_file( + "${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_module.lua.in" + "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" + @ONLY) + +install( + FILES "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" + RENAME "${DFTRACER_MODULEFILE_NAME}" + DESTINATION "${DFTRACER_INSTALL_SYSCONFDIR}" +) + endif() diff --git a/cmake/configure_files/dftracer_config.hpp.in b/cmake/configure_files/dftracer_config.hpp.in index f7497f70..afc939d4 100644 --- a/cmake/configure_files/dftracer_config.hpp.in +++ b/cmake/configure_files/dftracer_config.hpp.in @@ -35,10 +35,8 @@ #cmakedefine DFTRACER_HWLOC_ENABLE 1 #cmakedefine DFTRACER_MPI_ENABLE 1 #cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" -#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE -#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ -#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE -#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ +#cmakedefine01 DFTRACER_WRITER_TYPE_STDIO +#cmakedefine01 DFTRACER_WRITER_TYPE_MOFKA //========================== // Common macro definitions diff --git a/cmake/configure_files/dftracer_config_dbg.hpp.in b/cmake/configure_files/dftracer_config_dbg.hpp.in index c7ea7ee5..07428aab 100644 --- a/cmake/configure_files/dftracer_config_dbg.hpp.in +++ b/cmake/configure_files/dftracer_config_dbg.hpp.in @@ -35,10 +35,8 @@ #cmakedefine DFTRACER_HWLOC_ENABLE 1 #cmakedefine DFTRACER_MPI_ENABLE 1 #cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" -#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE -#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ -#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE -#cmakedefine01 DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ +#cmakedefine01 DFTRACER_WRITER_TYPE_STDIO +#cmakedefine01 DFTRACER_WRITER_TYPE_MOFKA #define DFTRACER_LOGGER_CPP_LOGGER 1 #define DFTRACER_LOGGER_LEVEL_TRACE 1 diff --git a/dependency/CMakeLists.txt b/dependency/CMakeLists.txt index cfe44325..0ec0e5b5 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -1,12 +1,17 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/dftracer-utils.cmake) + install_external_project(cpp-logger 1.0.0 "CPP_LOGGER" https://github.com/hariharan-devarajan/cpp-logger.git v0.0.6 ${CMAKE_INSTALL_PREFIX} "") -install_external_project(gotcha 2.3.2 "gotcha" https://github.com/LLNL/GOTCHA.git 1.0.7 ${CMAKE_INSTALL_PREFIX} "-DCMAKE_POLICY_VERSION_MINIMUM=3.5") + +find_package(gotcha QUIET) +if(NOT ${gotcha_FOUND}) + install_external_project(gotcha 2.3.2 "gotcha" https://github.com/LLNL/GOTCHA.git 1.0.7 ${CMAKE_INSTALL_PREFIX} "-DCMAKE_POLICY_VERSION_MINIMUM=3.5") +endif() + install_external_project(brahma 3.0.0 "BRAHMA" https://github.com/hariharan-devarajan/brahma.git v1.0.1 ${CMAKE_INSTALL_PREFIX} "") add_dependencies(brahma cpp-logger) add_dependencies(brahma gotcha) find_package(yaml-cpp QUIET) - if(NOT ${yaml-cpp_FOUND}) install_external_project(yaml-cpp "" "YAML_CPP" https://github.com/jbeder/yaml-cpp.git yaml-cpp-0.6.3 ${CMAKE_INSTALL_PREFIX} "-DYAML_CPP_BUILD_TESTS=OFF;-DYAML_BUILD_SHARED_LIBS=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5") add_dependencies(yaml-cpp brahma) @@ -14,50 +19,7 @@ if(NOT ${yaml-cpp_FOUND}) add_dependencies(yaml-cpp cpp-logger) endif() -install_external_project(pybind11 2.12.0 "pybind11" https://github.com/pybind/pybind11.git v2.12.0 ${CMAKE_INSTALL_PREFIX} "-DPYBIND11_TEST=OFF") - -if(DFTRACER_WRITER_TYPE MATCHES ".*PROTO.*") - install_external_project(protobuf 31.1 "protobuf" https://github.com/protocolbuffers/protobuf.git v31.1 ${CMAKE_INSTALL_PREFIX} "-Dprotobuf_BUILD_TESTS=OFF;-Dprotobuf_BUILD_EXAMPLES=OFF;-Dprotobuf_BUILD_LIBPROTOC=ON;-Dprotobuf_BUILD_SHARED_LIBS=ON;-Dprotobuf_WITH_ZLIB=OFF;") - - ExternalProject_Add( - perfetto - PREFIX ${CMAKE_BINARY_DIR} - GIT_REPOSITORY https://github.com/google/perfetto.git - GIT_TAG v51.0 - TIMEOUT 10 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - ) - - set(PERFETTO_SDK_DIR "${CMAKE_BINARY_DIR}/src/perfetto/sdk") - - set(PERFETTO_OUTPUT_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib64") - set(PERFETTO_OUTPUT_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") - - set(PERFETTO_SDK_HEADER_PATH "${PERFETTO_OUTPUT_INCLUDE_DIR}/perfetto.h") - set(PERFETTO_SDK_LIB_PATH "${PERFETTO_OUTPUT_LIB_DIR}/libperfetto_sdk.a") - - add_custom_command( - OUTPUT ${PERFETTO_SDK_LIB_PATH} - COMMAND ${CMAKE_COMMAND} -E make_directory ${PERFETTO_OUTPUT_LIB_DIR} - COMMAND ${CMAKE_COMMAND} -E make_directory ${PERFETTO_OUTPUT_INCLUDE_DIR} - COMMAND ${CMAKE_CXX_COMPILER} -std=c++17 -fPIC -c ${PERFETTO_SDK_DIR}/perfetto.cc -I${PERFETTO_SDK_DIR} -o ${CMAKE_BINARY_DIR}/perfetto.o - COMMAND ${CMAKE_AR} rcs ${PERFETTO_SDK_LIB_PATH} ${CMAKE_BINARY_DIR}/perfetto.o - COMMAND ${CMAKE_COMMAND} -E copy ${PERFETTO_SDK_DIR}/perfetto.h ${PERFETTO_SDK_HEADER_PATH} - DEPENDS perfetto - BYPRODUCTS ${PERFETTO_SDK_HEADER_PATH} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Building and placing Perfetto SDK into ${CMAKE_INSTALL_PREFIX}" - VERBATIM - ) - - add_custom_target(perfetto_sdk ALL DEPENDS ${PERFETTO_SDK_LIB_PATH}) -endif() - -if(DFTRACER_WRITER_TYPE MATCHES ".*ZMQ.*") - install_external_project(ZeroMQ 4.3.5 "ZeroMQ" https://github.com/zeromq/libzmq.git v4.3.5 ${CMAKE_INSTALL_PREFIX} "-DBUILD_SHARED=ON;-DENABLE_CURVE=OFF;-DZMQ_BUILD_TESTS=OFF") - install_external_project(cppzmq 4.10.0 "cppzmq" https://github.com/zeromq/cppzmq.git v4.9.0 ${CMAKE_INSTALL_PREFIX} "-DCPPZMQ_BUILD_TESTS=OFF") - add_dependencies(cppzmq ZeroMQ) +find_package(pybind11 QUIET) +if(NOT ${pybind11_FOUND}) + install_external_project(pybind11 2.12.0 "pybind11" https://github.com/pybind/pybind11.git v2.12.0 ${CMAKE_INSTALL_PREFIX} "-DPYBIND11_TEST=OFF") endif() diff --git a/setup.py b/setup.py index b5a0fc05..fd97be00 100644 --- a/setup.py +++ b/setup.py @@ -119,8 +119,7 @@ def build_extension(self, ext: CMakeExtension) -> None: cmake_args += [ f"-DDFTRACER_TEST_LD_LIBRARY_PATH={test_ld_library_path}"] - writer_type = os.environ.get( - "DFTRACER_WRITER_TYPE", "PERFETTO_CHROME_FILE") + writer_type = os.environ.get("DFTRACER_WRITER_TYPE", "STDIO") cmake_args += [f"-DDFTRACER_WRITER_TYPE={writer_type}"] # CMake lets you override the generator - we need to check this. diff --git a/src/dftracer/core/buffer/buffer.cpp b/src/dftracer/core/buffer/buffer.cpp index 492135b7..3bcca78e 100644 --- a/src/dftracer/core/buffer/buffer.cpp +++ b/src/dftracer/core/buffer/buffer.cpp @@ -1,4 +1,14 @@ #include + +#include +#include + +#if DFTRACER_WRITER_TYPE_MOFKA +#include +#elif DFTRACER_WRITER_TYPE_STDIO +#include +#endif + template <> std::shared_ptr dftracer::Singleton::instance = nullptr; @@ -8,6 +18,9 @@ bool dftracer::Singleton::stop_creating_instances = namespace dftracer { void BufferManager::compress_and_write_if_needed(size_t size, bool force) { +#if DFTRACER_WRITER_TYPE_MOFKA + force = true; +#endif if (force || buffer_pos + size > this->config->write_buffer_size) { if (this->config->compression) { size = this->compressor->compress(buffer, buffer_pos + size); @@ -34,7 +47,13 @@ int BufferManager::initialize(const char* filename, HashType hostname_hash) { DFTRACER_LOG_ERROR("BufferManager.BufferManager Failed to allocate buffer", ""); } - this->writer = dftracer::Singleton::get_instance(); +#if DFTRACER_WRITER_TYPE_MOFKA + this->writer = std::static_pointer_cast( + dftracer::Singleton::get_instance()); +#else + this->writer = std::static_pointer_cast( + dftracer::Singleton::get_instance()); +#endif this->writer->initialize(filename); this->serializer = dftracer::Singleton::get_instance(); this->aggregator = dftracer::Singleton::get_instance(); @@ -49,6 +68,9 @@ int BufferManager::initialize(const char* filename, HashType hostname_hash) { } int BufferManager::finalize(int index, ProcessID process_id, bool end_sym) { +#if DFTRACER_WRITER_TYPE_MOFKA + end_sym = false; +#endif std::unique_lock lock(mtx); if (buffer) { size_t size = 0; @@ -62,7 +84,6 @@ int BufferManager::finalize(int index, ProcessID process_id, bool end_sym) { auto end_size = this->serializer->finalize(buffer + buffer_pos + size, end_sym); compress_and_write_if_needed(size + end_size, true); - if (this->config->compression) this->compressor->finalize(); this->writer->finalize(index); free(buffer); diff --git a/src/dftracer/core/buffer/buffer.h b/src/dftracer/core/buffer/buffer.h index 0695cb13..accbd792 100644 --- a/src/dftracer/core/buffer/buffer.h +++ b/src/dftracer/core/buffer/buffer.h @@ -1,21 +1,21 @@ #ifndef DFTRACER_BUFFER_H #define DFTRACER_BUFFER_H -#include -#include -// #include #include #include #include +#include #include +#include #include #include -#include +#include #include #include #include #include + namespace dftracer { class BufferManager { public: @@ -60,7 +60,7 @@ class BufferManager { std::shared_ptr config; std::shared_ptr serializer; std::shared_ptr compressor; - std::shared_ptr writer; + std::shared_ptr writer; std::shared_ptr aggregator; }; } // namespace dftracer diff --git a/src/dftracer/core/common/dftracer_main.cpp b/src/dftracer/core/common/dftracer_main.cpp index c64bcd58..bc51a2ce 100644 --- a/src/dftracer/core/common/dftracer_main.cpp +++ b/src/dftracer/core/common/dftracer_main.cpp @@ -249,21 +249,13 @@ void dftracer::DFTracerCore::initialize(bool _bind, const char *_log_file, exec_name, hostname, this->process_id); char *log_file_hash = logger->get_hash(log_filename_str); DFTRACER_LOG_DEBUG("Conf has log file %s", conf->log_file.c_str()); - if (conf->writer_type == WriterType::PERFETTO_CHROME_ZMQ || - conf->writer_type == WriterType::PERFETTO_PROTO_ZMQ) { - this->log_file = std::string(conf->log_file); - } else if (conf->writer_type == WriterType::PERFETTO_PROTO_FILE) { - this->log_file = std::string(conf->log_file) + "-" + exec_name + - "-" + std::to_string(this->process_id) + "-" + - log_file_suffix + ".ptrace"; - } else { - this->log_file = std::string(conf->log_file) + "-" + exec_name + - "-" + std::to_string(this->process_id) + "-" + - log_file_suffix + ".pfw"; - if (conf->compression) { - this->log_file += ".gz"; - } + std::string extension = ".pfw"; + if (conf->compression) { + extension += ".gz"; } + this->log_file = std::string(conf->log_file) + "-" + + std::string(log_file_hash) + "-" + log_file_suffix + + extension; } else { // GCOV_EXCL_START DFTRACER_LOG_ERROR(DFTRACER_UNDEFINED_LOG_FILE_MSG, ""); throw std::runtime_error(DFTRACER_UNDEFINED_LOG_FILE_CODE); diff --git a/src/dftracer/core/common/enumeration.h b/src/dftracer/core/common/enumeration.h index 39292b11..a93e56ac 100644 --- a/src/dftracer/core/common/enumeration.h +++ b/src/dftracer/core/common/enumeration.h @@ -6,11 +6,12 @@ #define DFTRACER_ENUMERATION_H #include +#include +#include + enum WriterType : uint8_t { - PERFETTO_CHROME_FILE = 0, - PERFETTO_CHROME_ZMQ = 1, - PERFETTO_PROTO_FILE = 2, - PERFETTO_PROTO_ZMQ = 3, + WRITER_TYPE_STDIO = 0, + WRITER_TYPE_MOFKA = 1, }; enum ProfilerStage : uint8_t { PROFILER_INIT = 0, @@ -37,7 +38,7 @@ enum AggregationType : uint8_t { }; enum class RuleOp { AND, OR, NOT, EQ, NEQ, GT, LT, GTE, LTE, IN, LIKE }; -inline MetadataType convert(const int &s) { +inline MetadataType convert(const int& s) { if (s == 0) { return MetadataType::MT_KEY; } else if (s == 1) { @@ -49,7 +50,7 @@ inline MetadataType convert(const int &s) { } } -inline void convert(const int &s, MetadataType &type) { +inline void convert(const int& s, MetadataType& type) { if (s == 0) { type = MetadataType::MT_KEY; } else if (s == 1) { @@ -61,7 +62,7 @@ inline void convert(const int &s, MetadataType &type) { } } -inline void convert(const std::string &s, ProfileInitType &type) { +inline void convert(const std::string& s, ProfileInitType& type) { if (s == "PRELOAD") { type = ProfileInitType::PROFILER_INIT_LD_PRELOAD; } else if (s == "FUNCTION") { @@ -70,7 +71,7 @@ inline void convert(const std::string &s, ProfileInitType &type) { type = ProfileInitType::PROFILER_INIT_NONE; } } -inline void convert(const std::string &s, cpplogger::LoggerType &type) { +inline void convert(const std::string& s, cpplogger::LoggerType& type) { if (s == "DEBUG") { type = cpplogger::LoggerType::LOG_DEBUG; } else if (s == "INFO") { @@ -81,7 +82,7 @@ inline void convert(const std::string &s, cpplogger::LoggerType &type) { type = cpplogger::LoggerType::LOG_ERROR; } } -inline void convert(const std::string &s, AggregationType &type) { +inline void convert(const std::string& s, AggregationType& type) { if (s == "FULL") { type = AggregationType::AGGREGATION_TYPE_FULL; } else if (s == "SELECTIVE") { @@ -90,7 +91,7 @@ inline void convert(const std::string &s, AggregationType &type) { type = AggregationType::AGGREGATION_TYPE_FULL; } } -inline std::string to_string(const AggregationType &type) { +inline std::string to_string(const AggregationType& type) { switch (type) { case AggregationType::AGGREGATION_TYPE_FULL: return "FULL"; @@ -101,15 +102,11 @@ inline std::string to_string(const AggregationType &type) { } } -inline void convert(const std::string &s, WriterType &type) { - if (s == "PERFETTO_CHROME_ZMQ") { - type = WriterType::PERFETTO_CHROME_ZMQ; - } else if (s == "PERFETTO_PROTO_FILE") { - type = WriterType::PERFETTO_PROTO_FILE; - } else if (s == "PERFETTO_PROTO_ZMQ") { - type = WriterType::PERFETTO_PROTO_ZMQ; +inline void convert(const std::string& s, WriterType& type) { + if (s == "MOFKA") { + type = WriterType::WRITER_TYPE_MOFKA; } else { - type = WriterType::PERFETTO_CHROME_FILE; // Default to CHROME FILE + type = WriterType::WRITER_TYPE_STDIO; } } diff --git a/src/dftracer/core/df_logger.h b/src/dftracer/core/df_logger.h index 2edf8e40..bfde90f1 100644 --- a/src/dftracer/core/df_logger.h +++ b/src/dftracer/core/df_logger.h @@ -17,15 +17,6 @@ #include #include #include -#if DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE -#include -#elif DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ -#include -#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE -#include -#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ -#include -#endif #include #include #include @@ -51,16 +42,6 @@ typedef std::chrono::high_resolution_clock chrono; -#if DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE -using DFTWriter = dftracer::PerfettoProtoFileWriter; -#elif DFTRACER_WRITER_TYPE_PERFETTO_PROTO_ZMQ -using DFTWriter = dftracer::PerfettoProtoZMQWriter; -#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE -using DFTWriter = dftracer::PerfettoChromeFileWriter; -#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_ZMQ -using DFTWriter = dftracer::PerfettoChromeZMQWriter; -#endif - class DFTLogger { private: std::shared_ptr config; @@ -134,15 +115,15 @@ class DFTLogger { this->is_init = true; } ~DFTLogger() { - for (auto &hash : computed_hash) { + for (auto& hash : computed_hash) { if (hash.second) free(hash.second); } } - inline HashType get_hash(char *name) { + inline HashType get_hash(char* name) { uint8_t result[HASH_OUTPUT]; md5String(name, result); - char *hash_str = (char *)malloc(HASH_OUTPUT * 2 + 1); + char* hash_str = (char*)malloc(HASH_OUTPUT * 2 + 1); for (int i = 0; i < HASH_OUTPUT; i += 2) { sprintf(hash_str + i, "%02x", result[i]); } @@ -173,13 +154,13 @@ class DFTLogger { this->buffer_manager->log_metadata_event( thread_name, METADATA_NAME_THREAD_NAME, METADATA_NAME_THREAD_NAME, this->process_id, tid); - dftracer::Metadata *meta = nullptr; + dftracer::Metadata* metadata = nullptr; if (include_metadata) { - meta = new dftracer::Metadata(); + metadata = new dftracer::Metadata(); char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) != NULL) { auto cwd_hash = hash_and_store(cwd, METADATA_NAME_FILE_HASH); - meta->insert_or_assign("cwd", cwd_hash); + metadata->insert_or_assign("cwd", cwd_hash); } cmd_hash = hash_and_store(cmd.data(), METADATA_NAME_STRING_HASH); exec_hash = hash_and_store(exec_name.data(), METADATA_NAME_STRING_HASH); @@ -197,8 +178,8 @@ class DFTLogger { char timestamp[1024]; auto size = sprintf(timestamp, "%s", asctime(localtime(<ime))); timestamp[size - 1] = '\0'; - meta->insert_or_assign("date", std::string(timestamp)); - meta->insert_or_assign("ppid", getppid()); + metadata->insert_or_assign("date", std::string(timestamp)); + metadata->insert_or_assign("ppid", getppid()); this->buffer_manager->set_app_name(exec_name.c_str()); } this->enter_event(); @@ -316,7 +297,7 @@ class DFTLogger { inline void log(ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, TimeResolution duration, - dftracer::Metadata *metadata) { + dftracer::Metadata* metadata) { DFTRACER_LOG_DEBUG("DFTLogger.log", ""); // Get thread id and process id from metadata if it exists @@ -368,7 +349,7 @@ class DFTLogger { this->process_id, tid); } - inline HashType hash_and_store(char *filename, ConstEventNameType name) { + inline HashType hash_and_store(char* filename, ConstEventNameType name) { if (filename == NULL) return NO_HASH_DEFAULT; char file[PATH_MAX]; strcpy(file, filename); @@ -390,7 +371,7 @@ class DFTLogger { } } - void fix_str(char *str, size_t len) { + void fix_str(char* str, size_t len) { for (size_t i = 0; i < len && str[i] != '\0'; ++i) { if (ignore_chars(str[i])) str[i] = ' '; } @@ -413,7 +394,7 @@ class DFTLogger { return hash; } - inline HashType hash_and_store(const char *filename, + inline HashType hash_and_store(const char* filename, ConstEventNameType name) { if (filename == NULL) return NO_HASH_DEFAULT; char file[PATH_MAX]; @@ -467,7 +448,7 @@ class DFTLogger { HashType fhash = is_traced(entity, __FUNCTION__); \ bool trace = fhash != NO_HASH_DEFAULT; \ TimeResolution start_time = 0; \ - dftracer::Metadata *metadata = nullptr; \ + dftracer::Metadata* metadata = nullptr; \ if (trace) { \ if (this->logger->include_metadata) { \ metadata = new dftracer::Metadata(); \ @@ -480,7 +461,7 @@ class DFTLogger { DFTRACER_LOG_DEBUG("Calling function %s", __FUNCTION__); \ bool trace = true; \ TimeResolution start_time = 0; \ - dftracer::Metadata *metadata = nullptr; \ + dftracer::Metadata* metadata = nullptr; \ if (trace) { \ if (this->logger->include_metadata) { \ metadata = new dftracer::Metadata(); \ @@ -488,12 +469,12 @@ class DFTLogger { this->logger->enter_event(); \ start_time = this->logger->get_time(); \ } -#define DFT_LOGGER_END() \ - if (trace) { \ - TimeResolution end_time = this->logger->get_time(); \ - this->logger->log((char *)__FUNCTION__, CATEGORY, start_time, \ - end_time - start_time, metadata); \ - this->logger->exit_event(); \ +#define DFT_LOGGER_END() \ + if (trace) { \ + TimeResolution end_time = this->logger->get_time(); \ + this->logger->log((char*)__FUNCTION__, CATEGORY, start_time, \ + end_time - start_time, metadata); \ + this->logger->exit_event(); \ } #endif // DFTRACER_GENERIC_LOGGER_H diff --git a/src/dftracer/core/serialization/json_line.cpp b/src/dftracer/core/serialization/json_line.cpp index 406a9b80..11891c8f 100644 --- a/src/dftracer/core/serialization/json_line.cpp +++ b/src/dftracer/core/serialization/json_line.cpp @@ -5,8 +5,10 @@ #include #include +#include #include #include + namespace dftracer { template <> std::shared_ptr Singleton::instance = nullptr; @@ -17,19 +19,23 @@ JsonLines::JsonLines() : include_metadata(false) { include_metadata = conf->metadata; } -size_t JsonLines::initialize(char *buffer, HashType hostname_hash) { +size_t JsonLines::initialize(char* buffer, HashType hostname_hash) { this->hostname_hash = hostname_hash; +#if DFTRACER_WRITER_TYPE_MOFKA + return 0; +#else buffer[0] = '['; buffer[1] = '\n'; return 2; +#endif } -bool JsonLines::convert_metadata(Metadata *metadata, - std::stringstream &meta_stream) { +bool JsonLines::convert_metadata(Metadata* metadata, + std::stringstream& meta_stream) { auto meta_size = metadata->size(); long unsigned int i = 0; bool has_meta = false; - for (const auto &item : *metadata) { + for (const auto& item : *metadata) { has_meta = true; DFTRACER_FOR_EACH_NUMERIC_TYPE( DFTRACER_ANY_CAST_MACRO, item.second.second, { @@ -57,9 +63,9 @@ bool JsonLines::convert_metadata(Metadata *metadata, return has_meta; } -size_t JsonLines::data(char *buffer, int index, ConstEventNameType event_name, +size_t JsonLines::data(char* buffer, int index, ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, dftracer::Metadata *metadata, + TimeResolution duration, dftracer::Metadata* metadata, ProcessID process_id, ThreadID thread_id) { size_t written_size = 0; if (include_metadata && metadata != nullptr) { @@ -82,19 +88,21 @@ size_t JsonLines::data(char *buffer, int index, ConstEventNameType event_name, index, event_name, category, process_id, thread_id, start_time, duration); } +#if !DFTRACER_WRITER_TYPE_MOFKA if (written_size > 0) { buffer[written_size++] = '\n'; buffer[written_size] = '\0'; } +#endif DFTRACER_LOG_DEBUG("JsonLines.serialize %s", buffer); return written_size; } -size_t JsonLines::counter(char *buffer, int index, +size_t JsonLines::counter(char* buffer, int index, ConstEventNameType event_name, ConstEventNameType category, TimeResolution start_time, ProcessID process_id, - ThreadID thread_id, dftracer::Metadata *metadata) { + ThreadID thread_id, dftracer::Metadata* metadata) { size_t written_size = 0; if (metadata != nullptr && !metadata->empty()) { std::stringstream all_stream; @@ -114,15 +122,17 @@ size_t JsonLines::counter(char *buffer, int index, R"({"name":"%s","cat":"%s","ts":%llu,"ph":"C","pid":%d,"tid":%lu})", event_name, category, start_time, process_id, thread_id); } +#if !DFTRACER_WRITER_TYPE_MOFKA if (written_size > 0) { buffer[written_size++] = '\n'; buffer[written_size] = '\0'; } +#endif DFTRACER_LOG_DEBUG("JsonLines.serialize %s", buffer); return written_size; } -size_t JsonLines::metadata(char *buffer, ConstEventNameType name, +size_t JsonLines::metadata(char* buffer, ConstEventNameType name, ConstEventNameType value, ConstEventNameType ph, ProcessID process_id, ThreadID thread_id, bool is_string) { @@ -138,8 +148,10 @@ size_t JsonLines::metadata(char *buffer, ConstEventNameType name, R"({"name":"%s","cat":"dftracer","pid":%d,"tid":%lu,"ph":"M","args":{"hhash":"%s","name":"%s","value":%s}})", ph, process_id, thread_id, this->hostname_hash, name, value); } +#if !DFTRACER_WRITER_TYPE_MOFKA buffer[written_size++] = '\n'; buffer[written_size] = '\0'; +#endif DFTRACER_LOG_DEBUG("ChromeWriter.convert_json_metadata %s", buffer); return written_size; } @@ -149,22 +161,22 @@ size_t JsonLines::metadata(char *buffer, ConstEventNameType name, BLOCK; \ } -size_t JsonLines::aggregated(char *buffer, int index, ProcessID process_id, - dftracer::AggregatedDataType &data) { +size_t JsonLines::aggregated(char* buffer, int index, ProcessID process_id, + dftracer::AggregatedDataType& data) { size_t total_written = 0; DFTRACER_LOG_INFO("Writing %d intervals", data.size()); - for (const auto &interval_entry : data) { - const TimeResolution &interval = interval_entry.first; - const auto &event_map = interval_entry.second; + for (const auto& interval_entry : data) { + const TimeResolution& interval = interval_entry.first; + const auto& event_map = interval_entry.second; DFTRACER_LOG_INFO("Writing %d events for %llu", event_map.size(), interval); - for (const auto &event_entry : event_map) { - AggregatedValues *event_values = event_entry.second; + for (const auto& event_entry : event_map) { + AggregatedValues* event_values = event_entry.second; auto key = event_entry.first; auto metadata = key.additional_keys; - for (const auto &value_entry : event_values->values) { - const std::string &base_key = value_entry.first; - BaseAggregatedValue *base_value = value_entry.second; + for (const auto& value_entry : event_values->values) { + const std::string& base_key = value_entry.first; + BaseAggregatedValue* base_value = value_entry.second; if (!base_value) continue; // metadata->erase(base_key); auto id = base_value->_id; diff --git a/src/dftracer/core/utils/configuration_manager.cpp b/src/dftracer/core/utils/configuration_manager.cpp index 32e6f515..a383411c 100644 --- a/src/dftracer/core/utils/configuration_manager.cpp +++ b/src/dftracer/core/utils/configuration_manager.cpp @@ -68,13 +68,17 @@ dftracer::ConfigurationManager::ConfigurationManager() bind_signals(false), throw_error(false), write_buffer_size(16 * 1024 * 1024), - writer_type(WriterType::PERFETTO_CHROME_FILE), +#if DFTRACER_WRITER_TYPE_MOFKA + writer_type(WriterType::WRITER_TYPE_MOFKA), +#else + writer_type(WriterType::WRITER_TYPE_STDIO), +#endif trace_interval_ms(1000), aggregation_enable(false), aggregation_type(AggregationType::AGGREGATION_TYPE_FULL), aggregation_inclusion_rules(), aggregation_exclusion_rules() { - const char *env_conf = getenv(DFTRACER_CONFIGURATION); + const char* env_conf = getenv(DFTRACER_CONFIGURATION); YAML::Node config; if (env_conf != nullptr) { config = YAML::LoadFile(env_conf); @@ -86,7 +90,7 @@ dftracer::ConfigurationManager::ConfigurationManager() } } } - const char *env_log_level = getenv(DFTRACER_LOG_LEVEL); + const char* env_log_level = getenv(DFTRACER_LOG_LEVEL); if (env_log_level != nullptr) { convert(env_log_level, this->logger_level); } @@ -250,56 +254,56 @@ dftracer::ConfigurationManager::ConfigurationManager() this->write_buffer_size); } } - const char *env_enable = getenv(DFTRACER_ENABLE); + const char* env_enable = getenv(DFTRACER_ENABLE); if (env_enable != nullptr && strcmp(env_enable, "1") == 0) { this->enable = true; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.enable %d", this->enable); if (this->enable) { - const char *env_trace_interval = getenv(DFTRACER_TRACE_INTERVAL_MS); + const char* env_trace_interval = getenv(DFTRACER_TRACE_INTERVAL_MS); if (env_trace_interval != nullptr) { this->trace_interval_ms = atoi(env_trace_interval); } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.trace_interval_ms %d", this->trace_interval_ms); - const char *env_init_type = getenv(DFTRACER_INIT); + const char* env_init_type = getenv(DFTRACER_INIT); if (env_init_type != nullptr) { convert(env_init_type, this->init_type); } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.init_type %d", this->init_type); - const char *env_bind_signals = getenv(DFTRACER_BIND_SIGNALS); + const char* env_bind_signals = getenv(DFTRACER_BIND_SIGNALS); if (env_bind_signals != nullptr && strcmp(env_bind_signals, "1") == 0) { bind_signals = true; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.bind_signals %d", this->bind_signals); - const char *env_meta = getenv(DFTRACER_INC_METADATA); + const char* env_meta = getenv(DFTRACER_INC_METADATA); if (env_meta != nullptr && strcmp(env_meta, "1") == 0) { metadata = true; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.metadata %d", this->metadata); - const char *env_core = getenv(DFTRACER_SET_CORE_AFFINITY); + const char* env_core = getenv(DFTRACER_SET_CORE_AFFINITY); if (env_core != nullptr && strcmp(env_core, "1") == 0) { core_affinity = true; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.core_affinity %d", this->core_affinity); - const char *env_gotcha_priority = getenv(DFTRACER_GOTCHA_PRIORITY); + const char* env_gotcha_priority = getenv(DFTRACER_GOTCHA_PRIORITY); if (env_gotcha_priority != nullptr) { this->gotcha_priority = atoi(env_gotcha_priority); // GCOV_EXCL_LINE } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.gotcha_priority %d", this->gotcha_priority); - const char *env_log_file = getenv(DFTRACER_LOG_FILE); + const char* env_log_file = getenv(DFTRACER_LOG_FILE); if (env_log_file != nullptr) { this->log_file = env_log_file; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.log_file %s", this->log_file.c_str()); - const char *env_data_dirs = getenv(DFTRACER_DATA_DIR); + const char* env_data_dirs = getenv(DFTRACER_DATA_DIR); if (env_data_dirs != nullptr) { if (strcmp(env_data_dirs, DFTRACER_ALL_FILES) == 0) { this->trace_all_files = true; @@ -311,41 +315,41 @@ dftracer::ConfigurationManager::ConfigurationManager() this->data_dirs.c_str()); DFTRACER_LOG_DEBUG("ENV ConfigurationManager.trace_all_files %d", this->trace_all_files); - const char *disable_io = getenv(DFTRACER_DISABLE_IO); + const char* disable_io = getenv(DFTRACER_DISABLE_IO); if (disable_io != nullptr && strcmp(disable_io, "1") == 0) { this->io = false; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.io %d", this->io); if (this->io) { - const char *disable_posix = getenv(DFTRACER_DISABLE_POSIX); + const char* disable_posix = getenv(DFTRACER_DISABLE_POSIX); if (disable_posix != nullptr && strcmp(disable_posix, "1") == 0) { this->posix = false; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.posix %d", this->posix); - const char *disable_stdio = getenv(DFTRACER_DISABLE_STDIO); + const char* disable_stdio = getenv(DFTRACER_DISABLE_STDIO); if (disable_stdio != nullptr && strcmp(disable_stdio, "1") == 0) { this->stdio = false; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.stdio %d", this->stdio); } - const char *env_tid = getenv(DFTRACER_DISABLE_TIDS); + const char* env_tid = getenv(DFTRACER_DISABLE_TIDS); if (env_tid != nullptr && strcmp(env_tid, "0") == 0) { this->tids = false; } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.tids %d", this->tids); - const char *env_enable_aggregation = getenv(DFTRACER_ENABLE_AGGREGATION); + const char* env_enable_aggregation = getenv(DFTRACER_ENABLE_AGGREGATION); if (env_enable_aggregation != nullptr && strcmp(env_enable_aggregation, "1") == 0) { this->aggregation_enable = true; if (this->aggregation_enable) { this->aggregation_type = AggregationType::AGGREGATION_TYPE_FULL; - const char *env_aggregation_type = getenv(DFTRACER_AGGREGATION_TYPE); + const char* env_aggregation_type = getenv(DFTRACER_AGGREGATION_TYPE); if (env_aggregation_type != nullptr) { convert(env_aggregation_type, this->aggregation_type); } if (this->aggregation_type == AggregationType::AGGREGATION_TYPE_SELECTIVE) { - const char *env_aggregation_file = getenv(DFTRACER_AGGREGATION_FILE); + const char* env_aggregation_file = getenv(DFTRACER_AGGREGATION_FILE); if (env_aggregation_file != nullptr) { this->aggregation_file = env_aggregation_file; } @@ -358,13 +362,13 @@ dftracer::ConfigurationManager::ConfigurationManager() to_string(this->aggregation_type).c_str()); DFTRACER_LOG_DEBUG("ENV ConfigurationManager.aggregation_file %s", this->aggregation_file.c_str()); - const char *env_throw_error = getenv(DFTRACER_ERROR); + const char* env_throw_error = getenv(DFTRACER_ERROR); if (env_throw_error != nullptr && strcmp(env_throw_error, "1") == 0) { this->throw_error = true; // GCOVR_EXCL_LINE } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.throw_error %d", this->throw_error); - const char *env_compression = getenv(DFTRACER_TRACE_COMPRESSION); + const char* env_compression = getenv(DFTRACER_TRACE_COMPRESSION); if (env_compression != nullptr) { if (strcmp(env_compression, "1") == 0) this->compression = true; @@ -373,19 +377,25 @@ dftracer::ConfigurationManager::ConfigurationManager() } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.compression %d", this->compression); - const char *env_write_buf_size = getenv(DFTRACER_WRITE_BUFFER_SIZE); + const char* env_write_buf_size = getenv(DFTRACER_WRITE_BUFFER_SIZE); if (env_write_buf_size != nullptr) { this->write_buffer_size = atoi(env_write_buf_size); } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.write_buffer_size %d", this->write_buffer_size); - const char *writer_type = getenv(DFTRACER_WRITER_TYPE_ENV); + const char* writer_type = getenv(DFTRACER_WRITER_TYPE_ENV); if (writer_type != nullptr) { convert(writer_type, this->writer_type); } DFTRACER_LOG_DEBUG("ENV ConfigurationManager.writer_type %d", this->writer_type); } + if (this->writer_type == WriterType::WRITER_TYPE_MOFKA) { + if (this->compression) { + DFTRACER_LOG_WARN("Compression is not supported for Mofka writer", ""); + this->compression = false; + } + } derive_configurations(); DFTRACER_LOG_DEBUG("ENV ConfigurationManager finished", ""); } @@ -398,30 +408,30 @@ void dftracer::ConfigurationManager::derive_configurations() { // Load aggregation rules from the specified file YAML::Node agg_config = YAML::LoadFile(this->aggregation_file); if (agg_config[DFT_YAML_FEATURES_AGGREGATION_INCLUSION_FILTERS]) { - const auto &inclusion = + const auto& inclusion = agg_config[DFT_YAML_FEATURES_AGGREGATION_INCLUSION_FILTERS]; if (inclusion.IsSequence()) { - for (const auto &item : inclusion) { + for (const auto& item : inclusion) { this->aggregation_inclusion_rules.push_back(item.as()); } } } if (agg_config[DFT_YAML_FEATURES_AGGREGATION_EXCLUSION_FILTERS]) { - const auto &exclusion = + const auto& exclusion = agg_config[DFT_YAML_FEATURES_AGGREGATION_EXCLUSION_FILTERS]; if (exclusion.IsSequence()) { - for (const auto &item : exclusion) { + for (const auto& item : exclusion) { this->aggregation_exclusion_rules.push_back(item.as()); } } } DFTRACER_LOG_DEBUG("Aggregation inclusion rules", ""); - for (const auto &rule : this->aggregation_inclusion_rules) { + for (const auto& rule : this->aggregation_inclusion_rules) { (void)rule; DFTRACER_LOG_DEBUG(" - %s", rule.c_str()); } DFTRACER_LOG_DEBUG("Aggregation exclusion rules", ""); - for (const auto &rule : this->aggregation_exclusion_rules) { + for (const auto& rule : this->aggregation_exclusion_rules) { (void)rule; DFTRACER_LOG_DEBUG(" - %s", rule.c_str()); } diff --git a/src/dftracer/core/writer/mofka_writer.cpp b/src/dftracer/core/writer/mofka_writer.cpp new file mode 100644 index 00000000..23f657be --- /dev/null +++ b/src/dftracer/core/writer/mofka_writer.cpp @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace dftracer { +template <> +std::shared_ptr Singleton::instance = nullptr; +template <> +bool Singleton::stop_creating_instances = false; + +MofkaWriter::MofkaWriter() {} + +MofkaWriter::~MofkaWriter() { finalize(0); } + +void MofkaWriter::initialize(const char* filename) { + const char* group_file_env = std::getenv("DFTRACER_MOFKA_GROUP_FILE"); + if (!group_file_env) { + DFTRACER_LOG_ERROR("DFTRACER_MOFKA_GROUP_FILE not set", ""); + throw std::runtime_error("DFTRACER_MOFKA_GROUP_FILE not set"); + } + group_file_ = group_file_env; + const char* topic_name_env = std::getenv("DFTRACER_MOFKA_TOPIC_NAME"); + topic_name_ = topic_name_env ? topic_name_env : "dftracer_events"; + + // Allow Mofka/Mercury to access this process's memory for shared memory + // transport + // prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0); + + try { + diaspora::Metadata options; + options.json()["group_file"] = group_file_; + options.json()["margo"] = nlohmann::json::object(); + options.json()["margo"]["use_progress_thread"] = true; + + driver_ = std::make_unique( + diaspora::Driver::New("mofka", options)); + + if (!driver_->topicExists(topic_name_)) { + diaspora::Validator validator; + diaspora::Serializer serializer; + diaspora::PartitionSelector selector; + driver_->createTopic(topic_name_, diaspora::Metadata{}, validator, + selector, serializer); + driver_->as().addMemoryPartition(topic_name_, 0); + } + + topic_ = std::make_unique( + driver_->openTopic(topic_name_)); + + diaspora::BatchSize batchSize = diaspora::BatchSize::Adaptive(); + diaspora::ThreadCount threadCount = diaspora::ThreadCount{1}; + diaspora::Ordering ordering = diaspora::Ordering::Strict; + producer_ = std::make_unique( + topic_->producer("dftracer", batchSize, threadCount, ordering)); + } catch (const std::exception& e) { + DFTRACER_LOG_ERROR("Failed to initialize MofkaWriter", e.what()); + throw; + } +} + +size_t MofkaWriter::write(const char* data, size_t len, bool force) { + if (!topic_) return 0; + try { + producer_->push(diaspora::Metadata{data}, diaspora::DataView{}); + return len; + } catch (const std::exception& e) { + DFTRACER_LOG_ERROR("Mofka write failed", e.what()); + return 0; + } +} + +void MofkaWriter::finalize(int index) { + if (producer_) { + producer_->flush().wait(-1); + DFTRACER_LOG_INFO("Mofka producer flushed", ""); + producer_.reset(); + DFTRACER_LOG_INFO("Mofka producer reset", ""); + } + if (topic_) { + topic_.reset(); + DFTRACER_LOG_INFO("Mofka topic reset", ""); + } + if (driver_) { + driver_.reset(); + DFTRACER_LOG_INFO("Mofka driver reset", ""); + } +} + +} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/core/writer/mofka_writer.h b/src/dftracer/core/writer/mofka_writer.h new file mode 100644 index 00000000..16f42cec --- /dev/null +++ b/src/dftracer/core/writer/mofka_writer.h @@ -0,0 +1,32 @@ +#ifndef DFTRACER_MOFKA_WRITER_H +#define DFTRACER_MOFKA_WRITER_H + +#include + +#include +#include +#include +#include + +namespace dftracer { + +class MofkaWriter : public WriterInterface { + private: + std::string group_file_; + std::string topic_name_; + std::unique_ptr driver_; + std::unique_ptr producer_; + std::unique_ptr topic_; + + public: + MofkaWriter(); + ~MofkaWriter() override; + + void initialize(const char* filename) override; + size_t write(const char* data, size_t len, bool force = false) override; + void finalize(int index) override; +}; + +} // namespace dftracer + +#endif // DFTRACER_MOFKA_WRITER_H diff --git a/src/dftracer/core/writer/perfetto_chrome_file_writer.cpp b/src/dftracer/core/writer/perfetto_chrome_file_writer.cpp deleted file mode 100644 index 09536c3e..00000000 --- a/src/dftracer/core/writer/perfetto_chrome_file_writer.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// -// Created by haridev on 3/28/23. -// - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -template <> -std::shared_ptr - dftracer::Singleton::instance = nullptr; -template <> -bool dftracer::Singleton< - dftracer::PerfettoChromeFileWriter>::stop_creating_instances = false; - -namespace dftracer { - -void PerfettoChromeFileWriter::initialize(char *filename, bool throw_error, - HashType hostname_hash) { - this->hostname_hash = hostname_hash; - this->throw_error = throw_error; - this->filename = filename; - if (fh == nullptr) { - fh = fopen(filename, "ab+"); - if (fh == nullptr) { - DFTRACER_LOG_ERROR("unable to create log file %s", - filename); // GCOVR_EXCL_LINE - } else { - setvbuf(fh, NULL, _IOLBF, write_buffer_size + 4096); - DFTRACER_LOG_INFO("created log file %s", filename); - } - } - init = true; - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.initialize %s", - this->filename.c_str()); -} - - -void PerfettoChromeFileWriter::log(int index, ConstEventNameType event_name, - ConstEventNameType category, - TimeResolution start_time, - TimeResolution duration, Metadata *metadata, - ProcessID process_id, ThreadID thread_id) { - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.log", ""); - if (fh != nullptr) { - PerfettoChromeWriterBase::log(index, event_name, category, start_time, duration, metadata, process_id, thread_id); - } else { - DFTRACER_LOG_ERROR("PerfettoChromeFileWriter.log invalid", ""); - } - is_first_write = false; -} - - -void PerfettoChromeFileWriter::log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, - ConstEventNameType ph, - ProcessID process_id, ThreadID tid, - bool is_string) { - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.log_metadata", ""); - if (fh != nullptr) { - PerfettoChromeWriterBase::log_metadata(index, name, value, ph, process_id, tid, is_string); - } else { - DFTRACER_LOG_ERROR("PerfettoChromeFileWriter.log_metadata invalid", ""); - } - is_first_write = false; -} - -size_t PerfettoChromeFileWriter::flush_buffer_to_destination(bool force) { - std::unique_lock lock(mtx); - if (current_index == 0 || (!force && current_index < write_buffer_size)) - return 0; - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.write_buffer_op %s", - this->filename.c_str()); - size_t written_elements = 0; - flockfile(fh); - written_elements = fwrite(buffer.data(), current_index, sizeof(char), fh); - current_index = 0; - funlockfile(fh); - if (written_elements != 1) { // GCOVR_EXCL_START - DFTRACER_LOG_ERROR( - "unable to log write only %ld of %d trying to write %ld with error " - "code " - "%d", - written_elements, 1, current_index, errno); - } // GCOVR_EXCL_STOP - return written_elements; -} - -void PerfettoChromeFileWriter::finalize(bool has_entry) { - if (this->init) { - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.finalize", ""); - if (fh != nullptr) { - DFTRACER_LOG_INFO("Profiler finalizing writer %s", filename.c_str()); - flush_buffer_to_destination(true); - fflush(fh); - int status = fclose(fh); - if (status != 0) { - DFTRACER_LOG_ERROR("unable to close log file %s for a+", - filename.c_str()); // GCOVR_EXCL_LINE - } - if (!has_entry) { - DFTRACER_LOG_INFO("No trace data written deleting file %s", - filename.c_str()); - df_unlink(filename.c_str()); - } else { - DFTRACER_LOG_INFO("Profiler writing the final symbol", ""); - fh = fopen(this->filename.c_str(), "r+"); - if (fh != nullptr) { - std::string data = "[\n"; - auto written_elements = - fwrite(data.c_str(), sizeof(char), data.size(), fh); - if (written_elements != data.size()) { // GCOVR_EXCL_START - DFTRACER_LOG_ERROR( - "unable to finalize log write %s for O_WRONLY written only %ld " - "of %ld", - filename.c_str(), data.size(), written_elements); - } // GCOVR_EXCL_STOP - data = "]"; - fseek(fh, 0, SEEK_END); - written_elements = - fwrite(data.c_str(), sizeof(char), data.size(), fh); - if (written_elements != data.size()) { // GCOVR_EXCL_START - DFTRACER_LOG_ERROR( - "unable to finalize log write %s for O_WRONLY written only %ld " - "of %ld", - filename.c_str(), data.size(), written_elements); - } // GCOVR_EXCL_STOP - status = fclose(fh); - if (status != 0) { - DFTRACER_LOG_ERROR("unable to close log file %s for O_WRONLY", - filename.c_str()); // GCOVR_EXCL_LINE - } - fh = nullptr; - } - } - if (enable_compression) { - if (system("which gzip > /dev/null 2>&1")) { - DFTRACER_LOG_ERROR("Gzip compression does not exists", - ""); // GCOVR_EXCL_LINE - } else { - DFTRACER_LOG_INFO("Applying Gzip compression on file %s", - filename.c_str()); - char cmd[2048]; - sprintf(cmd, "gzip -f %s", filename.c_str()); - int ret = system(cmd); - if (ret == 0) { - DFTRACER_LOG_INFO("Successfully compressed file %s.gz", - filename.c_str()); - } else { - DFTRACER_LOG_ERROR("Unable to compress file %s", filename.c_str()); - } - } - } - } - if (enable_core_affinity) { -#if DISABLE_HWLOC == 1 - hwloc_topology_destroy(topology); -#endif - } - DFTRACER_LOG_DEBUG("Finished writer finalization", ""); - } else { - DFTRACER_LOG_DEBUG("Already finalized writer", ""); - } -} - -} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/core/writer/perfetto_chrome_file_writer.h b/src/dftracer/core/writer/perfetto_chrome_file_writer.h deleted file mode 100644 index b52ad642..00000000 --- a/src/dftracer/core/writer/perfetto_chrome_file_writer.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Created by haridev on 3/28/23. -// - -#ifndef DFTRACER_PERFETTO_CHROME_FILE_WRITER_H -#define DFTRACER_PERFETTO_CHROME_FILE_WRITER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace dftracer { -class PerfettoChromeFileWriter : public PerfettoChromeWriterBase { - private: - FILE *fh; - - protected: - size_t flush_buffer_to_destination(bool force = false) override; - - public: - PerfettoChromeFileWriter() : fh(nullptr) { - DFTRACER_LOG_DEBUG("PerfettoChromeFileWriter.PerfettoChromeFileWriter", ""); - } - ~PerfettoChromeFileWriter() { - DFTRACER_LOG_DEBUG("Destructing PerfettoChromeFileWriter", ""); - } - void initialize(char *filename, bool throw_error, - HashType hostname_hash) override; - void finalize(bool has_entry) override; -}; -} // namespace dftracer - -#endif // DFTRACER_PERFETTO_CHROME_FILE_WRITER_H diff --git a/src/dftracer/core/writer/perfetto_chrome_writer_base.cpp b/src/dftracer/core/writer/perfetto_chrome_writer_base.cpp deleted file mode 100644 index e8d54e7b..00000000 --- a/src/dftracer/core/writer/perfetto_chrome_writer_base.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// -// Created for shared Chrome writer functionality -// - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace dftracer { - -void PerfettoChromeWriterBase::log(int index, ConstEventNameType event_name, - ConstEventNameType category, - TimeResolution start_time, - TimeResolution duration, - Metadata *metadata, ProcessID process_id, - ThreadID thread_id) { - DFTRACER_LOG_DEBUG("PerfettoChromeWriterBase.log", ""); - write_event_json_to_buffer(index, event_name, category, start_time, duration, - metadata, process_id, thread_id); - flush_buffer_to_destination(false); - is_first_write = false; -} - -void PerfettoChromeWriterBase::log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, - ConstEventNameType ph, - ProcessID process_id, ThreadID tid, - bool is_string) { - DFTRACER_LOG_DEBUG("PerfettoChromeWriterBase.log_metadata", ""); - write_metadata_json_to_buffer(index, name, value, ph, process_id, tid, - is_string); - flush_buffer_to_destination(false); - is_first_write = false; -} - -void PerfettoChromeWriterBase::write_event_json_to_buffer( - int index, ConstEventNameType event_name, ConstEventNameType category, - TimeResolution start_time, TimeResolution duration, Metadata *metadata, - ProcessID process_id, ThreadID thread_id) { - size_t previous_index = 0; - (void)previous_index; - - char is_first_char[3] = " "; - if (!is_first_write) { - is_first_char[0] = '\0'; - } - - std::string metadata_json_string; - if (include_metadata && metadata != nullptr) { - metadata_json_string = convert_metadata_to_json_string(metadata); - } - - { - std::unique_lock lock(mtx); - previous_index = current_index; - auto written_size = sprintf( - buffer.data() + current_index, - R"(%s{"id":%d,"name":"%s","cat":"%s","pid":%d,"tid":%lu,"ts":%llu,"dur":%llu,"ph":"X"%s})", - is_first_char, index, event_name, category, process_id, thread_id, - start_time, duration, metadata_json_string.c_str()); - current_index += written_size; - buffer[current_index] = '\n'; - current_index++; - } - - DFTRACER_LOG_DEBUG( - "PerfettoChromeWriterBase.write_event_json_to_buffer %s on %s", - buffer.data() + previous_index, this->filename.c_str()); -} - -void PerfettoChromeWriterBase::write_metadata_json_to_buffer( - int index, ConstEventNameType name, ConstEventNameType value, - ConstEventNameType ph, ProcessID process_id, ThreadID thread_id, - bool is_string) { - size_t previous_index = 0; - (void)previous_index; - - char is_first_char[3] = " "; - if (!is_first_write) { - is_first_char[0] = '\0'; - } - - { - std::unique_lock lock(mtx); - previous_index = current_index; - auto written_size = 0; - if (is_string) { - written_size = sprintf( - buffer.data() + current_index, - R"(%s{"id":%d,"name":"%s","cat":"dftracer","pid":%d,"tid":%lu,"ph":"M","args":{"hhash":"%s","name":"%s","value":"%s"}})", - is_first_char, index, ph, process_id, thread_id, this->hostname_hash, - name, value); - } else { - written_size = sprintf( - buffer.data() + current_index, - R"(%s{"id":%d,"name":"%s","cat":"dftracer","pid":%d,"tid":%lu,"ph":"M","args":{"hhash":"%s","name":"%s","value":%s}})", - is_first_char, index, ph, process_id, thread_id, this->hostname_hash, - name, value); - } - current_index += written_size; - buffer[current_index] = '\n'; - current_index++; - } - - DFTRACER_LOG_DEBUG( - "PerfettoChromeWriterBase.write_metadata_json_to_buffer %s on %s", - buffer.data() + previous_index, this->filename.c_str()); -} - -std::string PerfettoChromeWriterBase::convert_metadata_to_json_string( - Metadata *metadata) { - std::stringstream metadata_stream; - metadata_stream << R"(,"args":{"hhash":")" << this->hostname_hash << "\""; - if (metadata != nullptr && !metadata->empty()) { - for (auto item : *metadata) { - metadata_stream << ","; - metadata_stream << "\"" << item.first << "\":"; - if (item.second.second.type() == typeid(unsigned int)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.second.type() == typeid(int)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.second.type() == typeid(const char *)) { - metadata_stream << "\"" << std::any_cast(item.second) - << "\""; - } else if (item.second.second.type() == typeid(std::string)) { - metadata_stream << "\"" << std::any_cast(item.second) - << "\""; - } else if (item.second.second.type() == typeid(size_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.second.type() == typeid(uint16_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.second.type() == typeid(HashType)) { - metadata_stream << "\"" << std::any_cast(item.second) << "\""; - } else if (item.second.second.type() == typeid(long)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.second.type() == typeid(ssize_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.second.type() == typeid(off_t)) { - metadata_stream << std::any_cast(item.second); - } else if (item.second.second.type() == typeid(off64_t)) { - metadata_stream << std::any_cast(item.second); - } else { - DFTRACER_LOG_WARN("No conversion for type %s", item.first.c_str()); - } - } - } - metadata_stream << "}"; - return metadata_stream.str(); -} - -} // namespace dftracer diff --git a/src/dftracer/core/writer/perfetto_chrome_writer_base.h b/src/dftracer/core/writer/perfetto_chrome_writer_base.h deleted file mode 100644 index 99bf4d53..00000000 --- a/src/dftracer/core/writer/perfetto_chrome_writer_base.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// Created for shared Chrome writer functionality -// - -#ifndef DFTRACER_PERFETTO_CHROME_WRITER_BASE_H -#define DFTRACER_PERFETTO_CHROME_WRITER_BASE_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace dftracer { -class PerfettoChromeWriterBase : public WriterBase { - protected: - static const int MAX_LINE_SIZE = 16 * 1024L; - std::mutex mtx; - std::vector buffer; - size_t current_index; - size_t write_buffer_size; - bool is_first_write = true; - - // Pure virtual method for flushing buffer - to be implemented by derived - // classes - virtual size_t flush_buffer_to_destination(bool force = false) = 0; - - public: - PerfettoChromeWriterBase() : current_index(0), write_buffer_size(0), is_first_write(true) { - DFTRACER_LOG_DEBUG("PerfettoChromeWriterBase.PerfettoChromeWriterBase", ""); - auto conf = - dftracer::Singleton::get_instance(); - enable_compression = conf->compression; - enable_core_affinity = conf->core_affinity; - include_metadata = conf->metadata; - write_buffer_size = conf->write_buffer_size; - { - std::unique_lock lock(mtx); - buffer = std::vector(write_buffer_size + MAX_LINE_SIZE); - current_index = 0; - } - } - - virtual ~PerfettoChromeWriterBase() { - DFTRACER_LOG_DEBUG("Destructing PerfettoChromeWriterBase", ""); - } - - void log(int index, ConstEventNameType event_name, - ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, Metadata *metadata, ProcessID process_id, - ThreadID tid) override; - - void log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, ConstEventNameType ph, - ProcessID process_id, ThreadID tid, - bool is_string = true) override; - - void set_write_buffer_size(size_t buffer_size) { - std::unique_lock lock(mtx); - write_buffer_size = buffer_size; - buffer = std::vector(write_buffer_size + MAX_LINE_SIZE); - current_index = 0; - } - - protected: - std::string convert_metadata_to_json_string(Metadata *metadata); - void write_event_json_to_buffer(int index, ConstEventNameType event_name, - ConstEventNameType category, - TimeResolution start_time, - TimeResolution duration, - Metadata *metadata, ProcessID process_id, - ThreadID thread_id); - void write_metadata_json_to_buffer(int index, ConstEventNameType name, - ConstEventNameType value, - ConstEventNameType ph, - ProcessID process_id, ThreadID thread_id, - bool is_string); -}; -} // namespace dftracer - -#endif // DFTRACER_PERFETTO_CHROME_WRITER_BASE_H diff --git a/src/dftracer/core/writer/perfetto_chrome_zmq_writer.cpp b/src/dftracer/core/writer/perfetto_chrome_zmq_writer.cpp deleted file mode 100644 index c7545bce..00000000 --- a/src/dftracer/core/writer/perfetto_chrome_zmq_writer.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -template <> -std::shared_ptr - dftracer::Singleton::instance = nullptr; -template <> -bool dftracer::Singleton< - dftracer::PerfettoChromeZMQWriter>::stop_creating_instances = false; - -namespace dftracer { - -static PerfettoChromeZMQWriter* writer_instance = nullptr; - -void on_fork_child() { - if (writer_instance) { - DFTRACER_LOG_DEBUG("Fork child: re-initializing ZMQ socket.", ""); - writer_instance->reconnect(); - } -} - -size_t PerfettoChromeZMQWriter::flush_buffer_to_destination(bool force) { - std::unique_lock lock(mtx); - if (current_index == 0 || (!force && current_index < write_buffer_size)) - return 0; - DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter.flush_buffer_to_stream %s", - this->filename.c_str()); - - size_t bytes_to_send = current_index; - if (socket && bytes_to_send > 0) { - try { - // Create ZMQ message from buffer content - zmq::message_t message(buffer.data(), bytes_to_send); - auto result = socket->send(message, zmq::send_flags::dontwait); - if (result) { - DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter sent %zu bytes", - bytes_to_send); - current_index = 0; // Reset buffer after successful send - return bytes_to_send; - } else { - DFTRACER_LOG_ERROR("PerfettoChromeZMQWriter failed to send message", - ""); - return 0; - } - } catch (const zmq::error_t& e) { - DFTRACER_LOG_ERROR("PerfettoChromeZMQWriter ZMQ error: %s", e.what()); - return 0; - } - } - return 0; -} - -void PerfettoChromeZMQWriter::initialize(char* filename, bool throw_error, - HashType hostname_hash) { - this->hostname_hash = hostname_hash; - this->throw_error = throw_error; - this->filename = filename; - - context = std::make_unique(1); - socket = std::make_unique(*context, zmq::socket_type::push); - if (!socket) { - DFTRACER_LOG_ERROR("unable to create ZeroMQ socket %s", filename); - } - socket->connect(filename); - - writer_instance = this; - - pthread_atfork(nullptr, nullptr, on_fork_child); - - init = true; - DFTRACER_LOG_DEBUG( - "PerfettoChromeZMQWriter.initialize on %s with fork handling", - this->filename.c_str()); -} - -void PerfettoChromeZMQWriter::finalize(bool has_entry) { - if (init) { - DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter.finalize", ""); - - socket->close(); - context->close(); - - if (writer_instance == this) { - writer_instance = nullptr; - } - - init = false; - - DFTRACER_LOG_DEBUG("Finished writer finalization", ""); - } else { - DFTRACER_LOG_DEBUG("Already finalized writer", ""); - } -} - -void PerfettoChromeZMQWriter::reconnect() { - DFTRACER_LOG_DEBUG("Child process starting ZMQ reconnect", ""); - - // Release ownership of the inherited pointers. - // This prevents the destructor (and zmq_close) from being called. - // The old state is invalid and must be abandoned. - if (socket) socket.release(); - if (context) context.release(); - - DFTRACER_LOG_DEBUG("Child process abandoned inherited ZMQ state", ""); - - // Create a brand new context and socket for this child process. - context = std::make_unique(1); - socket = std::make_unique(*context, zmq::socket_type::push); - - if (!socket) { - DFTRACER_LOG_ERROR("Unable to create new ZeroMQ socket in child for %s", - this->filename.c_str()); - return; - } - - // Connect the new socket to the original destination. - socket->connect(this->filename.c_str()); - DFTRACER_LOG_DEBUG("Child process successfully reconnected ZMQ socket to %s", - this->filename.c_str()); -} - -} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/core/writer/perfetto_chrome_zmq_writer.h b/src/dftracer/core/writer/perfetto_chrome_zmq_writer.h deleted file mode 100644 index 487bea82..00000000 --- a/src/dftracer/core/writer/perfetto_chrome_zmq_writer.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef DFTRACER_PERFETTO_CHROME_ZMQ_WRITER_H -#define DFTRACER_PERFETTO_CHROME_ZMQ_WRITER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace dftracer { -class PerfettoChromeZMQWriter : public PerfettoChromeWriterBase { - private: - std::unique_ptr context; - std::unique_ptr socket; - - protected: - size_t flush_buffer_to_destination(bool force = false) override; - - public: - PerfettoChromeZMQWriter() { - DFTRACER_LOG_DEBUG("PerfettoChromeZMQWriter.PerfettoChromeZMQWriter", ""); - } - ~PerfettoChromeZMQWriter() { - DFTRACER_LOG_DEBUG("Destructing PerfettoChromeZMQWriter", ""); - } - void initialize(char *filename, bool throw_error, - HashType hostname_hash) override; - void finalize(bool has_entry) override; - /** - * @brief Re-initializes the ZMQ socket. This is intended to be called - * in a child process after a fork(). - */ - void reconnect(); -}; -} // namespace dftracer - -#endif // DFTRACER_PERFETTO_CHROME_ZMQ_WRITER_H diff --git a/src/dftracer/core/writer/perfetto_proto_file_writer.cpp b/src/dftracer/core/writer/perfetto_proto_file_writer.cpp deleted file mode 100644 index c4f24f7b..00000000 --- a/src/dftracer/core/writer/perfetto_proto_file_writer.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -PERFETTO_DEFINE_CATEGORIES( - perfetto::Category("dftracer").SetDescription("DFTracer Events")); - -PERFETTO_TRACK_EVENT_STATIC_STORAGE(); - -template <> -std::shared_ptr - dftracer::Singleton::instance = nullptr; -template <> -bool dftracer::Singleton< - dftracer::PerfettoProtoFileWriter>::stop_creating_instances = false; - -namespace dftracer { -void PerfettoProtoFileWriter::initialize(char *filename, bool throw_error, - HashType hostname_hash) { - this->hostname_hash = hostname_hash; - this->throw_error = throw_error; - this->filename = filename; - - perfetto::TracingInitArgs tracing_args; - tracing_args.backends = perfetto::kInProcessBackend; - perfetto::Tracing::Initialize(tracing_args); - perfetto::TrackEvent::Register(); - - perfetto::TraceConfig trace_config; - trace_config.set_flush_period_ms(200); - auto *buffer_config = trace_config.add_buffers(); - buffer_config->set_size_kb(write_buffer_size / 1024); - auto *data_source_config = trace_config.add_data_sources()->mutable_config(); - data_source_config->set_name("track_event"); - - int trace_fd = open(this->filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644); - if (trace_fd == -1) { - DFTRACER_LOG_ERROR("unable to create log file %s", filename); - if (this->throw_error) { - throw std::runtime_error("unable to create log file"); - } - return; - } - - tracing_session = perfetto::Tracing::NewTrace(); - tracing_session->Setup(trace_config, trace_fd); - tracing_session->StartBlocking(); - - init = true; - - DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.initialize %s", - this->filename.c_str()); -} - -void PerfettoProtoFileWriter::log(int index, ConstEventNameType event_name, - ConstEventNameType category, - TimeResolution start_time, - TimeResolution duration, - Metadata *metadata, ProcessID process_id, - ThreadID thread_id) { - DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.log", ""); - if (!init) { - DFTRACER_LOG_ERROR("PerfettoProtoFileWriter not initialized", ""); - return; - } - - perfetto::TrackEvent::Trace([&](perfetto::TrackEvent::TraceContext ctx) { - auto packet = ctx.NewTracePacket(); - packet->set_timestamp(start_time * 1000); - packet->set_timestamp_clock_id( - perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); - - auto event = packet->set_track_event(); - event->add_categories(category); - event->set_name(event_name); - - auto *legacy_event = event->set_legacy_event(); - legacy_event->set_phase('X'); - legacy_event->set_duration_us(duration); - legacy_event->set_thread_duration_us(duration); - legacy_event->set_pid_override(process_id); - legacy_event->set_tid_override(thread_id); - - auto *hostname_annot = event->add_debug_annotations(); - hostname_annot->set_name("hhash"); - hostname_annot->set_string_value(this->hostname_hash); - if (metadata) { - for (auto const &[key, val] : *metadata) { - auto *debug_annot = event->add_debug_annotations(); - debug_annot->set_name(key.c_str()); - if (val.type() == typeid(int)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(unsigned int)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(long)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(unsigned long)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(long long)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(unsigned long long)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(const char *)) { - debug_annot->set_string_value(std::any_cast(val)); - } else if (val.type() == typeid(std::string)) { - debug_annot->set_string_value(std::any_cast(val)); - } else if (val.type() == typeid(HashType)) { - debug_annot->set_string_value(std::any_cast(val)); - } else if (val.type() == typeid(size_t)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(uint16_t)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(ssize_t)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(off_t)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(off64_t)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(float)) { - debug_annot->set_double_value(std::any_cast(val)); - } else if (val.type() == typeid(double)) { - debug_annot->set_double_value(std::any_cast(val)); - } else { - DFTRACER_LOG_WARN("No conversion for type %s", key.c_str()); - } - } - } - }); -} - -void PerfettoProtoFileWriter::log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, - ConstEventNameType ph, - ProcessID process_id, - ThreadID thread_id, bool is_string) { - DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.log_metadata", ""); -} - -void PerfettoProtoFileWriter::finalize(bool has_entry) { - DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.finalize", ""); - if (init) { - tracing_session->StopBlocking(); - - init = false; - } else { - DFTRACER_LOG_ERROR("PerfettoProtoFileWriter.finalize invalid", ""); - } -} - -} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/core/writer/perfetto_proto_file_writer.h b/src/dftracer/core/writer/perfetto_proto_file_writer.h deleted file mode 100644 index 07e96d7f..00000000 --- a/src/dftracer/core/writer/perfetto_proto_file_writer.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef DFTRACER_PERFETTO_PROTO_FILE_WRITER_H -#define DFTRACER_PERFETTO_PROTO_FILE_WRITER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace dftracer { -class PerfettoProtoFileWriter : public WriterBase { - private: - std::unique_ptr tracing_session; - size_t write_buffer_size; - - void stream_main(std::unique_ptr session); - - public: - PerfettoProtoFileWriter() { - DFTRACER_LOG_DEBUG("PerfettoProtoFileWriter.PerfettoProtoFileWriter", ""); - auto conf = - dftracer::Singleton::get_instance(); - enable_compression = conf->compression; - enable_core_affinity = conf->core_affinity; - include_metadata = conf->metadata; - write_buffer_size = conf->write_buffer_size; - } - ~PerfettoProtoFileWriter() { - DFTRACER_LOG_DEBUG("Destructing PerfettoProtoFileWriter", ""); - } - void initialize(char *filename, bool throw_error, HashType hostname_hash); - void log(int index, ConstEventNameType event_name, - ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, Metadata *metadata, ProcessID process_id, - ThreadID tid); - void log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, ConstEventNameType ph, - ProcessID process_id, ThreadID tid, bool is_string = true); - void finalize(bool has_entry); - void set_write_buffer_size(size_t buffer_size) { - write_buffer_size = buffer_size; - } -}; -} // namespace dftracer - -#endif // DFTRACER_PERFETTO_PROTO_FILE_WRITER_H diff --git a/src/dftracer/core/writer/perfetto_proto_zmq_writer.cpp b/src/dftracer/core/writer/perfetto_proto_zmq_writer.cpp deleted file mode 100644 index aa1dde2d..00000000 --- a/src/dftracer/core/writer/perfetto_proto_zmq_writer.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -PERFETTO_DEFINE_CATEGORIES( - perfetto::Category("dftracer").SetDescription("DFTracer Events")); - -PERFETTO_TRACK_EVENT_STATIC_STORAGE(); - -template <> -std::shared_ptr - dftracer::Singleton::instance = nullptr; -template <> -bool dftracer::Singleton< - dftracer::PerfettoProtoZMQWriter>::stop_creating_instances = false; - -namespace dftracer { -void PerfettoProtoZMQWriter::initialize(char *filename, bool throw_error, - HashType hostname_hash) { - this->hostname_hash = hostname_hash; - this->throw_error = throw_error; - this->filename = filename; - - perfetto::TracingInitArgs tracing_args; - tracing_args.backends = perfetto::kInProcessBackend; - // args.shmem_size_kb = (1024 * 16); // 16MB buffer - // args.shmem_page_size_kb = 4; - perfetto::Tracing::Initialize(tracing_args); - perfetto::TrackEvent::Register(); - - perfetto::TraceConfig trace_config; - trace_config.add_buffers()->set_size_kb(1024 * 16); // 16MB buffer - auto *data_source_config = trace_config.add_data_sources()->mutable_config(); - data_source_config->set_name("track_event"); - - tracing_session = perfetto::Tracing::NewTrace(); - tracing_session->Setup(trace_config); - tracing_session->StartBlocking(); - - context = std::make_unique(1); - socket = std::make_unique(*context, zmq::socket_type::push); - if (!socket) { - DFTRACER_LOG_ERROR("unable to create ZeroMQ socket %s", filename); - } - socket->connect(filename); - - stop_stream = false; - stream_thread = std::thread(&PerfettoProtoZMQWriter::stream_main, this, - std::move(tracing_session)); - - init = true; - DFTRACER_LOG_INFO("created ZeroMQ socket and connected to %s", filename); -} - -void PerfettoProtoZMQWriter::log(int index, ConstEventNameType event_name, - ConstEventNameType category, - TimeResolution start_time, - TimeResolution duration, Metadata *metadata, - ProcessID process_id, ThreadID thread_id) { - DFTRACER_LOG_DEBUG("PerfettoProtoZMQWriter.log", ""); - if (!init) { - DFTRACER_LOG_ERROR("PerfettoProtoZMQWriter not initialized", ""); - return; - } - std::lock_guard lock(mtx); - - perfetto::TrackEvent::Trace([&](perfetto::TrackEvent::TraceContext ctx) { - auto packet = ctx.NewTracePacket(); - packet->set_timestamp(start_time * 1000); - packet->set_timestamp_clock_id( - perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); - - auto event = packet->set_track_event(); - event->add_categories(category); - event->set_name(event_name); - - auto *legacy_event = event->set_legacy_event(); - legacy_event->set_phase('X'); - legacy_event->set_duration_us(duration); - legacy_event->set_thread_duration_us(duration); - legacy_event->set_pid_override(process_id); - legacy_event->set_tid_override(thread_id); - - auto *hostname_annot = event->add_debug_annotations(); - hostname_annot->set_name("hhash"); - hostname_annot->set_string_value(this->hostname_hash); - if (metadata) { - for (auto const &[key, val] : *metadata) { - auto *debug_annot = event->add_debug_annotations(); - debug_annot->set_name(key.c_str()); - if (val.type() == typeid(int)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(unsigned int)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(long)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(unsigned long)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(long long)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(unsigned long long)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(const char *)) { - debug_annot->set_string_value(std::any_cast(val)); - } else if (val.type() == typeid(std::string)) { - debug_annot->set_string_value(std::any_cast(val)); - } else if (val.type() == typeid(HashType)) { - debug_annot->set_string_value(std::any_cast(val)); - } else if (val.type() == typeid(size_t)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(uint16_t)) { - debug_annot->set_uint_value(std::any_cast(val)); - } else if (val.type() == typeid(ssize_t)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(off_t)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(off64_t)) { - debug_annot->set_int_value(std::any_cast(val)); - } else if (val.type() == typeid(float)) { - debug_annot->set_double_value(std::any_cast(val)); - } else if (val.type() == typeid(double)) { - debug_annot->set_double_value(std::any_cast(val)); - } else { - DFTRACER_LOG_WARN("No conversion for type %s", key.c_str()); - } - } - } - }); -} - -void PerfettoProtoZMQWriter::log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, - ConstEventNameType ph, - ProcessID process_id, - ThreadID thread_id, bool is_string) { - DFTRACER_LOG_DEBUG("PerfettoProtoZMQWriter.log_metadata", ""); -} - -void PerfettoProtoZMQWriter::stream_main( - std::unique_ptr session) { - while (!stop_stream.load(std::memory_order_relaxed)) { - auto trace_data = session->ReadTraceBlocking(); - if (!trace_data.empty()) { - zmq::message_t message(trace_data.data(), trace_data.size()); - socket->send(message, zmq::send_flags::dontwait); - } - } - session->FlushBlocking(); - auto trace_data = session->ReadTraceBlocking(); - if (!trace_data.empty()) { - zmq::message_t message(trace_data.data(), trace_data.size()); - socket->send(message, zmq::send_flags::dontwait); - } -} - -void PerfettoProtoZMQWriter::finalize(bool has_entry) { - DFTRACER_LOG_DEBUG("PerfettoProtoZMQWriter.finalize", ""); - if (init) { - tracing_session->StopBlocking(); - - stop_stream.store(true); - if (stream_thread.joinable()) { - stream_thread.join(); - } - - socket->close(); - context->close(); - - init = false; - } else { - DFTRACER_LOG_ERROR("PerfettoProtoZMQWriter.finalize invalid", ""); - } -} - -} // namespace dftracer \ No newline at end of file diff --git a/src/dftracer/core/writer/perfetto_proto_zmq_writer.h b/src/dftracer/core/writer/perfetto_proto_zmq_writer.h deleted file mode 100644 index 53cfc6bb..00000000 --- a/src/dftracer/core/writer/perfetto_proto_zmq_writer.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef DFTRACER_PERFETTO_PROTO_ZMQ_WRITER_H -#define DFTRACER_PERFETTO_PROTO_ZMQ_WRITER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace dftracer { -class PerfettoProtoZMQWriter : public WriterBase { - private: - std::mutex mtx; - std::unique_ptr context; - std::unique_ptr socket; - std::thread stream_thread; - std::atomic stop_stream; - std::unique_ptr tracing_session; - - void stream_main(std::unique_ptr session); - - public: - PerfettoProtoZMQWriter() { - DFTRACER_LOG_DEBUG("PerfettoProtoZMQWriter.PerfettoProtoZMQWriter", ""); - auto conf = - dftracer::Singleton::get_instance(); - include_metadata = conf->metadata; - enable_core_affinity = conf->core_affinity; - } - ~PerfettoProtoZMQWriter() { - DFTRACER_LOG_DEBUG("Destructing PerfettoProtoZMQWriter", ""); - } - void initialize(char *filename, bool throw_error, HashType hostname_hash); - void log(int index, ConstEventNameType event_name, - ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, Metadata *metadata, ProcessID process_id, - ThreadID tid); - void log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, ConstEventNameType ph, - ProcessID process_id, ThreadID tid, bool is_string = true); - void finalize(bool has_entry); -}; -} // namespace dftracer - -#endif // DFTRACER_PERFETTO_PROTO_ZMQ_WRITER_H diff --git a/src/dftracer/core/writer/stdio_writer.h b/src/dftracer/core/writer/stdio_writer.h index 15e51621..e9148686 100644 --- a/src/dftracer/core/writer/stdio_writer.h +++ b/src/dftracer/core/writer/stdio_writer.h @@ -2,15 +2,17 @@ #include #include #include +#include #include #include #include + namespace dftracer { -class STDIOWriter { +class STDIOWriter : public WriterInterface { public: STDIOWriter() : max_size_(0), fh_(nullptr) {} - void initialize(const char* filename) { + void initialize(const char* filename) override { this->filename = filename; auto conf = dftracer::Singleton::get_instance(); @@ -28,7 +30,7 @@ class STDIOWriter { void initialize() {} ~STDIOWriter() {} - void finalize(int index) { + void finalize(int index) override { if (fh_ != nullptr) { DFTRACER_LOG_INFO("Finalizing STDIOWriter", ""); fflush(fh_); @@ -51,7 +53,7 @@ class STDIOWriter { } // Write data to buffer, flush if necessary - size_t write(const char* data, size_t len, bool force = false) { + size_t write(const char* data, size_t len, bool force = false) override { if (fh_ != nullptr && (force || len >= max_size_)) { // Use stdio file locking (flockfile/funlockfile) for FILE* // needed for fork and spawn cases to maintain consistency diff --git a/src/dftracer/core/writer/writer_base.h b/src/dftracer/core/writer/writer_base.h deleted file mode 100644 index 7131a9f7..00000000 --- a/src/dftracer/core/writer/writer_base.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef DFTRACER_WRITER_BASE_H -#define DFTRACER_WRITER_BASE_H - -#include -#include - -#include -#include -#include -#include -#include - -namespace dftracer { -class WriterBase { - protected: - std::string filename; - HashType hostname_hash; - bool enable_compression = false; - bool enable_core_affinity = false; - bool include_metadata = false; - bool init = false; - bool throw_error = false; - - public: - virtual ~WriterBase() = default; - virtual void initialize(char *filename, bool throw_error, - HashType hostname_hash) = 0; - virtual void log(int index, ConstEventNameType event_name, - ConstEventNameType category, TimeResolution start_time, - TimeResolution duration, dftracer::Metadata *metadata, - ProcessID process_id, ThreadID tid) = 0; - virtual void log_metadata(int index, ConstEventNameType name, - ConstEventNameType value, ConstEventNameType ph, - ProcessID process_id, ThreadID tid, - bool is_string = true) = 0; - virtual void finalize(bool has_entry) = 0; -}; -} // namespace dftracer - -#endif // DFTRACER_WRITER_BASE_H \ No newline at end of file diff --git a/src/dftracer/core/writer/writer_interface.h b/src/dftracer/core/writer/writer_interface.h new file mode 100644 index 00000000..b275b1c3 --- /dev/null +++ b/src/dftracer/core/writer/writer_interface.h @@ -0,0 +1,16 @@ +#ifndef DFTRACER_WRITER_INTERFACE_H +#define DFTRACER_WRITER_INTERFACE_H + +#include + +namespace dftracer { +class WriterInterface { + public: + virtual void initialize(const char* filename) = 0; + virtual size_t write(const char* data, size_t len, bool force = false) = 0; + virtual void finalize(int index) = 0; + virtual ~WriterInterface() = default; +}; +} // namespace dftracer + +#endif // DFTRACER_WRITER_INTERFACE_H diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9b05b759..3d7cf1cd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,17 +1,50 @@ set_property(GLOBAL PROPERTY COVERAGE_FILES "") include_directories(${DFTRACER_PROJECT_DIR}/include) +set(MOFKA_SERVER_FIXTURE "MOFKA_SERVER") + +find_program(BASH_EXE bash) +if (DFTRACER_WRITER_TYPE_MOFKA) + find_program(BEDROCK_EXE bedrock REQUIRED) + add_test(mofka_server_start ${CMAKE_CURRENT_SOURCE_DIR}/mofka_server_start.sh ${BEDROCK_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/mofka.config.json ${CMAKE_CURRENT_BINARY_DIR}/mofka_server.log) + add_test(mofka_server_stop ${CMAKE_CURRENT_SOURCE_DIR}/mofka_server_stop.sh) + set_tests_properties(mofka_server_start PROPERTIES FIXTURES_SETUP ${MOFKA_SERVER_FIXTURE}) + set_tests_properties(mofka_server_stop PROPERTIES FIXTURES_CLEANUP ${MOFKA_SERVER_FIXTURE}) +endif() + function(df_add_test) add_test(${ARGV}) set_tests_properties(${ARGV0} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${ARGV0}.profraw") get_property(OLD_CF GLOBAL PROPERTY COVERAGE_FILES) - # Use test_fixture_name for constructing the profraw path - set(NEW_CF ${OLD_CF} ${CMAKE_CURRENT_BINARY_DIR}/${test_fixture_name}.profraw) + set(NEW_CF ${OLD_CF} ${CMAKE_CURRENT_BINARY_DIR}/${ARGV0}.profraw) set_property(GLOBAL PROPERTY COVERAGE_FILES ${NEW_CF}) endfunction() +function(df_check_test test_name expected_count) + if (DFTRACER_WRITER_TYPE_MOFKA) + df_add_test(check_${test_name} + ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_mofka_topic.py ${test_name} ${expected_count}) + set_tests_properties(check_${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) + set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${CMAKE_CURRENT_BINARY_DIR}/mofka.flock.json) + set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) + else() + if (${expected_count} EQUAL 0) + df_add_test(check_${test_name} + ${BASH_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_not.sh + ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* + ) + else() + df_add_test(check_${test_name} + ${BASH_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh + ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* ${expected_count} + ) + endif() + endif() + set_tests_properties(check_${test_name} PROPERTIES DEPENDS ${test_name}) +endfunction() + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(test_cpp cpp/test.cpp) @@ -29,44 +62,36 @@ add_dependencies(test_c ${PROJECT_NAME}_core_dbg) add_dependencies(test_c ${PROJECT_NAME}_preload_dbg) function(set_common_properties test_name) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=DEBUG) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_TRACE_COMPRESSION=1) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE_AGGREGATION=OFF) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${DFTRACER_TEST_LD_LIBRARY_PATH}) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_BIND_SIGNALS=0) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_CURRENT_BINARY_DIR}/data) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE_AGGREGATION=OFF) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_BIND_SIGNALS=0) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=DEBUG) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_TRACE_COMPRESSION=1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_WRITE_BUFFER_SIZE=4096) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${DFTRACER_TEST_LD_LIBRARY_PATH}) + if (DFTRACER_WRITER_TYPE_MOFKA) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${CMAKE_CURRENT_BINARY_DIR}/mofka.flock.json) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) + set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) + endif() endfunction() file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data) -if(DFTRACER_WRITER_TYPE MATCHES ".*FILE.*") - set(file_writer_test_name FileWriterPerformanceTest) - set(perf_output_file ${CMAKE_CURRENT_BINARY_DIR}/${file_writer_test_name}.out) - df_add_test(${file_writer_test_name} $ ${perf_output_file}) - set_common_properties(${file_writer_test_name}) - set_property(TEST ${file_writer_test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=0) -endif() - set(test_name test_cpp_basic_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data) set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload_dbg.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=PRELOAD) - -find_program(BASH_PROGRAM bash) -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 29) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 29) set(test_name test_cpp_basic_app_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data 1) set_common_properties(${test_name}) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 29) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 29) set(test_name test_cpp_basic_app_only_yaml) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data 1) @@ -82,9 +107,7 @@ set(test_name test_cpp_basic_app_aggregate_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data 1) set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE_AGGREGATION=ON) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 14) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 14) set(test_name test_cpp_basic_app_aggregate_selective_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data 1) @@ -92,41 +115,31 @@ set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE_AGGREGATION=ON) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_AGGREGATION_TYPE=SELECTIVE) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_AGGREGATION_FILE=${CMAKE_CURRENT_SOURCE_DIR}/yaml/rules.yaml) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 14) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 14) set(test_name test_cpp_basic_app_disable_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data 1) set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=0) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_not.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 0) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 0) set(test_name test_c_basic_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_c ${CMAKE_CURRENT_BINARY_DIR}/data) set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload_dbg.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=PRELOAD) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 4) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 4) set(test_name test_c_basic_app_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_c ${CMAKE_CURRENT_BINARY_DIR}/data 1) set_common_properties(${test_name}) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 4) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 4) set(test_name test_c_basic_app_aggregate_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_c ${CMAKE_CURRENT_BINARY_DIR}/data 1) set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE_AGGREGATION=ON) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 11) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 11) set(test_name test_c_basic_app_aggregate_selective_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_c ${CMAKE_CURRENT_BINARY_DIR}/data 1) @@ -134,47 +147,37 @@ set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE_AGGREGATION=ON) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_AGGREGATION_TYPE=SELECTIVE) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_AGGREGATION_FILE=${CMAKE_CURRENT_SOURCE_DIR}/yaml/rules.yaml) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 11) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 11) set(test_name test_c_basic_app_disable_only) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_c ${CMAKE_CURRENT_BINARY_DIR}/data 1) set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=0) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_not.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 0) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 0) set(test_name test_cpp_basic_meta) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) +set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload_dbg.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=PRELOAD) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 29) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 29) set(test_name test_cpp_basic_affinity) df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY_DIR}/data) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) +set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload_dbg.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=PRELOAD) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_SET_CORE_AFFINITY=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 29) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 29) set(test_name test_py_disable_only) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/test.py --format=npz --data_dir=${CMAKE_CURRENT_BINARY_DIR}) set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=0) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_not.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* 0) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 0) set(test_name test_py_both) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/test.py --format=npz --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data) @@ -226,9 +229,7 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${C set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=HYBRID) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}*-app.pfw* 74) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 74) # # Normal Run + Epoch as Metadata set(test_name test_py_ai_logging_epoch_as_metadata) @@ -241,9 +242,7 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${C set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=HYBRID) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}*-app.pfw* 74) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 74) # # Disable DFTracer set(test_name test_py_ai_logging_disable_only) @@ -251,9 +250,7 @@ df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/a set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=0) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_not.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}*-app.pfw*) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 0) # # Disable Category @@ -268,9 +265,7 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${C set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=HYBRID) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}*-app.pfw* 7) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 7) # ## DataLoader category set(test_name test_py_ai_logging_disable_cat_dataloader) @@ -283,9 +278,7 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${C set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=HYBRID) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}*-app.pfw* 59) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 59) # ## Device category set(test_name test_py_ai_logging_disable_cat_device) @@ -298,9 +291,7 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${C set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=HYBRID) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}*-app.pfw* 68) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 68) # ## Compute category set(test_name test_py_ai_logging_disable_cat_compute) @@ -313,9 +304,7 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${C set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=HYBRID) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}*-app.pfw* 50) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 50) # ## Checkpoint category set(test_name test_py_ai_logging_disable_cat_ckpt) @@ -328,9 +317,7 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${C set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INIT=HYBRID) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - -df_add_test(check_file_exists_${test_name} ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/check_file.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}*-app.pfw* 71) -set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_name}) +df_check_test(${test_name} 71) # ######################################################################## # ## END OF AI LOGGING TEST diff --git a/test/c/test.c b/test/c/test.c index 3670d524..c9ed74c5 100644 --- a/test/c/test.c +++ b/test/c/test.c @@ -30,7 +30,7 @@ void foo() { DFTRACER_C_FUNCTION_END(); } -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { int init = 0; if (argc > 2) { if (strcmp(argv[2], "1") == 0) { @@ -42,7 +42,7 @@ int main(int argc, char *argv[]) { char filename[1024]; sprintf(filename, "%s/demofile_c.txt", argv[1]); foo(); - FILE *fh = fopen(filename, "w+"); + FILE* fh = fopen(filename, "w+"); fwrite("hello", sizeof("hello"), 1, fh); int child_pid = fork(); // fork a duplicate process int pid = getpid(); @@ -51,7 +51,7 @@ int main(int argc, char *argv[]) { if (child_ppid == pid) { // if the current process is a child of the main process - char *arr[] = {"ls", "-l", NULL}; + char* arr[] = {"ls", "-l", NULL}; execv("/bin/ls", arr); if (init) { DFTRACER_C_FINI(); diff --git a/test/check_mofka_topic.py b/test/check_mofka_topic.py new file mode 100644 index 00000000..b7a060bc --- /dev/null +++ b/test/check_mofka_topic.py @@ -0,0 +1,141 @@ +import sys +import os +import argparse +import traceback +import time +import json +import mochi.mofka.client as mofka + +def main(): + parser = argparse.ArgumentParser(description='Check Mofka topic event count') + parser.add_argument('topic_name', help='Name of the Mofka topic') + parser.add_argument('expected_count', type=int, help='Minimum number of events expected') + args = parser.parse_args() + + group_file = os.getenv("DFTRACER_MOFKA_GROUP_FILE") + if not group_file: + print("Error: DFTRACER_MOFKA_GROUP_FILE not set") + sys.exit(1) + + print(f"Checking topic '{args.topic_name}' for at least {args.expected_count} events...") + print(f"Using group file: {group_file}") + + driver = None + try: + driver = mofka.MofkaDriver(group_file=group_file, use_progress_thread=True) + if not driver.topic_exists(args.topic_name): + if args.expected_count == 0: + print(f"Success: Topic {args.topic_name} does not exist (as expected for disabled test)") + sys.exit(0) + else: + print(f"Error: Topic {args.topic_name} does not exist") + sys.exit(1) + + topic = driver.open_topic(args.topic_name) + consumer = topic.consumer( + name=f"validator_{os.getpid()}", + thread_pool=driver.default_thread_pool, + batch_size=mofka.AdaptiveBatchSize, + data_allocator=mofka.ByteArrayAllocator, + data_selector=mofka.FullDataSelector, + ) + + count = 0 + # Determine strictness. If we expect 0, we verify 0? + # Usually check_file_at_least implies >=. + # But if expected is 0 (disable test), we might want to ensure no events? + # Based on check_file_not.sh usage in CMake for disable tests, we might need a separate logic for 0? + # CMake uses check_file_not.sh for expected=0. + # But df_check_test in CMake passes 0 for disable tests and uses check_file_at_least logic branch? + # Wait, looking at CMake: + # For disable tests (expected=0), it uses 'check_file_not.sh' logic in the ELSE branch? + # No, function df_check_test only calls check_mofka_topic.py. + # If expected_count is 0, we expect 0 events. + # However, check_file_not.sh ensures file does NOT exist or is empty. + # If expected_count > 0, we expect >= count. + + # We will assume: + # If expected_count == 0: Fail if any event found (or maybe strict 0 check). + # If expected_count > 0: Pass as soon as count >= expected. + + # We need a timeout logic because we don't know when the stream ends. + # For a "at least" check, we can return success immediately. + # For a "exactly 0" check, we must wait a bit to be sure? + # Mofka is persistent in memory? If test finished, data should be there. + # But consumer might block if no data. + + start_time = time.time() + timeout = 5.0 # seconds to wait for data + + while True: + try: + # wait(timeout_ms) + # If we expect events, we wait. + # If we expect 0, we try to pull with short timeout? + + # Check for "at least" condition first + if args.expected_count > 0 and count >= args.expected_count: + print(f"Success: Found {count} events (>= {args.expected_count})") + sys.exit(0) + + # If we have waited too long and still haven't met criteria + if time.time() - start_time > timeout: + break + + future = consumer.pull() + event = future.wait(timeout_ms=1000) # 1 sec wait per pull + + if event: + # Mofka library deserializes metadata into a dict automatically + if event.metadata and isinstance(event.metadata, dict): + # Logic parity: Shell script validates it is JSON. + # Here it IS a dict, so it mimics valid JSON. + pass + elif event.metadata: + print(f"Warning: Metadata is not a dict: {type(event.metadata)}") + # If we strictly want to fail non-dict metadata: + # sys.exit(1) + count += 1 + else: + # No event in this pull + pass + + except RuntimeError as e: + # Timeout uses RuntimeError often in these bindings if timed out? + # Or checks future result? + # future.wait throws if timeout? + # documentation says: wait(timeout_ms) -> Event or raises MofkaException/Timeout + # We catch generic exception to be safe or check specific error. + # Assuming simple timeout just continues loop. + pass + except Exception as e: + # Real error + print(f"Error while pulling: {e}") + break + + print(f"Finished polling. Total events found: {count}") + + if args.expected_count == 0: + if count == 0: + print("Success: Found 0 events as expected.") + sys.exit(0) + else: + print(f"Failure: Expected 0 events, found {count}") + sys.exit(1) + else: + if count >= args.expected_count: + print(f"Success: Found {count} events") + sys.exit(0) + else: + print(f"Failure: Expected at least {args.expected_count} events, found {count}") + sys.exit(1) + + except Exception as e: + print(traceback.format_exc()) + sys.exit(1) + finally: + # Cleanup if needed + del driver + +if __name__ == '__main__': + main() diff --git a/test/cpp/test.cpp b/test/cpp/test.cpp index 055ed1ed..9f392a19 100644 --- a/test/cpp/test.cpp +++ b/test/cpp/test.cpp @@ -15,7 +15,6 @@ void foo() { DFTRACER_CPP_FUNCTION(); - DFTRACER_CPP_FUNCTION_UPDATE("key", 0); DFTRACER_CPP_FUNCTION_UPDATE("key", "0"); usleep(1000); @@ -31,7 +30,7 @@ void foo() { } } -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { int init = 0; if (argc > 2) { if (strcmp(argv[2], "1") == 0) { @@ -46,7 +45,7 @@ int main(int argc, char *argv[]) { sprintf(filename_link, "%s/demofile_link.txt", argv[1]); foo(); truncate(filename, 0); - FILE *fh = fopen(filename, "w+"); + FILE* fh = fopen(filename, "w+"); if (fh != nullptr) { fwrite("hello", sizeof("hello"), 1, fh); fclose(fh); diff --git a/test/mofka.config.json b/test/mofka.config.json new file mode 100644 index 00000000..f81c0050 --- /dev/null +++ b/test/mofka.config.json @@ -0,0 +1,61 @@ +{ + "libraries": [ + "libflock-bedrock-module.so", + "libmofka-bedrock-module.so", + "libwarabi-bedrock-module.so", + "libyokan-bedrock-module.so" + ], + "providers": [ + { + "name": "mofka_flock_provider", + "type": "flock", + "provider_id": 1, + "config": { + "bootstrap": "self", + "file": "mofka.flock.json", + "group": { + "type": "static" + } + } + }, + { + "name": "mofka_master_provider", + "provider_id": 2, + "type": "yokan", + "tags": [ + "mofka:master" + ], + "config": { + "database": { + "type": "map" + } + } + }, + { + "name": "mofka_data_provider", + "provider_id": 3, + "type": "warabi", + "tags": [ + "mofka:data" + ], + "config": { + "target": { + "type": "memory" + } + } + }, + { + "name": "mofka_metadata_provider", + "provider_id": 4, + "type": "yokan", + "tags": [ + "mofka:metadata" + ], + "config": { + "database": { + "type": "map" + } + } + } + ] +} \ No newline at end of file diff --git a/test/mofka.flock.json b/test/mofka.flock.json new file mode 100644 index 00000000..260423d5 --- /dev/null +++ b/test/mofka.flock.json @@ -0,0 +1,12 @@ +{ + "members": [ + { + "address": "ofi+tcp://192.168.178.126:36677", + "provider_id": 1 + } + ], + "metadata": { + "__config__": "{}", + "__type__": "static" + } +} \ No newline at end of file diff --git a/test/mofka_server_start.sh b/test/mofka_server_start.sh new file mode 100755 index 00000000..add1dfa8 --- /dev/null +++ b/test/mofka_server_start.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# bedrock tcp -c mofka.config.json -v trace 1> mofka_server.log 2>&1 & + +$1 tcp -c $2 -v trace 1> $3 2>&1 & +sleep 1 diff --git a/test/mofka_server_stop.sh b/test/mofka_server_stop.sh new file mode 100755 index 00000000..2291c755 --- /dev/null +++ b/test/mofka_server_stop.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +pkill -f "bedrock tcp" diff --git a/test/writer/test_file_writer.cpp b/test/writer/test_file_writer.cpp deleted file mode 100644 index 3cdfb100..00000000 --- a/test/writer/test_file_writer.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dftracer/dftracer_config.hpp" -#include "dftracer/core/typedef.h" -#if DFTRACER_WRITER_TYPE_PERFETTO_PROTO_FILE -#include "dftracer/writer/perfetto_proto_file_writer.h" -static dftracer::PerfettoProtoFileWriter writer_instance; -#elif DFTRACER_WRITER_TYPE_PERFETTO_CHROME_FILE -#include "dftracer/writer/perfetto_chrome_file_writer.h" -static dftracer::PerfettoChromeFileWriter writer_instance; -#endif - -int main(int argc, char** argv) { - std::string tmp_output_file = "file_writer.out"; - int num_events_to_log = 10000; - size_t writer_buffer_size = 4 * 1024 * 1024; // 4 MB default - - if (argc > 1) { - tmp_output_file = argv[1]; - } - if (argc > 2) { - try { - num_events_to_log = std::stoi(argv[2]); - } catch (const std::invalid_argument& ia) { - std::cerr << "Invalid argument for number of events: " << argv[2] - << std::endl; - return EXIT_FAILURE; - } catch (const std::out_of_range& oor) { - std::cerr << "Number of events out of range: " << argv[2] << std::endl; - return EXIT_FAILURE; - } - } - if (argc > 3) { - try { - writer_buffer_size = std::stoull(argv[3]); - } catch (const std::invalid_argument& ia) { - std::cerr << "Invalid argument for writer buffer size: " << argv[3] - << std::endl; - return EXIT_FAILURE; - } catch (const std::out_of_range& oor) { - std::cerr << "Writer buffer size out of range: " << argv[3] << std::endl; - return EXIT_FAILURE; - } - } - - writer_instance.set_write_buffer_size(writer_buffer_size); - writer_instance.initialize(const_cast(tmp_output_file.c_str()), false, - const_cast("test_host_hash_perf")); - - const std::string detail_str = "performance_test_event_detail"; - const std::string another_key_str = "another_value_for_metadata_map"; - std::vector event_names; - event_names.reserve(num_events_to_log); - for (int i = 0; i < num_events_to_log; ++i) { - event_names.push_back("event_name_perf_" + std::to_string(i)); - } - - auto start_time = std::chrono::high_resolution_clock::now(); - unsigned long long current_ts = - std::chrono::duration_cast( - start_time.time_since_epoch()) - .count(); - srand(time(0)); - - for (int i = 0; i < num_events_to_log; ++i) { - std::unordered_map m; - m["iteration"] = i; - m["detail"] = detail_str; - m["another_key"] = another_key_str; - int duration = 100 + (rand() % 101); - writer_instance.log(i, event_names[i].c_str(), "perf_category", current_ts, - duration, &m, 12345, 54321); - current_ts += duration + 1; - } - - writer_instance.finalize(true); - - auto end_time = std::chrono::high_resolution_clock::now(); - auto duration_ms = std::chrono::duration_cast( - end_time - start_time) - .count(); - double duration_s = static_cast(duration_ms) / 1000.0; - - std::cout << std::endl; - std::cout << "[ PERFORMANCE ] FileWriter: Logged " << num_events_to_log - << " main events (plus some metadata events) in " << duration_s - << " seconds." << std::endl; - if (duration_s > 0) { - std::cout << "[ PERFORMANCE ] FileWriter: Throughput: " - << static_cast(num_events_to_log) / duration_s - << " main events/sec." << std::endl; - } else { - std::cout << "[ PERFORMANCE ] FileWriter: Duration too short to " - "calculate throughput accurately." - << std::endl; - } - - std::ifstream file(tmp_output_file); - if (!file.good()) { - std::cerr << "Error: Output file was not created: " << tmp_output_file - << std::endl; - return EXIT_FAILURE; - } - file.seekg(0, std::ios::end); - if (file.tellg() <= 0) { - std::cerr << "Error: Output file is empty: " << tmp_output_file - << std::endl; - file.close(); - return EXIT_FAILURE; - } - file.close(); - - return EXIT_SUCCESS; -} \ No newline at end of file From f8959bdd695adf0eea43aaf50a4787a7e635ca46 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 5 Jan 2026 17:38:33 +0300 Subject: [PATCH 20/33] feat: update Mofka writer test launch configurations. --- .vscode/launch.json | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 54be3d9d..c7a3ccb6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -154,7 +154,7 @@ } }, { - "name": "testc", + "name": "testc-stdio", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/build/bin/test_c", @@ -164,15 +164,46 @@ ], "cwd": "${workspaceFolder}/build", "env": { + "DFTRACER_DATA_DIR": "${workspaceFolder}/build/test/data", + "DFTRACER_ENABLE": "1", + "DFTRACER_INC_METADATA": "1", + "DFTRACER_LOG_FILE": "${workspaceFolder}/build/test/test_c_basic_only", "DFTRACER_LOG_LEVEL": "DEBUG", - "DFTRACER_TRACE_COMPRESSION": "1", + "DFTRACER_TRACE_COMPRESSION": "0", + "DFTRACER_WRITER_TYPE": "STDIO", "LD_LIBRARY_PATH": "${workspaceFolder}/build/lib", + "LD_PRELOAD": "${workspaceFolder}/build/lib64/libdftracer_preload_dbg.so", + }, + "initCommands": [ + "settings set target.process.follow-fork-mode child" + ] + }, + { + "name": "testc-mofka", + "type": "lldb", + "request": "launch", + "program": "${workspaceFolder}/build/bin/test_c", + "args": [ + "${workspaceFolder}/build/test/data", + "1" + ], + "cwd": "${workspaceFolder}/build", + "env": { "DFTRACER_DATA_DIR": "${workspaceFolder}/build/test/data", - "DFTRACER_LOG_FILE": "${workspaceFolder}/build/test/test_c_basic_only", "DFTRACER_ENABLE": "1", "DFTRACER_INC_METADATA": "1", + "DFTRACER_LOG_FILE": "${workspaceFolder}/build/test/test_c_basic_only", + "DFTRACER_LOG_LEVEL": "DEBUG", + "DFTRACER_MOFKA_GROUP_FILE": "${workspaceFolder}/build/test/mofka.group.json", + "DFTRACER_MOFKA_TOPIC_NAME": "test_c", + "DFTRACER_TRACE_COMPRESSION": "0", + "DFTRACER_WRITER_TYPE": "MOFKA", + "LD_LIBRARY_PATH": "${workspaceFolder}/build/lib", "LD_PRELOAD": "${workspaceFolder}/build/lib64/libdftracer_preload_dbg.so", - } + }, + "initCommands": [ + "settings set target.process.follow-fork-mode child" + ] }, ] } \ No newline at end of file From 3b57908dd62f03ab43819db26a34d14e98153dd6 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 5 Jan 2026 17:41:06 +0300 Subject: [PATCH 21/33] Fix Mofka group file name in test env --- test/CMakeLists.txt | 5 +++-- test/mofka.config.json | 2 +- test/mofka.flock.json | 12 ------------ test/mofka.group.json | 1 + 4 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 test/mofka.flock.json create mode 100644 test/mofka.group.json diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3d7cf1cd..7d89a02e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,7 @@ set_property(GLOBAL PROPERTY COVERAGE_FILES "") include_directories(${DFTRACER_PROJECT_DIR}/include) +set(MOFKA_GROUP_FILE "${CMAKE_CURRENT_BINARY_DIR}/mofka.group.json") set(MOFKA_SERVER_FIXTURE "MOFKA_SERVER") find_program(BASH_EXE bash) @@ -27,7 +28,7 @@ function(df_check_test test_name expected_count) df_add_test(check_${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_mofka_topic.py ${test_name} ${expected_count}) set_tests_properties(check_${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) - set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${CMAKE_CURRENT_BINARY_DIR}/mofka.flock.json) + set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${MOFKA_GROUP_FILE}) set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) else() if (${expected_count} EQUAL 0) @@ -73,7 +74,7 @@ function(set_common_properties test_name) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_WRITE_BUFFER_SIZE=4096) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${DFTRACER_TEST_LD_LIBRARY_PATH}) if (DFTRACER_WRITER_TYPE_MOFKA) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${CMAKE_CURRENT_BINARY_DIR}/mofka.flock.json) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${MOFKA_GROUP_FILE}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) endif() diff --git a/test/mofka.config.json b/test/mofka.config.json index f81c0050..862605f7 100644 --- a/test/mofka.config.json +++ b/test/mofka.config.json @@ -12,7 +12,7 @@ "provider_id": 1, "config": { "bootstrap": "self", - "file": "mofka.flock.json", + "file": "mofka.group.json", "group": { "type": "static" } diff --git a/test/mofka.flock.json b/test/mofka.flock.json deleted file mode 100644 index 260423d5..00000000 --- a/test/mofka.flock.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "members": [ - { - "address": "ofi+tcp://192.168.178.126:36677", - "provider_id": 1 - } - ], - "metadata": { - "__config__": "{}", - "__type__": "static" - } -} \ No newline at end of file diff --git a/test/mofka.group.json b/test/mofka.group.json new file mode 100644 index 00000000..3fb6eca4 --- /dev/null +++ b/test/mofka.group.json @@ -0,0 +1 @@ +{"members":[{"address":"ofi+tcp://192.168.178.126:41707","provider_id":1}],"metadata":{"__config__":"{}","__type__":"static"}} \ No newline at end of file From f27d4b4d17276ae1d245c7ed7f845908f4a7e4bf Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 5 Jan 2026 22:00:00 +0300 Subject: [PATCH 22/33] Handle reinit in Mofka writer due to fork --- src/dftracer/core/writer/mofka_writer.cpp | 88 ++++++++++++++++------- src/dftracer/core/writer/mofka_writer.h | 1 + 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/dftracer/core/writer/mofka_writer.cpp b/src/dftracer/core/writer/mofka_writer.cpp index 23f657be..60ed968e 100644 --- a/src/dftracer/core/writer/mofka_writer.cpp +++ b/src/dftracer/core/writer/mofka_writer.cpp @@ -32,40 +32,56 @@ void MofkaWriter::initialize(const char* filename) { // transport // prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0); - try { - diaspora::Metadata options; - options.json()["group_file"] = group_file_; - options.json()["margo"] = nlohmann::json::object(); - options.json()["margo"]["use_progress_thread"] = true; + if (driver_) { + DFTRACER_LOG_INFO("MofkaWriter already initialized", ""); + } else { + try { + diaspora::Metadata options; + options.json()["group_file"] = group_file_; + options.json()["margo"] = nlohmann::json::object(); + options.json()["margo"]["use_progress_thread"] = true; - driver_ = std::make_unique( - diaspora::Driver::New("mofka", options)); + driver_ = std::make_unique( + diaspora::Driver::New("mofka", options)); + DFTRACER_LOG_INFO("Mofka driver initialized", ""); - if (!driver_->topicExists(topic_name_)) { - diaspora::Validator validator; - diaspora::Serializer serializer; - diaspora::PartitionSelector selector; - driver_->createTopic(topic_name_, diaspora::Metadata{}, validator, - selector, serializer); - driver_->as().addMemoryPartition(topic_name_, 0); - } + if (driver_->topicExists(topic_name_)) { + DFTRACER_LOG_INFO("Mofka topic exists", ""); + } else { + diaspora::Validator validator; + diaspora::Serializer serializer; + diaspora::PartitionSelector selector; + driver_->createTopic(topic_name_, diaspora::Metadata{}, validator, + selector, serializer); + driver_->as().addMemoryPartition(topic_name_, 0); + DFTRACER_LOG_INFO("Mofka topic created", ""); + } - topic_ = std::make_unique( - driver_->openTopic(topic_name_)); + topic_ = std::make_unique( + driver_->openTopic(topic_name_)); + DFTRACER_LOG_INFO("Mofka topic opened", ""); - diaspora::BatchSize batchSize = diaspora::BatchSize::Adaptive(); - diaspora::ThreadCount threadCount = diaspora::ThreadCount{1}; - diaspora::Ordering ordering = diaspora::Ordering::Strict; - producer_ = std::make_unique( - topic_->producer("dftracer", batchSize, threadCount, ordering)); - } catch (const std::exception& e) { - DFTRACER_LOG_ERROR("Failed to initialize MofkaWriter", e.what()); - throw; + diaspora::BatchSize batchSize = diaspora::BatchSize::Adaptive(); + diaspora::ThreadCount threadCount = diaspora::ThreadCount{1}; + diaspora::Ordering ordering = diaspora::Ordering::Strict; + producer_ = std::make_unique( + topic_->producer("dftracer", batchSize, threadCount, ordering)); + DFTRACER_LOG_INFO("Mofka producer created", ""); + + init_pid_ = getpid(); + DFTRACER_LOG_INFO("MofkaWriter initialized with PID %d", init_pid_); + } catch (const std::exception& e) { + DFTRACER_LOG_ERROR("Failed to initialize MofkaWriter", e.what()); + throw; + } } } size_t MofkaWriter::write(const char* data, size_t len, bool force) { - if (!topic_) return 0; + if (!topic_) { + DFTRACER_LOG_ERROR("Mofka topic not initialized", ""); + return 0; + } try { producer_->push(diaspora::Metadata{data}, diaspora::DataView{}); return len; @@ -76,6 +92,26 @@ size_t MofkaWriter::write(const char* data, size_t len, bool force) { } void MofkaWriter::finalize(int index) { + DFTRACER_LOG_INFO("Mofka finalizing", ""); + if (getpid() != init_pid_) { + DFTRACER_LOG_INFO( + "MofkaWriter::finalize called in child process (Init PID: %d, Current " + "PID: %d). Skipping flush to avoid hang.", + init_pid_, getpid()); + // In a child process, do not flush or destruct normally. + // Just release ownership to avoid destructor calls that might wait on + // futures. + if (producer_) { + producer_.release(); + } + if (topic_) { + topic_.release(); + } + if (driver_) { + driver_.release(); + } + return; + } if (producer_) { producer_->flush().wait(-1); DFTRACER_LOG_INFO("Mofka producer flushed", ""); diff --git a/src/dftracer/core/writer/mofka_writer.h b/src/dftracer/core/writer/mofka_writer.h index 16f42cec..9864452f 100644 --- a/src/dftracer/core/writer/mofka_writer.h +++ b/src/dftracer/core/writer/mofka_writer.h @@ -17,6 +17,7 @@ class MofkaWriter : public WriterInterface { std::unique_ptr driver_; std::unique_ptr producer_; std::unique_ptr topic_; + pid_t init_pid_; public: MofkaWriter(); From 47e073de8b7210cdc10631b7420faa6de30f36d0 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Tue, 6 Jan 2026 00:07:14 +0300 Subject: [PATCH 23/33] Initialize init_pid_ to 0 in MofkaWriter for improved stability --- src/dftracer/core/writer/mofka_writer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dftracer/core/writer/mofka_writer.h b/src/dftracer/core/writer/mofka_writer.h index 9864452f..1c272fcd 100644 --- a/src/dftracer/core/writer/mofka_writer.h +++ b/src/dftracer/core/writer/mofka_writer.h @@ -17,7 +17,7 @@ class MofkaWriter : public WriterInterface { std::unique_ptr driver_; std::unique_ptr producer_; std::unique_ptr topic_; - pid_t init_pid_; + pid_t init_pid_ = 0; public: MofkaWriter(); From ff68974093729db3587cdf37f23b5eb47bd3548e Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Sun, 15 Feb 2026 18:35:50 -0800 Subject: [PATCH 24/33] fix: correct log message format for aggregation_file in ConfigurationManager --- src/dftracer/core/utils/configuration_manager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dftracer/core/utils/configuration_manager.cpp b/src/dftracer/core/utils/configuration_manager.cpp index a383411c..4b7330e7 100644 --- a/src/dftracer/core/utils/configuration_manager.cpp +++ b/src/dftracer/core/utils/configuration_manager.cpp @@ -229,8 +229,8 @@ dftracer::ConfigurationManager::ConfigurationManager() this->aggregation_enable); DFTRACER_LOG_DEBUG("YAML ConfigurationManager.aggregation_type %d", this->aggregation_type); - DFTRACER_LOG_DEBUG("YAML ConfigurationManager.aggregation_enable %d", - this->aggregation_file); + DFTRACER_LOG_DEBUG("YAML ConfigurationManager.aggregation_file %s", + this->aggregation_file.c_str()); } if (config[DFT_YAML_INTERNAL]) { if (config[DFT_YAML_INTERNAL][DFT_YAML_INTERNAL_SIGNALS]) { @@ -442,4 +442,4 @@ void dftracer::ConfigurationManager::derive_configurations() { } DFTRACER_LOG_DEBUG("ConfigurationManager::derive_configurations finished", ""); -} \ No newline at end of file +} From f4a2e9a4442af5d0b99dcaf29172e5bcd7d459c0 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Sun, 15 Feb 2026 18:36:44 -0800 Subject: [PATCH 25/33] Improve CMake build configuration to work with Spack env --- setup.py | 78 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/setup.py b/setup.py index fd97be00..ea07f9b1 100644 --- a/setup.py +++ b/setup.py @@ -20,6 +20,7 @@ def myversion_func(version: ScmVersion) -> str: from setuptools_scm.version import only_version + if version.distance > 0: return version.format_next_version(only_version, fmt="{tag}.dev{distance}") else: @@ -85,8 +86,7 @@ def build_extension(self, ext: CMakeExtension) -> None: cmake_args += [f"-DCMAKE_BUILD_TYPE={build_type}"] enable_ftracing = os.environ.get("DFTRACER_ENABLE_FTRACING", "OFF") cmake_args += [f"-DDFTRACER_ENABLE_FTRACING={enable_ftracing}"] - enable_hip_tracing = os.environ.get( - "DFTRACER_ENABLE_HIP_TRACING", "OFF") + enable_hip_tracing = os.environ.get("DFTRACER_ENABLE_HIP_TRACING", "OFF") cmake_args += [f"-DDFTRACER_ENABLE_HIP_TRACING={enable_hip_tracing}"] enable_mpi = os.environ.get("DFTRACER_ENABLE_MPI", "OFF") cmake_args += [f"-DDFTRACER_ENABLE_MPI={enable_mpi}"] @@ -95,8 +95,19 @@ def build_extension(self, ext: CMakeExtension) -> None: cmake_args += [f"-DDFTRACER_PYTHON_EXE={sys.executable}"] cmake_args += [f"-DDFTRACER_PYTHON_SITE={python_site}"] cmake_args += [f"-DCMAKE_INSTALL_PREFIX={install_prefix}"] + # Preserve environment-provided prefix paths (e.g. Spack view paths) + # while still preferring the local install prefix. + env_prefix_path = os.environ.get("CMAKE_PREFIX_PATH", "") + prefix_entries = [install_prefix] + if env_prefix_path: + normalized_env_prefix_path = env_prefix_path.replace(";", os.pathsep) + prefix_entries.extend( + [p for p in normalized_env_prefix_path.split(os.pathsep) if p] + ) + cmake_prefix_path = ";".join(dict.fromkeys(prefix_entries)) + cmake_args += [ - f"-DCMAKE_PREFIX_PATH={install_prefix}", + f"-DCMAKE_PREFIX_PATH={cmake_prefix_path}", f"-Dpybind11_DIR={py_cmake_dir}", ] cmake_args += ["-DPYBIND11_FINDPYTHON=ON"] @@ -108,16 +119,12 @@ def build_extension(self, ext: CMakeExtension) -> None: enable_dlio_tests = os.environ.get( "DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS", "OFF" ) - cmake_args += [ - f"-DDFTRACER_ENABLE_DLIO_BENCHMARK_TESTS={enable_dlio_tests}"] - enable_dlio_tests = os.environ.get( - "DFTRACER_ENABLE_PAPER_TESTS", "OFF") + cmake_args += [f"-DDFTRACER_ENABLE_DLIO_BENCHMARK_TESTS={enable_dlio_tests}"] + enable_dlio_tests = os.environ.get("DFTRACER_ENABLE_PAPER_TESTS", "OFF") cmake_args += [f"-DDFTRACER_ENABLE_PAPER_TESTS={enable_dlio_tests}"] - test_ld_library_path = os.environ.get( - "DFTRACER_TEST_LD_LIBRARY_PATH", "") - cmake_args += [ - f"-DDFTRACER_TEST_LD_LIBRARY_PATH={test_ld_library_path}"] + test_ld_library_path = os.environ.get("DFTRACER_TEST_LD_LIBRARY_PATH", "") + cmake_args += [f"-DDFTRACER_TEST_LD_LIBRARY_PATH={test_ld_library_path}"] writer_type = os.environ.get("DFTRACER_WRITER_TYPE", "STDIO") cmake_args += [f"-DDFTRACER_WRITER_TYPE={writer_type}"] @@ -139,8 +146,7 @@ def build_extension(self, ext: CMakeExtension) -> None: # (needed e.g. to build for ARM OSx on conda-forge) # In this example, we pass in the version to C++. You might not need to. - cmake_args += [ - f"-DEXAMPLE_VERSION_INFO={self.distribution.get_version()}"] + cmake_args += [f"-DEXAMPLE_VERSION_INFO={self.distribution.get_version()}"] # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level # across all generators. @@ -151,6 +157,24 @@ def build_extension(self, ext: CMakeExtension) -> None: build_temp.mkdir(parents=True) print("cmake", ext.sourcedir, cmake_args) + cmake_env = os.environ.copy() + ldflags = [item for item in cmake_env.get("LDFLAGS", "").split() if item] + extra_ldflags = [] + for prefix in [ + item + for item in cmake_prefix_path.replace(";", os.pathsep).split(os.pathsep) + if item + ]: + libdir = Path(prefix) / "lib" + libflag = f"-L{libdir}" + if ( + libdir.is_dir() + and libflag not in ldflags + and libflag not in extra_ldflags + ): + extra_ldflags.append(libflag) + cmake_env["LDFLAGS"] = " ".join(ldflags + extra_ldflags) + if ( "DFTRACER_BUILD_DEPENDENCIES" not in os.environ or os.environ["DFTRACER_BUILD_DEPENDENCIES"] == "1" @@ -163,9 +187,13 @@ def build_extension(self, ext: CMakeExtension) -> None: ["cmake", ext.sourcedir, *install_cmake_args], cwd=build_temp, check=True, + env=cmake_env, ) subprocess.run( - ["cmake", "--build", ".", *build_args], cwd=build_temp, check=True + ["cmake", "--build", ".", *build_args], + cwd=build_temp, + check=True, + env=cmake_env, ) cmake_args += ["-DDFTRACER_INSTALL_DEPENDENCIES=OFF"] # link correct depedencies @@ -176,15 +204,24 @@ def build_extension(self, ext: CMakeExtension) -> None: if "DFTRACER_CMAKE_ARGS" in os.environ: cmake_args += [ - item for item in os.environ["DFTRACER_CMAKE_ARGS"].split(";") if item] + item for item in os.environ["DFTRACER_CMAKE_ARGS"].split(";") if item + ] subprocess.run( - ["cmake", ext.sourcedir, *cmake_args], cwd=build_temp, check=True + ["cmake", ext.sourcedir, *cmake_args], + cwd=build_temp, + check=True, + env=cmake_env, + ) + subprocess.run( + ["cmake", "--build", ".", *build_args], + cwd=build_temp, + check=True, + env=cmake_env, ) subprocess.run( - ["cmake", "--build", ".", *build_args], cwd=build_temp, check=True + ["cmake", "--install", "."], cwd=build_temp, check=True, env=cmake_env ) - subprocess.run(["cmake", "--install", "."], cwd=build_temp, check=True) # The information here can also be placed in setup.cfg - better separation of @@ -192,9 +229,8 @@ def build_extension(self, ext: CMakeExtension) -> None: setup( name="dftracer", use_scm_version={"version_scheme": myversion_func}, - packages=find_packages(where='python') + - find_packages(where='dfanalyzer_old'), - package_dir={'': 'python', 'dfanalyzer_old': 'dfanalyzer_old'}, + packages=find_packages(where="python") + find_packages(where="dfanalyzer_old"), + package_dir={"": "python", "dfanalyzer_old": "dfanalyzer_old"}, ext_modules=[ CMakeExtension("dftracer.dftracer"), CMakeExtension("dftracer.dftracer_dbg"), From 47d23521c76949cb5253fb8e51556dabb869b053 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Thu, 19 Feb 2026 08:25:56 -0800 Subject: [PATCH 26/33] fix: add explicit linking for std::filesystem on GNU toolchains --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcf76ea0..b5cc0b8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,6 +223,12 @@ else() set(DEPENDENCY_LIB ${CMAKE_EXE_LINKER_FLAGS} $ENV{LDFLAGS} -lpthread) set(DEPENDENCY_LIBRARY_DIRS "") +# On some GNU toolchains, std::filesystem symbols require explicit +# linking with libstdc++fs. +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND DFTRACER_HAS_STD_FILESYSTEM) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} stdc++fs) +endif () + find_package(cpp-logger 1.0.0 REQUIRED) if (${cpp-logger_FOUND}) include_directories(${CPP_LOGGER_INCLUDE_DIRS}) From ca92a6f5c2f6514effac7bd960a0e9d2fc6e072b Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Thu, 19 Feb 2026 08:26:14 -0800 Subject: [PATCH 27/33] fix: ensure directory exists before creating symlinks for Python bindings --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b5cc0b8b..69ff9143 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -527,7 +527,7 @@ if (DFTRACER_BUILD_PYTHON_BINDINGS) LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) - file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;mkdir -p ${MAIN_PYTHON_SITE_PACKAGES}/dftracer;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") install(CODE "execute_process( COMMAND bash -c \"set -e chmod +x ${CMAKE_BINARY_DIR}/symlink.sh @@ -539,7 +539,7 @@ if (DFTRACER_BUILD_PYTHON_BINDINGS) LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) - file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink_dbg.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink_dbg.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;mkdir -p ${MAIN_PYTHON_SITE_PACKAGES}/dftracer;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") install(CODE "execute_process( COMMAND bash -c \"set -e chmod +x ${CMAKE_BINARY_DIR}/symlink_dbg.sh From 3827e7d37a5cd490b38b286c30ddf3df27cf5ad6 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Fri, 20 Feb 2026 11:20:25 -0800 Subject: [PATCH 28/33] test: improve mofka server management and test configuration - Add automatic fabric protocol detection (CXI/TCP) for mofka server startup - Implement PID-based process tracking for reliable server lifecycle management - Update CMake to use Spack environment paths for LD_LIBRARY_PATH and PYTHONPATH - Consolidate environment variable settings in set_common_properties function --- test/CMakeLists.txt | 51 +++++++-------------- test/check_mofka_topic.py | 92 ++++++++++++++++++++------------------ test/mofka_server_start.sh | 72 +++++++++++++++++++++++++++-- test/mofka_server_stop.sh | 41 ++++++++++++++++- test/py/requirements.txt | 5 ++- 5 files changed, 178 insertions(+), 83 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7d89a02e..e302dc2f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,7 +5,8 @@ set(MOFKA_GROUP_FILE "${CMAKE_CURRENT_BINARY_DIR}/mofka.group.json") set(MOFKA_SERVER_FIXTURE "MOFKA_SERVER") find_program(BASH_EXE bash) -if (DFTRACER_WRITER_TYPE_MOFKA) + +if(DFTRACER_WRITER_TYPE_MOFKA) find_program(BEDROCK_EXE bedrock REQUIRED) add_test(mofka_server_start ${CMAKE_CURRENT_SOURCE_DIR}/mofka_server_start.sh ${BEDROCK_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/mofka.config.json ${CMAKE_CURRENT_BINARY_DIR}/mofka_server.log) add_test(mofka_server_stop ${CMAKE_CURRENT_SOURCE_DIR}/mofka_server_stop.sh) @@ -18,31 +19,33 @@ function(df_add_test) set_tests_properties(${ARGV0} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${ARGV0}.profraw") get_property(OLD_CF GLOBAL PROPERTY COVERAGE_FILES) + # Use test_fixture_name for constructing the profraw path set(NEW_CF ${OLD_CF} ${CMAKE_CURRENT_BINARY_DIR}/${ARGV0}.profraw) set_property(GLOBAL PROPERTY COVERAGE_FILES ${NEW_CF}) endfunction() function(df_check_test test_name expected_count) - if (DFTRACER_WRITER_TYPE_MOFKA) - df_add_test(check_${test_name} + if(DFTRACER_WRITER_TYPE_MOFKA) + df_add_test(check_${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_mofka_topic.py ${test_name} ${expected_count}) set_tests_properties(check_${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${MOFKA_GROUP_FILE}) set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) else() - if (${expected_count} EQUAL 0) - df_add_test(check_${test_name} - ${BASH_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_not.sh + if(${expected_count} EQUAL 0) + df_add_test(check_${test_name} + ${BASH_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_not.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* ) else() - df_add_test(check_${test_name} - ${BASH_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh + df_add_test(check_${test_name} + ${BASH_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* ${expected_count} ) endif() endif() + set_tests_properties(check_${test_name} PROPERTIES DEPENDS ${test_name}) endfunction() @@ -63,7 +66,7 @@ add_dependencies(test_c ${PROJECT_NAME}_core_dbg) add_dependencies(test_c ${PROJECT_NAME}_preload_dbg) function(set_common_properties test_name) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_BIND_SIGNALS=0) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_BIND_SIGNALS=0) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_CURRENT_BINARY_DIR}/data) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE_AGGREGATION=OFF) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=1) @@ -72,11 +75,13 @@ function(set_common_properties test_name) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=DEBUG) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_TRACE_COMPRESSION=1) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_WRITE_BUFFER_SIZE=4096) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${DFTRACER_TEST_LD_LIBRARY_PATH}) - if (DFTRACER_WRITER_TYPE_MOFKA) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:${CMAKE_SOURCE_DIR}/.spack-env/view/lib:${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${DFTRACER_TEST_LD_LIBRARY_PATH}) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/.spack-env/bin/python) + + if(DFTRACER_WRITER_TYPE_MOFKA) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${MOFKA_GROUP_FILE}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) - set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) + set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) endif() endfunction() @@ -176,15 +181,12 @@ df_check_test(${test_name} 29) set(test_name test_py_disable_only) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/test.py --format=npz --data_dir=${CMAKE_CURRENT_BINARY_DIR}) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=0) df_check_test(${test_name} 0) set(test_name test_py_both) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/test.py --format=npz --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -193,8 +195,6 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA set(test_name test_py_aggregation_both) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/test.py --format=npz --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -205,8 +205,6 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_AGGREGATION_ set(test_name test_py_aggregation_selective_both) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/test.py --format=npz --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -223,8 +221,6 @@ set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_AGGREGATION_ set(test_name test_py_ai_logging_normal) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/ai_logging.py --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data --niter 3 --num_files 2) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -236,8 +232,6 @@ df_check_test(${test_name} 74) set(test_name test_py_ai_logging_epoch_as_metadata) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/ai_logging.py --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data --niter 3 --num_files 2 --epoch-as-metadata) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -249,7 +243,6 @@ df_check_test(${test_name} 74) set(test_name test_py_ai_logging_disable_only) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/ai_logging.py --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data --niter 3 --num_files 2) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=0) df_check_test(${test_name} 0) @@ -259,8 +252,6 @@ df_check_test(${test_name} 0) set(test_name test_py_ai_logging_disable_cat_all) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/ai_logging.py --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data --niter 3 --num_files 2 --disable-ai-cat all) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -272,8 +263,6 @@ df_check_test(${test_name} 7) set(test_name test_py_ai_logging_disable_cat_dataloader) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/ai_logging.py --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data --niter 3 --num_files 2 --disable-ai-cat dataloader) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -285,8 +274,6 @@ df_check_test(${test_name} 59) set(test_name test_py_ai_logging_disable_cat_device) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/ai_logging.py --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data --niter 3 --num_files 2 --disable-ai-cat device) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -298,8 +285,6 @@ df_check_test(${test_name} 68) set(test_name test_py_ai_logging_disable_cat_compute) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/ai_logging.py --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data --niter 3 --num_files 2 --disable-ai-cat compute) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) @@ -311,8 +296,6 @@ df_check_test(${test_name} 50) set(test_name test_py_ai_logging_disable_cat_ckpt) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/ai_logging.py --data_dir=${CMAKE_CURRENT_BINARY_DIR}/data --niter 3 --num_files 2 --disable-ai-cat ckpt) set_common_properties(${test_name}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}/venv/${DFTRACER_LIBDIR}) -set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}:${CMAKE_SOURCE_DIR}/dependency/.spack-env/view/lib64:${DFTRACER_TEST_LD_LIBRARY_PATH}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT LD_PRELOAD=${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/libdftracer_preload.so) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_DATA_DIR=${CMAKE_BINARY_DIR}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/${test_name}) diff --git a/test/check_mofka_topic.py b/test/check_mofka_topic.py index b7a060bc..8e791b8e 100644 --- a/test/check_mofka_topic.py +++ b/test/check_mofka_topic.py @@ -6,10 +6,13 @@ import json import mochi.mofka.client as mofka + def main(): - parser = argparse.ArgumentParser(description='Check Mofka topic event count') - parser.add_argument('topic_name', help='Name of the Mofka topic') - parser.add_argument('expected_count', type=int, help='Minimum number of events expected') + parser = argparse.ArgumentParser(description="Check Mofka topic event count") + parser.add_argument("topic_name", help="Name of the Mofka topic") + parser.add_argument( + "expected_count", type=int, help="Minimum number of events expected" + ) args = parser.parse_args() group_file = os.getenv("DFTRACER_MOFKA_GROUP_FILE") @@ -17,89 +20,89 @@ def main(): print("Error: DFTRACER_MOFKA_GROUP_FILE not set") sys.exit(1) - print(f"Checking topic '{args.topic_name}' for at least {args.expected_count} events...") + print( + f"Checking topic '{args.topic_name}' for at least {args.expected_count} events..." + ) print(f"Using group file: {group_file}") driver = None try: driver = mofka.MofkaDriver(group_file=group_file, use_progress_thread=True) if not driver.topic_exists(args.topic_name): - if args.expected_count == 0: - print(f"Success: Topic {args.topic_name} does not exist (as expected for disabled test)") - sys.exit(0) - else: - print(f"Error: Topic {args.topic_name} does not exist") - sys.exit(1) - + if args.expected_count == 0: + print( + f"Success: Topic {args.topic_name} does not exist (as expected for disabled test)" + ) + sys.exit(0) + else: + print(f"Error: Topic {args.topic_name} does not exist") + sys.exit(1) + topic = driver.open_topic(args.topic_name) - consumer = topic.consumer( - name=f"validator_{os.getpid()}", - thread_pool=driver.default_thread_pool, - batch_size=mofka.AdaptiveBatchSize, - data_allocator=mofka.ByteArrayAllocator, - data_selector=mofka.FullDataSelector, - ) - + consumer = topic.consumer(name=f"validator_{os.getpid()}") + count = 0 - # Determine strictness. If we expect 0, we verify 0? - # Usually check_file_at_least implies >=. - # But if expected is 0 (disable test), we might want to ensure no events? + # Determine strictness. If we expect 0, we verify 0? + # Usually check_file_at_least implies >=. + # But if expected is 0 (disable test), we might want to ensure no events? # Based on check_file_not.sh usage in CMake for disable tests, we might need a separate logic for 0? # CMake uses check_file_not.sh for expected=0. # But df_check_test in CMake passes 0 for disable tests and uses check_file_at_least logic branch? # Wait, looking at CMake: # For disable tests (expected=0), it uses 'check_file_not.sh' logic in the ELSE branch? # No, function df_check_test only calls check_mofka_topic.py. - # If expected_count is 0, we expect 0 events. + # If expected_count is 0, we expect 0 events. # However, check_file_not.sh ensures file does NOT exist or is empty. # If expected_count > 0, we expect >= count. - + # We will assume: # If expected_count == 0: Fail if any event found (or maybe strict 0 check). # If expected_count > 0: Pass as soon as count >= expected. # We need a timeout logic because we don't know when the stream ends. # For a "at least" check, we can return success immediately. - # For a "exactly 0" check, we must wait a bit to be sure? + # For a "exactly 0" check, we must wait a bit to be sure? # Mofka is persistent in memory? If test finished, data should be there. # But consumer might block if no data. - + start_time = time.time() - timeout = 5.0 # seconds to wait for data - + timeout = 5.0 # seconds to wait for data + while True: try: # wait(timeout_ms) # If we expect events, we wait. # If we expect 0, we try to pull with short timeout? - + # Check for "at least" condition first if args.expected_count > 0 and count >= args.expected_count: print(f"Success: Found {count} events (>= {args.expected_count})") sys.exit(0) - + # If we have waited too long and still haven't met criteria if time.time() - start_time > timeout: - break + break future = consumer.pull() - event = future.wait(timeout_ms=1000) # 1 sec wait per pull - + event = future.wait(timeout_ms=1000) # 1 sec wait per pull + if event: # Mofka library deserializes metadata into a dict automatically if event.metadata and isinstance(event.metadata, dict): - # Logic parity: Shell script validates it is JSON. - # Here it IS a dict, so it mimics valid JSON. - pass + # Logic parity: Shell script validates it is JSON. + # Here it IS a dict, so it mimics valid JSON. + pass elif event.metadata: - print(f"Warning: Metadata is not a dict: {type(event.metadata)}") - # If we strictly want to fail non-dict metadata: - # sys.exit(1) + print( + f"Warning: Metadata is not a dict: {type(event.metadata)}" + ) + # If we strictly want to fail non-dict metadata: + # sys.exit(1) count += 1 else: # No event in this pull pass - + except RuntimeError as e: # Timeout uses RuntimeError often in these bindings if timed out? # Or checks future result? @@ -114,7 +117,7 @@ def main(): break print(f"Finished polling. Total events found: {count}") - + if args.expected_count == 0: if count == 0: print("Success: Found 0 events as expected.") @@ -127,7 +130,9 @@ def main(): print(f"Success: Found {count} events") sys.exit(0) else: - print(f"Failure: Expected at least {args.expected_count} events, found {count}") + print( + f"Failure: Expected at least {args.expected_count} events, found {count}" + ) sys.exit(1) except Exception as e: @@ -137,5 +142,6 @@ def main(): # Cleanup if needed del driver -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/test/mofka_server_start.sh b/test/mofka_server_start.sh index add1dfa8..858d7e6b 100755 --- a/test/mofka_server_start.sh +++ b/test/mofka_server_start.sh @@ -1,6 +1,72 @@ #!/bin/bash -# bedrock tcp -c mofka.config.json -v trace 1> mofka_server.log 2>&1 & +# Detect the best available fabric protocol for bedrock. +# Checks for CXI fabric availability (used on Cray EX systems with Slingshot). +# Returns 'ofi+cxi' if CXI devices are found, otherwise falls back to 'tcp'. +# +# Environment variable that can override detection: +# - DFTRACER_MOFKA_FABRIC_PROTOCOL: Force a specific protocol (e.g., 'ofi+cxi', 'tcp') -$1 tcp -c $2 -v trace 1> $3 2>&1 & -sleep 1 +detect_fabric_protocol() { + # Allow environment variable override + if [ -n "$DFTRACER_MOFKA_FABRIC_PROTOCOL" ]; then + echo "$DFTRACER_MOFKA_FABRIC_PROTOCOL" + return 0 + fi + + # Check for CXI devices (Cray EX / Slingshot interconnect) + # CXI devices typically appear as /dev/cxi* or /dev/hfi* + local cxi_devices + cxi_devices=$(ls /dev/cxi* /dev/hfi* 2>/dev/null | head -1) + if [ -n "$cxi_devices" ]; then + echo "ofi+cxi" + return 0 + fi + + # Check for libfabric CXI provider availability + if command -v fi_info &>/dev/null; then + if fi_info -p cxi &>/dev/null; then + echo "ofi+cxi" + return 0 + fi + fi + + # Fall back to TCP for local development or systems without CXI + echo "tcp" +} + +# PID file for tracking the server process +PID_FILE="${4:-mofka_server.pid}" + +# Detect fabric protocol +FABRIC_PROTOCOL=$(detect_fabric_protocol) + +echo "Using fabric protocol: $FABRIC_PROTOCOL" + +# Start the server with detected or overridden protocol +$1 "$FABRIC_PROTOCOL" -c $2 -v trace 1> $3 2>&1 & +SERVER_PID=$! + +# Save PID to file for later termination +echo "$SERVER_PID" > "$PID_FILE" + +echo "Server started with PID: $SERVER_PID (saved to $PID_FILE)" + +# Wait for the group file to be created before tests proceed. +GROUP_FILE="mofka.group.json" +for _ in $(seq 1 30); do + if [ -s "$GROUP_FILE" ]; then + sleep 3 + exit 0 + fi + # Check if process is still running + if ! kill -0 "$SERVER_PID" 2>/dev/null; then + echo "Server process (PID: $SERVER_PID) died unexpectedly" >&2 + rm -f "$PID_FILE" + exit 1 + fi + sleep 1 +done + +echo "Timed out waiting for $GROUP_FILE" >&2 +exit 1 diff --git a/test/mofka_server_stop.sh b/test/mofka_server_stop.sh index 2291c755..273b6c1a 100755 --- a/test/mofka_server_stop.sh +++ b/test/mofka_server_stop.sh @@ -1,3 +1,42 @@ #!/bin/bash -pkill -f "bedrock tcp" +# Stop the mofka server using the PID file created during startup. +# This ensures safe termination of the correct process. + +# PID file location (should match what was used in mofka_server_start.sh) +PID_FILE="${1:-mofka_server.pid}" + +if [ -f "$PID_FILE" ]; then + SERVER_PID=$(cat "$PID_FILE") + + if kill -0 "$SERVER_PID" 2>/dev/null; then + echo "Stopping server with PID: $SERVER_PID" + kill "$SERVER_PID" + + # Wait for process to terminate + for _ in $(seq 1 10); do + if ! kill -0 "$SERVER_PID" 2>/dev/null; then + echo "Server stopped successfully" + rm -f "$PID_FILE" + exit 0 + fi + sleep 1 + done + + # Force kill if still running + if kill -0 "$SERVER_PID" 2>/dev/null; then + echo "Server did not stop gracefully, force killing..." + kill -9 "$SERVER_PID" 2>/dev/null + rm -f "$PID_FILE" + fi + else + echo "Server process (PID: $SERVER_PID) is not running" + rm -f "$PID_FILE" + fi +else + echo "PID file not found: $PID_FILE" + echo "Falling back to pkill for 'bedrock'..." + pkill -f "bedrock" +fi + +exit 0 diff --git a/test/py/requirements.txt b/test/py/requirements.txt index f409f614..8e9a3fd5 100644 --- a/test/py/requirements.txt +++ b/test/py/requirements.txt @@ -1,5 +1,6 @@ -numpy==1.26.0 -Pillow==10.0.1 +numpy<2 h5py opencv-python==4.8.1.78 +Pillow==10.0.1 +pydftracer torch==2.5.1 \ No newline at end of file From 8dbfad08f864530e2245267c0016b381f468b504 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Sat, 21 Feb 2026 09:54:15 -0800 Subject: [PATCH 29/33] feat(writer): add ZeroMQ writer for streaming trace data Key changes: - Add ZMQWriter class with non-blocking PUSH socket implementation - Handle fork() safely with automatic socket reconnection in child processes - Add CMake configuration for ZMQ dependencies (libzmq, cppzmq) - Add test infrastructure with ZMQ sink process for integration testing --- CMakeLists.txt | 1256 +++++++++-------- cmake/configure_files/dftracer_config.hpp.in | 1 + .../dftracer_config_dbg.hpp.in | 1 + pyproject.toml | 67 +- src/dftracer/core/buffer/buffer.cpp | 7 +- src/dftracer/core/common/enumeration.h | 3 + .../core/utils/configuration_manager.cpp | 8 + src/dftracer/core/writer/zmq_writer.cpp | 181 +++ src/dftracer/core/writer/zmq_writer.h | 40 + test/CMakeLists.txt | 20 + test/check_zmq_sink.py | 139 ++ test/zmq_sink.py | 177 +++ test/zmq_sink_start.sh | 55 + test/zmq_sink_stop.sh | 17 + 14 files changed, 1349 insertions(+), 623 deletions(-) create mode 100644 src/dftracer/core/writer/zmq_writer.cpp create mode 100644 src/dftracer/core/writer/zmq_writer.h create mode 100755 test/check_zmq_sink.py create mode 100755 test/zmq_sink.py create mode 100755 test/zmq_sink_start.sh create mode 100755 test/zmq_sink_stop.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 69ff9143..9d6c5a6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.5...3.18) -#------------------------------------------------------------------------------ -# Version information -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ +# Version information +# ------------------------------------------------------------------------------ set(DFTRACER_VERSION_MAJOR "4") set(DFTRACER_VERSION_MINOR "0") set(DFTRACER_VERSION_PATCH "0") @@ -22,748 +22,830 @@ project(dftracer LANGUAGES C CXX) string(TOUPPER "${PROJECT_NAME}" UPPER_PROJECT_NAME) string(TOLOWER "${PROJECT_NAME}" LOWER_PROJECT_NAME) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-empty-body -Wno-format-extra-args") -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ # Internal Includes for header and libraries -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Get installation directories -- these get used in various places; # best to just make them available -option (DFTRACER_LIBDIR_AS_LIB OFF) -if (NOT DFTRACER_LIBDIR_AS_LIB) +option(DFTRACER_LIBDIR_AS_LIB OFF) + +if(NOT DFTRACER_LIBDIR_AS_LIB) include(GNUInstallDirs) -endif () +endif() + # -if (CMAKE_INSTALL_LIBDIR) - message(STATUS "CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}") - set(DFTRACER_LIBDIR ${CMAKE_INSTALL_LIBDIR}) - set(DFTRACER_INSTALL_INCLUDE_DIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) - set(DFTRACER_INSTALL_DOCDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}) - set(DFTRACER_INSTALL_SYSCONFDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/modulefiles) - set(DFTRACER_INSTALL_BINFDIR - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}) -else () - set(DFTRACER_LIBDIR "lib") - set(DFTRACER_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") - set(DFTRACER_INSTALL_DOCDIR "${CMAKE_INSTALL_PREFIX}/doc") - set(DFTRACER_INSTALL_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc/modulefiles") - set(DFTRACER_INSTALL_BINARYDIR "${CMAKE_INSTALL_PREFIX}/bin") - message(STATUS "DFTRACER_LIBDIR set to ${DFTRACER_LIBDIR}") -endif () - -#------------------------------------------------------------------------------ +if(CMAKE_INSTALL_LIBDIR) + message(STATUS "CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}") + set(DFTRACER_LIBDIR ${CMAKE_INSTALL_LIBDIR}) + set(DFTRACER_INSTALL_INCLUDE_DIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) + set(DFTRACER_INSTALL_DOCDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DOCDIR}) + set(DFTRACER_INSTALL_SYSCONFDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/modulefiles) + set(DFTRACER_INSTALL_BINFDIR + ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}) +else() + set(DFTRACER_LIBDIR "lib") + set(DFTRACER_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include") + set(DFTRACER_INSTALL_DOCDIR "${CMAKE_INSTALL_PREFIX}/doc") + set(DFTRACER_INSTALL_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc/modulefiles") + set(DFTRACER_INSTALL_BINARYDIR "${CMAKE_INSTALL_PREFIX}/bin") + message(STATUS "DFTRACER_LIBDIR set to ${DFTRACER_LIBDIR}") +endif() + +# ------------------------------------------------------------------------------ # Internal Paths for cmake libraries and Setup install and output Directories -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # This sets where to look for dependent libraries set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_BINARY_DIR} ${CMAKE_INSTALL_PREFIX}) + # This sets where to look for dependent library's cmake files list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}/cmake) list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}/share/cmake) -#------------------------------------------------------------------------------ -if (NOT DFTRACER_EXTERNALLY_CONFIGURED) +# ------------------------------------------------------------------------------ +if(NOT DFTRACER_EXTERNALLY_CONFIGURED) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Single Directory for all Executables.") set(CMAKE_INCLUDE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/include CACHE PATH "Store the headers.") set(EXECUTABLE_OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all Libraries") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR} CACHE PATH "Single Directory for all static libraries.") -endif () +endif() include_directories(${CMAKE_BINARY_DIR}/include) link_directories(${CMAKE_BINARY_DIR}/${DFTRACER_LIBDIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Targets built within this project are exported at Install time for use # by other projects. -#----------------------------------------------------------------------------- -if (NOT DFTRACER_EXPORTED_TARGETS) +# ----------------------------------------------------------------------------- +if(NOT DFTRACER_EXPORTED_TARGETS) set(DFTRACER_EXPORTED_TARGETS "dftracer-targets") -endif () +endif() include(dftracer-utils) -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ # Build options -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # option(ENABLE_DFTRACER_DEBUG "Include debugging prints and logging" OFF) # This is not needed as we have CMAKE_BUILD_TYPE # This is verbose, maybe an alternate might help simplify -#option(BUILD_URPC "Build DFTRACER's URPC code" OFF) -#option(ENABLE_PERFFLOW "Build with PerfFlow Aspect support" OFF) -#option(ENABLE_UCX_DTL "Build DFTRACER's UCX data transport layer" OFF) +# option(BUILD_URPC "Build DFTRACER's URPC code" OFF) +# option(ENABLE_PERFFLOW "Build with PerfFlow Aspect support" OFF) +# option(ENABLE_UCX_DTL "Build DFTRACER's UCX data transport layer" OFF) # This option is off by default because non-developers should not use # this option under normal circumstances. option(DFTRACER_WARNINGS_AS_ERRORS "Build with warnings promoted to errors." OFF) mark_as_advanced(DFTRACER_WARNINGS_AS_ERRORS) -option (DFTRACER_USE_CLANG_LIBCXX OFF) -if (DFTRACER_USE_CLANG_LIBCXX) - set (GCC_TOOLCHAIN "") -endif (DFTRACER_USE_CLANG_LIBCXX) +option(DFTRACER_USE_CLANG_LIBCXX OFF) + +if(DFTRACER_USE_CLANG_LIBCXX) + set(GCC_TOOLCHAIN "") +endif(DFTRACER_USE_CLANG_LIBCXX) # Options -option (DFTRACER_DISABLE_HWLOC "Disable HWLOC" On) -if (NOT DFTRACER_DISABLE_HWLOC) +option(DFTRACER_DISABLE_HWLOC "Disable HWLOC" On) + +if(NOT DFTRACER_DISABLE_HWLOC) set(DFTRACER_HWLOC_ENABLE 1) endif() # Options -option (DFTRACER_ENABLE_FTRACING "Enable Function Tracing" OFF) -if (DFTRACER_ENABLE_FTRACING) +option(DFTRACER_ENABLE_FTRACING "Enable Function Tracing" OFF) + +if(DFTRACER_ENABLE_FTRACING) set(DFTRACER_FTRACING_ENABLE 1) set(DFTRACER_FUNCTION_FLAGS "-g" "-finstrument-functions" "-Wl,-E" "-fvisibility=default") else() - set(DFTRACER_FUNCTION_FLAGS ) + set(DFTRACER_FUNCTION_FLAGS) endif() # Options -option (DFTRACER_ENABLE_HIP_TRACING "Enable HIP Tracing" OFF) -if (DFTRACER_ENABLE_HIP_TRACING) +option(DFTRACER_ENABLE_HIP_TRACING "Enable HIP Tracing" OFF) + +if(DFTRACER_ENABLE_HIP_TRACING) set(DFTRACER_HIP_TRACING_ENABLE 1) endif() -option (DFTRACER_ENABLE_MPI "Enable MPI" OFF) -if (DFTRACER_ENABLE_MPI) +option(DFTRACER_ENABLE_MPI "Enable MPI" OFF) + +if(DFTRACER_ENABLE_MPI) set(DFTRACER_MPI_ENABLE 1) endif() -option (DFTRACER_BUILD_PYTHON_BINDINGS "Build python bindings." ON) + +option(DFTRACER_BUILD_PYTHON_BINDINGS "Build python bindings." ON) set(DFTRACER_PYTHON_EXE "python3" CACHE STRING "Python executable to use for building.") + if(DEFINED ENV{DFTRACER_PYTHON_EXE}) set(DFTRACER_PYTHON_EXE $ENV{DFTRACER_PYTHON_EXE} CACHE STRING "Python executable to use for building." FORCE) endif() set(DFTRACER_PYTHON_SITE $ENV{DFTRACER_PYTHON_SITE} CACHE STRING "Python site packages to use for building.") + if(NOT DFTRACER_PYTHON_SITE AND DEFINED ENV{DFTRACER_PYTHON_SITE}) set(DFTRACER_PYTHON_SITE $ENV{DFTRACER_PYTHON_SITE} CACHE STRING "Python site packages to use for building." FORCE) endif() -if (DFTRACER_BUILD_PYTHON_BINDINGS) - if (DFTRACER_PYTHON_SITE) +if(DFTRACER_BUILD_PYTHON_BINDINGS) + if(DFTRACER_PYTHON_SITE) set(PYTHON_SITE_PACKAGES "${DFTRACER_PYTHON_SITE}") set(MAIN_PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES}) else() set(PYTHON_SITE_PACKAGES ${CMAKE_INSTALL_PREFIX}) - execute_process (COMMAND ${DFTRACER_PYTHON_EXE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE MAIN_PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${DFTRACER_PYTHON_EXE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE MAIN_PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) endif() + include_directories(${PYTHON_SITE_PACKAGES}/dftracer/include) link_directories(${PYTHON_SITE_PACKAGES}/dftracer/lib) endif() # install dependency -option (DFTRACER_INSTALL_DEPENDENCIES "Install DFTracer dependencies" OFF) +option(DFTRACER_INSTALL_DEPENDENCIES "Install DFTracer dependencies" OFF) # testing -option (DFTRACER_ENABLE_TESTS "Enable tests for DFTRACER." OFF) -option (DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS "Enable dlio_benchmark tests" OFF) -option (DFTRACER_ENABLE_PAPER_TESTS "Enable paper tests" OFF) -set (DFTRACER_TEST_LD_LIBRARY_PATH "" CACHE STRING "Additional LD_LIBRARY_PATH to be included on testing") +option(DFTRACER_ENABLE_TESTS "Enable tests for DFTRACER." OFF) +option(DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS "Enable dlio_benchmark tests" OFF) +option(DFTRACER_ENABLE_PAPER_TESTS "Enable paper tests" OFF) +set(DFTRACER_TEST_LD_LIBRARY_PATH "" CACHE STRING "Additional LD_LIBRARY_PATH to be included on testing") option(DFTRACER_ENABLE_NATIVE_SCRIPT "Build with native scripting support." OFF) -option(DFTRACER_WRITER_TYPE "Writer Type" "STDIO") +option(DFTRACER_WRITER_TYPE "Writer Type (STDIO, MOFKA, or ZMQ)" "STDIO") + if(DFTRACER_WRITER_TYPE STREQUAL "MOFKA") - set(DFTRACER_WRITER_TYPE_STDIO 0) - set(DFTRACER_WRITER_TYPE_MOFKA 1) + set(DFTRACER_WRITER_TYPE_STDIO 0) + set(DFTRACER_WRITER_TYPE_MOFKA 1) + set(DFTRACER_WRITER_TYPE_ZMQ 0) +elseif(DFTRACER_WRITER_TYPE STREQUAL "ZMQ") + set(DFTRACER_WRITER_TYPE_STDIO 0) + set(DFTRACER_WRITER_TYPE_MOFKA 0) + set(DFTRACER_WRITER_TYPE_ZMQ 1) else() - set(DFTRACER_WRITER_TYPE_STDIO 1) - set(DFTRACER_WRITER_TYPE_MOFKA 0) + set(DFTRACER_WRITER_TYPE_STDIO 1) + set(DFTRACER_WRITER_TYPE_MOFKA 0) + set(DFTRACER_WRITER_TYPE_ZMQ 0) endif() -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Compiler setup -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ include(ExternalProject) + # It requires include(GNUInstallDirs) before if that is needed include(SetupCompiler) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Build Type based configurations -#------------------------------------------------------------------------------ - +# ------------------------------------------------------------------------------ if(CMAKE_BUILD_TYPE STREQUAL "") set(CMAKE_BUILD_TYPE "Release") # Setting default as Release endif() -if (NOT DEFINED BUILD_SHARED_LIBS) +if(NOT DEFINED BUILD_SHARED_LIBS) set(BUILD_SHARED_LIBS ON) -endif () -#------------------------------------------------------------------------------ +endif() + +# ------------------------------------------------------------------------------ # Disallow in-source build -#------------------------------------------------------------------------------ -if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") +# ------------------------------------------------------------------------------ +if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR - "${PROJECT_NAME} requires an out of source Build. " - "Please create a separate binary directory and run CMake there.") -endif () -#------------------------------------------------------------------------------ + "${PROJECT_NAME} requires an out of source Build. " + "Please create a separate binary directory and run CMake there.") +endif() + +# ------------------------------------------------------------------------------ # Set a default build type if none was specified -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ set(CMAKE_POSITION_INDEPENDENT_CODE ON) -if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" - "MinSizeRel" "RelWithDebInfo") -endif () -#------------------------------------------------------------------------------ -# Dependencies -#------------------------------------------------------------------------------ + "MinSizeRel" "RelWithDebInfo") +endif() -if (DFTRACER_INSTALL_DEPENDENCIES) +# ------------------------------------------------------------------------------ +# Dependencies +# ------------------------------------------------------------------------------ +if(DFTRACER_INSTALL_DEPENDENCIES) message(STATUS "[${PROJECT_NAME}] downloading dependencies. Please run make for downloading depedencies and then do reconfigure without dependency flag.") message(STATUS "[${PROJECT_NAME}] Installing depedencies at ${CMAKE_INSTALL_PREFIX}") add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/dependency) else() -# Required Dependencies -# ============================================================================= -set(DEPENDENCY_LIB ${CMAKE_EXE_LINKER_FLAGS} $ENV{LDFLAGS} -lpthread) -set(DEPENDENCY_LIBRARY_DIRS "") - -# On some GNU toolchains, std::filesystem symbols require explicit -# linking with libstdc++fs. -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND DFTRACER_HAS_STD_FILESYSTEM) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} stdc++fs) -endif () - -find_package(cpp-logger 1.0.0 REQUIRED) -if (${cpp-logger_FOUND}) - include_directories(${CPP_LOGGER_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${CPP_LOGGER_LIBRARIES}) - set(CPP_LOGGER_LIBRARY_DIR ${cpp-logger_DIR}/../../) - # Get absolute path for CPP_LOGGER_LIBRARY_DIR - get_filename_component(CPP_LOGGER_LIBRARY_DIR "${CPP_LOGGER_LIBRARY_DIR}" ABSOLUTE) - if (DEFINED CPP_LOGGER_LIBRARY_DIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${CPP_LOGGER_LIBRARY_DIR}) + # Required Dependencies + # ============================================================================= + set(DEPENDENCY_LIB ${CMAKE_EXE_LINKER_FLAGS} $ENV{LDFLAGS} -lpthread) + set(DEPENDENCY_LIBRARY_DIRS "") + + # On some GNU toolchains, std::filesystem symbols require explicit + # linking with libstdc++fs. + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND DFTRACER_HAS_STD_FILESYSTEM) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} stdc++fs) endif() - message(STATUS "[CPP_LOGGER] found cpp-logger at ${CPP_LOGGER_INCLUDE_DIRS}") -else () + + find_package(cpp-logger 1.0.0 REQUIRED) + + if(${cpp-logger_FOUND}) + include_directories(${CPP_LOGGER_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${CPP_LOGGER_LIBRARIES}) + set(CPP_LOGGER_LIBRARY_DIR ${cpp-logger_DIR}/../../) + + # Get absolute path for CPP_LOGGER_LIBRARY_DIR + get_filename_component(CPP_LOGGER_LIBRARY_DIR "${CPP_LOGGER_LIBRARY_DIR}" ABSOLUTE) + + if(DEFINED CPP_LOGGER_LIBRARY_DIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${CPP_LOGGER_LIBRARY_DIR}) + endif() + + message(STATUS "[CPP_LOGGER] found cpp-logger at ${CPP_LOGGER_INCLUDE_DIRS}") + else() message(FATAL_ERROR "-- [CPP_LOGGER] is needed for ${PROJECT_NAME} build") -endif () - -find_package(brahma 3.0.0 REQUIRED) -if (${brahma_FOUND}) - message(STATUS "[BRAHMA] found brahma at ${BRAHMA_INCLUDE_DIRS}") - include_directories(${BRAHMA_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${BRAHMA_LIBRARIES}) - set(BRAHMA_LIBRARY_DIR ${brahma_DIR}/../../) - # Get absolute path for BRAHMA_LIBRARY_DIR - get_filename_component(BRAHMA_LIBRARY_DIR "${BRAHMA_LIBRARY_DIR}" ABSOLUTE) - if (DEFINED BRAHMA_LIBRARY_DIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${BRAHMA_LIBRARY_DIR}) endif() -else () - message(FATAL_ERROR "-- [BRAHMA] is needed for ${PROJECT_NAME} build") -endif () - -find_package(yaml-cpp REQUIRED) -if (${yaml-cpp_FOUND}) - message(STATUS "[DFTRACER] found yaml-cpp at ${YAML_CPP_INCLUDE_DIR}") - include_directories(${YAML_CPP_INCLUDE_DIR}) - set(YAML_CPP_LIBRARY_DIR ${yaml-cpp_DIR}/../../) - # Get absolute path for YAML_CPP_LIBRARY_DIR - get_filename_component(YAML_CPP_LIBRARY_DIR "${YAML_CPP_LIBRARY_DIR}" ABSOLUTE) - if (DEFINED YAML_CPP_LIBRARY_DIR) + + find_package(brahma 3.0.0 REQUIRED) + + if(${brahma_FOUND}) + message(STATUS "[BRAHMA] found brahma at ${BRAHMA_INCLUDE_DIRS}") + include_directories(${BRAHMA_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${BRAHMA_LIBRARIES}) + set(BRAHMA_LIBRARY_DIR ${brahma_DIR}/../../) + + # Get absolute path for BRAHMA_LIBRARY_DIR + get_filename_component(BRAHMA_LIBRARY_DIR "${BRAHMA_LIBRARY_DIR}" ABSOLUTE) + + if(DEFINED BRAHMA_LIBRARY_DIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${BRAHMA_LIBRARY_DIR}) + endif() + else() + message(FATAL_ERROR "-- [BRAHMA] is needed for ${PROJECT_NAME} build") + endif() + + find_package(yaml-cpp REQUIRED) + + if(${yaml-cpp_FOUND}) + message(STATUS "[DFTRACER] found yaml-cpp at ${YAML_CPP_INCLUDE_DIR}") + include_directories(${YAML_CPP_INCLUDE_DIR}) + set(YAML_CPP_LIBRARY_DIR ${yaml-cpp_DIR}/../../) + + # Get absolute path for YAML_CPP_LIBRARY_DIR + get_filename_component(YAML_CPP_LIBRARY_DIR "${YAML_CPP_LIBRARY_DIR}" ABSOLUTE) + + if(DEFINED YAML_CPP_LIBRARY_DIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${YAML_CPP_LIBRARY_DIR}) + endif() + + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} -L${YAML_CPP_LIBRARY_DIR} ${YAML_CPP_LIBRARIES}) list(APPEND DEPENDENCY_LIBRARY_DIRS ${YAML_CPP_LIBRARY_DIR}) + else() + message(FATAL_ERROR "-- [DFTRACER] yaml-cpp is needed for ${PROJECT_NAME} build") endif() - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} -L${YAML_CPP_LIBRARY_DIR} ${YAML_CPP_LIBRARIES}) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${YAML_CPP_LIBRARY_DIR}) -else () - message(FATAL_ERROR "-- [DFTRACER] yaml-cpp is needed for ${PROJECT_NAME} build") -endif () - -# Optional Dependencies -# ============================================================================= -if (DFTRACER_BUILD_PYTHON_BINDINGS) - find_package(pybind11 REQUIRED) - #add_subdirectory(dependency/py11bind) -endif() + # Optional Dependencies + # ============================================================================= + if(DFTRACER_BUILD_PYTHON_BINDINGS) + find_package(pybind11 REQUIRED) -if (DFTRACER_ENABLE_MPI) - find_package(MPI COMPONENTS CXX REQUIRED) - if (MPI_FOUND) - message(STATUS "[DFTRACER] found mpi.h at ${MPI_CXX_INCLUDE_DIRS}") - include_directories(${MPI_CXX_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${MPI_CXX_LIBRARIES}) - # Get the directory of each MPI_CXX_LIBRARY and append to MPI_CXX_LIBRARY_DIRS - set(MPI_CXX_LIBRARY_DIRS "") - foreach(_lib ${MPI_CXX_LIBRARIES}) - get_filename_component(_lib_dir "${_lib}" DIRECTORY) - if (_lib_dir) - list(APPEND MPI_CXX_LIBRARY_DIRS "${_lib_dir}") + # add_subdirectory(dependency/py11bind) + endif() + + if(DFTRACER_ENABLE_MPI) + find_package(MPI COMPONENTS CXX REQUIRED) + + if(MPI_FOUND) + message(STATUS "[DFTRACER] found mpi.h at ${MPI_CXX_INCLUDE_DIRS}") + include_directories(${MPI_CXX_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${MPI_CXX_LIBRARIES}) + + # Get the directory of each MPI_CXX_LIBRARY and append to MPI_CXX_LIBRARY_DIRS + set(MPI_CXX_LIBRARY_DIRS "") + + foreach(_lib ${MPI_CXX_LIBRARIES}) + get_filename_component(_lib_dir "${_lib}" DIRECTORY) + + if(_lib_dir) + list(APPEND MPI_CXX_LIBRARY_DIRS "${_lib_dir}") + endif() + endforeach() + + list(REMOVE_DUPLICATES MPI_CXX_LIBRARY_DIRS) + + if(DEFINED MPI_CXX_LIBRARY_DIRS) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${MPI_CXX_LIBRARY_DIRS}) endif() - endforeach() - list(REMOVE_DUPLICATES MPI_CXX_LIBRARY_DIRS) - if (DEFINED MPI_CXX_LIBRARY_DIRS) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${MPI_CXX_LIBRARY_DIRS}) + else() + message(FATAL_ERROR "-- [DFTRACER] mpi is needed for ${PROJECT_NAME} build") endif() - else () - message(FATAL_ERROR "-- [DFTRACER] mpi is needed for ${PROJECT_NAME} build") - endif () -endif() + endif() -if (NOT DFTRACER_DISABLE_HWLOC) - find_package(HWLOC REQUIRED) - if (${HWLOC_FOUND}) - include_directories(${HWLOC_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HWLOC_LIBRARIES}) - if (DEFINED HWLOC_LIBDIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${HWLOC_LIBDIR}) + if(NOT DFTRACER_DISABLE_HWLOC) + find_package(HWLOC REQUIRED) + + if(${HWLOC_FOUND}) + include_directories(${HWLOC_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HWLOC_LIBRARIES}) + + if(DEFINED HWLOC_LIBDIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${HWLOC_LIBDIR}) + endif() + + message(STATUS "[DFTRACER] found hwloc at ${HWLOC_INCLUDE_DIRS}") + else() + message(FATAL_ERROR "-- [DFTRACER] hwloc is needed for ${PROJECT_NAME} build with -DDFTRACER_DISABLE_HWLOC-ON option.") endif() - message(STATUS "[DFTRACER] found hwloc at ${HWLOC_INCLUDE_DIRS}") - else () - message(FATAL_ERROR "-- [DFTRACER] hwloc is needed for ${PROJECT_NAME} build with -DDFTRACER_DISABLE_HWLOC-ON option.") - endif () -endif() + endif() + + find_package(ZLIB REQUIRED) + + if(ZLIB_FOUND) + message(STATUS "[DFTRACER] found zlib at ${ZLIB_INCLUDE_DIRS}") + include_directories(${ZLIB_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZLIB_LIBRARIES}) + get_filename_component(ZLIB_LIBRARY "${ZLIB_LIBRARIES}" DIRECTORY) + set(ZLIB_LIBRARY_DIR "${ZLIB_LIBRARY}") + + # Get absolute path for ZLIB_LIBRARY_DIR + get_filename_component(ZLIB_LIBRARY_DIR "${ZLIB_LIBRARY_DIR}" ABSOLUTE) -find_package(ZLIB REQUIRED) -if (ZLIB_FOUND) - message(STATUS "[DFTRACER] found zlib at ${ZLIB_INCLUDE_DIRS}") - include_directories(${ZLIB_INCLUDE_DIRS}) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZLIB_LIBRARIES}) - get_filename_component(ZLIB_LIBRARY "${ZLIB_LIBRARIES}" DIRECTORY) - set(ZLIB_LIBRARY_DIR "${ZLIB_LIBRARY}") - # Get absolute path for ZLIB_LIBRARY_DIR - get_filename_component(ZLIB_LIBRARY_DIR "${ZLIB_LIBRARY_DIR}" ABSOLUTE) - if (DEFINED ZLIB_LIBRARY_DIR) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIR}) + if(DEFINED ZLIB_LIBRARY_DIR) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIR}) + endif() + + if(DEFINED ZLIB_LIBRARY_DIRS) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIRS}) + endif() + else() + message(FATAL_ERROR "-- [DFTRACER] zlib is needed for ${PROJECT_NAME} build") endif() - if (DEFINED ZLIB_LIBRARY_DIRS) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIRS}) + + if(DFTRACER_ENABLE_HIP_TRACING) + find_package(rocprofiler-sdk REQUIRED) + + if(rocprofiler-sdk_FOUND) + message(STATUS "[DFTRACER] found rocprofiler-sdk at ${ROCPROFILER_SDK_INCLUDE_DIRS}") + set(HIP_TRACING_LIBRARIES rocprofiler-sdk::rocprofiler-sdk) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HIP_TRACING_LIBRARIES}) + else() + message(FATAL_ERROR "-- [DFTRACER] rocprofiler-sdk is needed for ${PROJECT_NAME} build") + endif() endif() -else () - message(FATAL_ERROR "-- [DFTRACER] zlib is needed for ${PROJECT_NAME} build") -endif () - -if (DFTRACER_ENABLE_HIP_TRACING) - find_package(rocprofiler-sdk REQUIRED) - if (rocprofiler-sdk_FOUND) - message(STATUS "[DFTRACER] found rocprofiler-sdk at ${ROCPROFILER_SDK_INCLUDE_DIRS}") - set(HIP_TRACING_LIBRARIES rocprofiler-sdk::rocprofiler-sdk) - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${HIP_TRACING_LIBRARIES}) - else() - message(FATAL_ERROR "-- [DFTRACER] rocprofiler-sdk is needed for ${PROJECT_NAME} build") + + if(DFTRACER_WRITER_TYPE_MOFKA) + find_package(mofka REQUIRED) + + if(${mofka_FOUND}) + message(STATUS "[DFTRACER] found mofka") + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} mofka::client) + else() + message(FATAL_ERROR "-- [DFTRACER] mofka is needed for ${PROJECT_NAME} build") + endif() endif() -endif() -if(DFTRACER_WRITER_TYPE_MOFKA) - find_package(mofka REQUIRED) - if (${mofka_FOUND}) - message(STATUS "[DFTRACER] found mofka") - set(DEPENDENCY_LIB ${DEPENDENCY_LIB} mofka::client) + if(DFTRACER_WRITER_TYPE_ZMQ) + find_package(PkgConfig REQUIRED) + pkg_check_modules(ZMQ REQUIRED libzmq) + + if(ZMQ_FOUND) + message(STATUS "[DFTRACER] Found ZeroMQ at ${ZMQ_INCLUDE_DIRS}") + include_directories(${ZMQ_INCLUDE_DIRS}) + set(DEPENDENCY_LIB ${DEPENDENCY_LIB} ${ZMQ_LIBRARIES}) + list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZMQ_LIBRARY_DIRS}) + else() + message(FATAL_ERROR "-- [DFTRACER] ZeroMQ (libzmq) is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'ZMQ'") + endif() + + find_path(CPPZMQ_INCLUDE_DIR zmq.hpp) + + if(CPPZMQ_INCLUDE_DIR) + message(STATUS "[DFTRACER] Found cppzmq at ${CPPZMQ_INCLUDE_DIR}") + include_directories(${CPPZMQ_INCLUDE_DIR}) + else() + message(FATAL_ERROR "-- [DFTRACER] cppzmq (C++ wrapper for ZeroMQ) is needed for ${PROJECT_NAME} build when DFTRACER_WRITER_TYPE is 'ZMQ'") + endif() + endif() + + # Set RPATH to all dependency library dirs + list(REMOVE_DUPLICATES DEPENDENCY_LIBRARY_DIRS) + set(CMAKE_INSTALL_RPATH "${DEPENDENCY_LIBRARY_DIRS}") + set(CMAKE_BUILD_RPATH "${DEPENDENCY_LIBRARY_DIRS}") + set(CMAKE_SKIP_BUILD_RPATH OFF) + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) + + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + set(DFTRACER_PRELOAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_preload.cpp) + set(DFTRACER_PRELOAD_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_preload.h) + + set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/posix.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/stdio.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/finstrument/functions.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/function/hip/intercept.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/chrome_writer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/posix_internal.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/dftracer_main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/configuration_manager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/md5.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/df_logger.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/utils.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/serialization/json_line.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/compression/zlib_compression.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/buffer/buffer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/aggregator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/datastructure.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/rules.cpp) + set(DFTRACER_CORE_PUBLIC_INCLUDE + ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/dftracer.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/common/constants.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/common/typedef.h) + set(DFTRACER_CORE_PRIVATE_INCLUDE + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/posix_internal.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/utils.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/md5.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/finstrument/functions.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/posix.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/stdio.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/dftracer_main.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/logging.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/function/generic_function.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/function/hip/intercept.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/singleton.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/configuration_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/aggregator.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/datastructure.h) + + if(DFTRACER_WRITER_TYPE_MOFKA) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/mofka_writer.cpp) + elseif(DFTRACER_WRITER_TYPE_ZMQ) + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/zmq_writer.cpp) else() - message(FATAL_ERROR "-- [DFTRACER] mofka is needed for ${PROJECT_NAME} build") + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/stdio_writer.cpp) endif() -endif() -# Set RPATH to all dependency library dirs -list(REMOVE_DUPLICATES DEPENDENCY_LIBRARY_DIRS) -set(CMAKE_INSTALL_RPATH "${DEPENDENCY_LIBRARY_DIRS}") -set(CMAKE_BUILD_RPATH "${DEPENDENCY_LIBRARY_DIRS}") -set(CMAKE_SKIP_BUILD_RPATH OFF) -set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) + add_library(${PROJECT_NAME}_core SHARED) + target_compile_definitions(${PROJECT_NAME}_core PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) + target_link_libraries(${PROJECT_NAME}_core ${DEPENDENCY_LIB}) + add_library(${PROJECT_NAME}_core_dbg SHARED) + target_link_libraries(${PROJECT_NAME}_core_dbg ${DEPENDENCY_LIB}) + add_library(${PROJECT_NAME}_preload SHARED) + target_link_libraries(${PROJECT_NAME}_preload ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) + add_library(${PROJECT_NAME}_preload_dbg SHARED) + target_link_libraries(${PROJECT_NAME}_preload_dbg ${DEPENDENCY_LIB} ${PROJECT_NAME}_core_dbg) + + set(DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_core_dbg ${PROJECT_NAME}_preload_dbg) + set(DFTRACER_SERVICE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/service/service.cpp) + + add_executable(${PROJECT_NAME}_service ${DFTRACER_SERVICE_SRC}) + target_compile_definitions(${PROJECT_NAME}_service PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) + target_link_libraries(${PROJECT_NAME}_service ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) + + if(DFTRACER_BUILD_PYTHON_BINDINGS) + pybind11_add_module(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/python/dftracer.cpp) + target_compile_definitions(${PROJECT_NAME} PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) + target_link_libraries(${PROJECT_NAME} PRIVATE ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) + + pybind11_add_module(${PROJECT_NAME}_dbg NO_EXTRAS ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/python/dftracer_dbg.cpp) + target_compile_definitions(${PROJECT_NAME}_dbg PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) + target_link_libraries(${PROJECT_NAME}_dbg PRIVATE ${DEPENDENCY_LIB} ${PROJECT_NAME}_core_dbg) + list(APPEND DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_dbg) + endif() -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -set(DFTRACER_PRELOAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_preload.cpp) -set(DFTRACER_PRELOAD_PRIVATE_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer_preload.h) - -set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/posix.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/stdio.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/finstrument/functions.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/function/hip/intercept.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/chrome_writer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/posix_internal.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/dftracer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/dftracer_main.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/configuration_manager.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/md5.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/df_logger.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/utils.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/serialization/json_line.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/compression/zlib_compression.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/buffer/buffer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/aggregator.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/datastructure.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/rules.cpp) -set(DFTRACER_CORE_PUBLIC_INCLUDE - ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/dftracer.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/common/constants.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/dftracer/core/common/typedef.h) -set(DFTRACER_CORE_PRIVATE_INCLUDE - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/posix_internal.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/utils.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/md5.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/finstrument/functions.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/posix.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/stdio.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/dftracer_main.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/logging.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/function/generic_function.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/function/hip/intercept.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/singleton.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/utils/configuration_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/aggregator/aggregator.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/common/datastructure.h) - -if(DFTRACER_WRITER_TYPE_MOFKA) - list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/mofka_writer.cpp) -else() - list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/stdio_writer.cpp) -endif() + target_sources(${PROJECT_NAME}_core PRIVATE ${DFTRACER_CORE_SRC}) + target_sources(${PROJECT_NAME}_core_dbg PRIVATE ${DFTRACER_CORE_SRC}) + target_sources(${PROJECT_NAME}_preload PRIVATE ${DFTRACER_PRELOAD_SRC}) + target_sources(${PROJECT_NAME}_preload_dbg PRIVATE ${DFTRACER_PRELOAD_SRC}) + target_sources(${PROJECT_NAME}_service PRIVATE ${DFTRACER_SERVICE_SRC}) + target_include_directories(${PROJECT_NAME}_core PRIVATE -add_library(${PROJECT_NAME}_core SHARED) -target_compile_definitions(${PROJECT_NAME}_core PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) -target_link_libraries(${PROJECT_NAME}_core ${DEPENDENCY_LIB}) -add_library(${PROJECT_NAME}_core_dbg SHARED) -target_link_libraries(${PROJECT_NAME}_core_dbg ${DEPENDENCY_LIB}) -add_library(${PROJECT_NAME}_preload SHARED) -target_link_libraries(${PROJECT_NAME}_preload ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) -add_library(${PROJECT_NAME}_preload_dbg SHARED) -target_link_libraries(${PROJECT_NAME}_preload_dbg ${DEPENDENCY_LIB} ${PROJECT_NAME}_core_dbg) - -set(DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_core_dbg ${PROJECT_NAME}_preload_dbg) -set(DFTRACER_SERVICE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/service/service.cpp) - -add_executable(${PROJECT_NAME}_service ${DFTRACER_SERVICE_SRC}) -target_compile_definitions(${PROJECT_NAME}_service PUBLIC DFTRACER_LOGGER_LEVEL_ERROR) -target_link_libraries(${PROJECT_NAME}_service ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) - -if (DFTRACER_BUILD_PYTHON_BINDINGS) - pybind11_add_module(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/python/dftracer.cpp) - target_compile_definitions(${PROJECT_NAME} PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) - target_link_libraries(${PROJECT_NAME} PRIVATE ${DEPENDENCY_LIB} ${PROJECT_NAME}_core) - - pybind11_add_module(${PROJECT_NAME}_dbg NO_EXTRAS ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/python/dftracer_dbg.cpp) - target_compile_definitions(${PROJECT_NAME}_dbg PRIVATE VERSION_INFO=${EXAMPLE_VERSION_INFO}) - target_link_libraries(${PROJECT_NAME}_dbg PRIVATE ${DEPENDENCY_LIB} ${PROJECT_NAME}_core_dbg) - list(APPEND DFTRACER_DEBUG_TARGETS ${PROJECT_NAME}_dbg) -endif() + # where the library itself will look for its internal headers + ${CMAKE_CURRENT_SOURCE_DIR}/src + PUBLIC + + # where top-level project will look for the library's public headers + $ + + # where external projects will look for the library's public headers + $ + ) + target_include_directories(${PROJECT_NAME}_core_dbg PRIVATE + + # where the library itself will look for its internal headers + ${CMAKE_CURRENT_SOURCE_DIR}/src + PUBLIC -target_sources(${PROJECT_NAME}_core PRIVATE ${DFTRACER_CORE_SRC}) -target_sources(${PROJECT_NAME}_core_dbg PRIVATE ${DFTRACER_CORE_SRC}) -target_sources(${PROJECT_NAME}_preload PRIVATE ${DFTRACER_PRELOAD_SRC}) -target_sources(${PROJECT_NAME}_preload_dbg PRIVATE ${DFTRACER_PRELOAD_SRC}) -target_sources(${PROJECT_NAME}_service PRIVATE ${DFTRACER_SERVICE_SRC}) -target_include_directories(${PROJECT_NAME}_core PRIVATE - # where the library itself will look for its internal headers - ${CMAKE_CURRENT_SOURCE_DIR}/src - PUBLIC - # where top-level project will look for the library's public headers - $ - # where external projects will look for the library's public headers - $ -) -target_include_directories(${PROJECT_NAME}_core_dbg PRIVATE - # where the library itself will look for its internal headers - ${CMAKE_CURRENT_SOURCE_DIR}/src - PUBLIC - # where top-level project will look for the library's public headers - $ - # where external projects will look for the library's public headers - $ -) -set_target_properties(${PROJECT_NAME}_core - PROPERTIES - DEBUG_OUTPUT_NAME ${PROJECT_NAME}_core - RELEASE_OUTPUT_NAME ${PROJECT_NAME}_core - MINSIZEREL_OUTPUT_NAME ${PROJECT_NAME}_core - RELWITHDEBINFO_OUTPUT_NAME ${PROJECT_NAME}_core - VERSION ${DFTRACER_PACKAGE_VERSION} - SOVERSION ${DFTRACER_PACKAGE_VERSION} -) - -dftracer_debug_config("${DFTRACER_DEBUG_TARGETS}") -dftracer_install_headers("${DFTRACER_CORE_PUBLIC_INCLUDE}") -install( - TARGETS ${PROJECT_NAME}_core - EXPORT ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} -) -install( - TARGETS ${PROJECT_NAME}_core_dbg - EXPORT ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} -) -install( - TARGETS ${PROJECT_NAME}_service - EXPORT ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} -) -install(TARGETS ${PROJECT_NAME}_preload - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -install(TARGETS ${PROJECT_NAME}_preload_dbg - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - -install(TARGETS ${PROJECT_NAME}_preload - EXPORT ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} -) -install(TARGETS ${PROJECT_NAME}_preload_dbg - EXPORT ${DFTRACER_EXPORTED_TARGETS} - LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} - RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} -) - -if (DFTRACER_BUILD_PYTHON_BINDINGS) + # where top-level project will look for the library's public headers + $ + + # where external projects will look for the library's public headers + $ + ) + set_target_properties(${PROJECT_NAME}_core + PROPERTIES + DEBUG_OUTPUT_NAME ${PROJECT_NAME}_core + RELEASE_OUTPUT_NAME ${PROJECT_NAME}_core + MINSIZEREL_OUTPUT_NAME ${PROJECT_NAME}_core + RELWITHDEBINFO_OUTPUT_NAME ${PROJECT_NAME}_core + VERSION ${DFTRACER_PACKAGE_VERSION} + SOVERSION ${DFTRACER_PACKAGE_VERSION} + ) + + dftracer_debug_config("${DFTRACER_DEBUG_TARGETS}") + dftracer_install_headers("${DFTRACER_CORE_PUBLIC_INCLUDE}") install( - TARGETS ${PROJECT_NAME} + TARGETS ${PROJECT_NAME}_core + EXPORT ${DFTRACER_EXPORTED_TARGETS} + LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} + ) + install( + TARGETS ${PROJECT_NAME}_core_dbg + EXPORT ${DFTRACER_EXPORTED_TARGETS} + LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} + ) + install( + TARGETS ${PROJECT_NAME}_service + EXPORT ${DFTRACER_EXPORTED_TARGETS} + LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} + ) + install(TARGETS ${PROJECT_NAME}_preload LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(TARGETS ${PROJECT_NAME}_preload_dbg + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + install(TARGETS ${PROJECT_NAME}_preload + EXPORT ${DFTRACER_EXPORTED_TARGETS} + LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} + ) + install(TARGETS ${PROJECT_NAME}_preload_dbg + EXPORT ${DFTRACER_EXPORTED_TARGETS} + LIBRARY DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${DFTRACER_INSTALL_LIB_DIR} + RUNTIME DESTINATION ${DFTRACER_INSTALL_BIN_DIR} ) - file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;mkdir -p ${MAIN_PYTHON_SITE_PACKAGES}/dftracer;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") - install(CODE "execute_process( + + if(DFTRACER_BUILD_PYTHON_BINDINGS) + install( + TARGETS ${PROJECT_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;mkdir -p ${MAIN_PYTHON_SITE_PACKAGES}/dftracer;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") + install(CODE "execute_process( COMMAND bash -c \"set -e chmod +x ${CMAKE_BINARY_DIR}/symlink.sh . ${CMAKE_BINARY_DIR}/symlink.sh \")") - install( - TARGETS ${PROJECT_NAME}_dbg - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) - file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink_dbg.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;mkdir -p ${MAIN_PYTHON_SITE_PACKAGES}/dftracer;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") - install(CODE "execute_process( + install( + TARGETS ${PROJECT_NAME}_dbg + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/symlink_dbg.sh CONTENT "echo -- Installing: symlink ${MAIN_PYTHON_SITE_PACKAGES}/$ from ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$;mkdir -p ${MAIN_PYTHON_SITE_PACKAGES}/dftracer;ln -sf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/$ ${MAIN_PYTHON_SITE_PACKAGES}/dftracer/$") + install(CODE "execute_process( COMMAND bash -c \"set -e chmod +x ${CMAKE_BINARY_DIR}/symlink_dbg.sh . ${CMAKE_BINARY_DIR}/symlink_dbg.sh \")") -endif() + endif() -if(DFTRACER_ENABLE_NATIVE_SCRIPT) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact DESTINATION bin) + if(DFTRACER_ENABLE_NATIVE_SCRIPT) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact_by_pid ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid DESTINATION bin) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_compact_by_pid ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_compact_by_pid DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_merge ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge DESTINATION bin) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_merge ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_merge DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_sanitize ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize DESTINATION bin) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_sanitize ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_sanitize DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_anonymize ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize DESTINATION bin) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_anonymize ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_anonymize DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_create_index ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index DESTINATION bin) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_create_index ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_create_index DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_pgzip ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip DESTINATION bin) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_pgzip ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_pgzip DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_split ${EXECUTABLE_OUTPUT_PATH}/dftracer_split COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_split DESTINATION bin) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_split ${EXECUTABLE_OUTPUT_PATH}/dftracer_split COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_split DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_event_count ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count DESTINATION bin) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_event_count ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_event_count DESTINATION bin) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_validate ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate COPYONLY) - install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate DESTINATION bin) -endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/dftracer_validate ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate DESTINATION bin) + endif() + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/git_sparse_clone_interactive ${EXECUTABLE_OUTPUT_PATH}/git_sparse_clone_interactive COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/git_sparse_clone_interactive DESTINATION bin) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/git_sparse_push_interactive ${EXECUTABLE_OUTPUT_PATH}/git_sparse_push_interactive COPYONLY) + install(FILES ${EXECUTABLE_OUTPUT_PATH}/git_sparse_push_interactive DESTINATION bin) + + # cmake_policy(SET CMP0079 NEW) # In case that we need more control over the target building order + if(DFTRACER_ENABLE_TESTS) + message("-- " "[DFTracer] Enabling Testing") + + if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") + message("-- " "[DFTracer] building with CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}") + set(CMAKE_C_FLAGS_PROFILE --coverage) + set(CMAKE_CXX_FLAGS_PROFILE --coverage) + endif() + + enable_testing() + add_subdirectory(test) + + if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") + get_property(COVERAGE_FILE_LIST GLOBAL PROPERTY COVERAGE_FILES) + add_custom_command(OUTPUT default.profdata COMMAND llvm-profdata merge -sparse ${COVERAGE_FILE_LIST} -o default.profdata VERBATIM) + add_custom_target(merged_coverage DEPENDS default.profdata) + endif() + endif() + + # ----------------------------------------------------------------------------- + # Configure the config.cmake file for the build directory + # ----------------------------------------------------------------------------- + include(CMakePackageConfigHelpers) + configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.build.in + "${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config.cmake" + INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake + PATH_VARS CMAKE_BINARY_DIR + ) + + configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.install.in + "${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake" + INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/install/${PROJECT_NAME}-config.cmake + PATH_VARS CMAKE_BINARY_DIR + ) + install(FILES ${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME}) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/dftracer-utils.cmake" DESTINATION "${DFTRACER_LIBDIR}/cmake/dftracer") -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/git_sparse_clone_interactive ${EXECUTABLE_OUTPUT_PATH}/git_sparse_clone_interactive COPYONLY) -install(FILES ${EXECUTABLE_OUTPUT_PATH}/git_sparse_clone_interactive DESTINATION bin) + # ----------------------------------------------------------------------------- + # Configure the ${PROJECT_NAME}-config-version .cmake file for the install directory + # ----------------------------------------------------------------------------- + install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME}) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/script/git_sparse_push_interactive ${EXECUTABLE_OUTPUT_PATH}/git_sparse_push_interactive COPYONLY) -install(FILES ${EXECUTABLE_OUTPUT_PATH}/git_sparse_push_interactive DESTINATION bin) + export(EXPORT ${DFTRACER_EXPORTED_TARGETS} FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake") + + # Write the configure file + configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config.hpp.in" + "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config.hpp" @ONLY) + + configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config_dbg.hpp.in" + "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config_dbg.hpp" @ONLY) + + # ############################################################### + # Install DFTRACER + # ############################################################### + include(CMakePackageConfigHelpers) + + # Write the version file. This is independent of build/install tree. + write_basic_package_version_file( + dftracer-config-version.cmake + VERSION "${DFTRACER_PACKAGE_VERSION}" + COMPATIBILITY SameMajorVersion + ) -#cmake_policy(SET CMP0079 NEW) # In case that we need more control over the target building order + install(FILES "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config.hpp" DESTINATION ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer/core) + install(FILES "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config_dbg.hpp" DESTINATION ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer/core) -if(DFTRACER_ENABLE_TESTS) - message("-- " "[DFTracer] Enabling Testing") - if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") - message("-- " "[DFTracer] building with CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}") - set(CMAKE_C_FLAGS_PROFILE --coverage) - set(CMAKE_CXX_FLAGS_PROFILE --coverage) + install(EXPORT ${DFTRACER_EXPORTED_TARGETS} DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} FILE ${DFTRACER_EXPORTED_TARGETS}.cmake) + + # Install license and readme + install(FILES "${PROJECT_SOURCE_DIR}/LICENSE" "${PROJECT_SOURCE_DIR}/README.md" DESTINATION ${DFTRACER_INSTALL_DOCDIR}) + + # ############################################################################## + # Print out configuration summary + # ############################################################################## + if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") + set(DFTRACER_GNU_LINUX TRUE) endif() - enable_testing() - add_subdirectory(test) - if(CMAKE_BUILD_TYPE STREQUAL "PROFILE") - get_property(COVERAGE_FILE_LIST GLOBAL PROPERTY COVERAGE_FILES) - add_custom_command(OUTPUT default.profdata COMMAND llvm-profdata merge -sparse ${COVERAGE_FILE_LIST} -o default.profdata VERBATIM) - add_custom_target(merged_coverage DEPENDS default.profdata) + + # NOTE: message() outputs to stderr by default. We now use a string to + # maintain this information and then have cmake echo it to stdout. The + # only side effects are that if you use the CMake GUI, you won't see + # this output anymore (they only report stderr) and that if you add + # something to the list, you must remember your newline! + set(_str "\n== DFTRACER Configuration Summary ==\n\n") + string(APPEND _str " PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}\n" + " PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}\n\n" + " CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}\n" + " CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n\n") + + if(CMAKE_BUILD_TYPE MATCHES None) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS}\n") + elseif(CMAKE_BUILD_TYPE MATCHES Release) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\n") + string(APPEND _str + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}\n") + elseif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}\n") + string(APPEND _str + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELWITHDEBINFO}\n") + elseif(CMAKE_BUILD_TYPE MATCHES Debug) + string(APPEND _str + " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}\n") + string(APPEND _str + " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}\n") endif() -endif() -#----------------------------------------------------------------------------- -# Configure the config.cmake file for the build directory -#----------------------------------------------------------------------------- -include(CMakePackageConfigHelpers) -configure_package_config_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.build.in - "${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config.cmake" - INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake - PATH_VARS CMAKE_BINARY_DIR -) - -configure_package_config_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure_files/${PROJECT_NAME}-config.cmake.install.in - "${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake" - INSTALL_DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/install/${PROJECT_NAME}-config.cmake - PATH_VARS CMAKE_BINARY_DIR -) -install(FILES ${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}-config.cmake DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME}) -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/dftracer-utils.cmake" DESTINATION "${DFTRACER_LIBDIR}/cmake/dftracer") -#----------------------------------------------------------------------------- -# Configure the ${PROJECT_NAME}-config-version .cmake file for the install directory -#----------------------------------------------------------------------------- - -install(FILES ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME}) - -export(EXPORT ${DFTRACER_EXPORTED_TARGETS} FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake") - -# Write the configure file -configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config.hpp.in" - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config.hpp" @ONLY) - -configure_file("${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_config_dbg.hpp.in" - "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config_dbg.hpp" @ONLY) - -################################################################ -# Install DFTRACER -################################################################ - -include(CMakePackageConfigHelpers) - -# Write the version file. This is independent of build/install tree. -write_basic_package_version_file( - dftracer-config-version.cmake - VERSION "${DFTRACER_PACKAGE_VERSION}" - COMPATIBILITY SameMajorVersion -) - -install(FILES "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config.hpp" DESTINATION ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer/core) -install(FILES "${CMAKE_INCLUDE_OUTPUT_DIRECTORY}/dftracer/core/dftracer_config_dbg.hpp" DESTINATION ${DFTRACER_INSTALL_INCLUDE_DIR}/dftracer/core) - -install(EXPORT ${DFTRACER_EXPORTED_TARGETS} DESTINATION ${DFTRACER_LIBDIR}/cmake/${PROJECT_NAME} FILE ${DFTRACER_EXPORTED_TARGETS}.cmake) - -# Install license and readme -install(FILES "${PROJECT_SOURCE_DIR}/LICENSE" "${PROJECT_SOURCE_DIR}/README.md" DESTINATION ${DFTRACER_INSTALL_DOCDIR}) - -############################################################################### -# Print out configuration summary -############################################################################### - -if (CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") - set(DFTRACER_GNU_LINUX TRUE) -endif () - -# NOTE: message() outputs to stderr by default. We now use a string to -# maintain this information and then have cmake echo it to stdout. The -# only side effects are that if you use the CMake GUI, you won't see -# this output anymore (they only report stderr) and that if you add -# something to the list, you must remember your newline! -set(_str "\n== DFTRACER Configuration Summary ==\n\n") -string(APPEND _str " PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}\n" - " PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}\n\n" - " CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}\n" - " CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n\n") -if (CMAKE_BUILD_TYPE MATCHES None) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS}\n") -elseif (CMAKE_BUILD_TYPE MATCHES Release) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}\n") - string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}\n") -elseif (CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}\n") - string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELWITHDEBINFO}\n") -elseif (CMAKE_BUILD_TYPE MATCHES Debug) - string(APPEND _str - " CXX FLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}\n") - string(APPEND _str - " C FLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}\n") -endif () -string(APPEND _str "\n") - -string(APPEND _str - " DFTRACER_PACKAGE_VERSION: ${DFTRACER_PACKAGE_VERSION}\n") -string(APPEND _str - " DFTRACER_GIT_VERSION: ${DFTRACER_GIT_VERSION}\n") -string(APPEND _str - " GLIBC_VERSION: ${GLIBC_VERSION}\n") - string(APPEND _str - " DFTRACER_PYTHON_EXE: ${DFTRACER_PYTHON_EXE}\n") - string(APPEND _str - " DFTRACER_PYTHON_SITE: ${DFTRACER_PYTHON_SITE}\n") - string(APPEND _str - " MAIN_PYTHON_SITE_PACKAGES: ${MAIN_PYTHON_SITE_PACKAGES}\n") - string(APPEND _str - " DEPENDENCY_LIB: ${DEPENDENCY_LIB}\n") - string(APPEND _str - " CMAKE_BUILD_RPATH: ${CMAKE_BUILD_RPATH}\n") - string(APPEND _str - " CMAKE_INSTALL_RPATH: ${CMAKE_INSTALL_RPATH}\n") - -# Print the true/false variables -append_str_tf(_str - DFTRACER_GNU_LINUX - DFTRACER_LIBDIR_AS_LIB - DFTRACER_ENABLE_FTRACING - DFTRACER_ENABLE_HIP_TRACING - DFTRACER_ENABLE_MPI - DFTRACER_DISABLE_HWLOC - DFTRACER_USE_CLANG_LIBCXX - DFTRACER_WARNINGS_AS_ERRORS - DFTRACER_BUILD_PYTHON_BINDINGS - DFTRACER_ENABLE_TESTS - DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS - DFTRACER_ENABLE_PAPER_TESTS - DFTRACER_WRITER_TYPE_STDIO - DFTRACER_WRITER_TYPE_MOFKA -) -string(APPEND _str - "\n== End DFTRACER Configuration Summary ==\n") - -# Output to stdout -execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${_str}") -set(_str) - -############################################################################### -# Write a basic modulefile -############################################################################### - -set(DFTRACER_MODULEFILE_NAME "dftracer-${DFTRACER_PACKAGE_VERSION}.lua") - -# CACHE STRING -# "The name of the DFTRACER modulefile to install. Must end in .lua." -if (NOT (DFTRACER_MODULEFILE_NAME MATCHES ".+\.lua")) - message(WARNING - "DFTRACER_MODULEFILE_NAME must have extension \".lua\". Appending.") - set(DFTRACER_MODULEFILE_NAME "${DFTRACER_MODULEFILE_NAME}.lua" - CACHE STRING "" FORCE) -endif () - -configure_file( - "${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_module.lua.in" - "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" - @ONLY) - -install( - FILES "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" - RENAME "${DFTRACER_MODULEFILE_NAME}" - DESTINATION "${DFTRACER_INSTALL_SYSCONFDIR}" -) + string(APPEND _str "\n") + + string(APPEND _str + " DFTRACER_PACKAGE_VERSION: ${DFTRACER_PACKAGE_VERSION}\n") + string(APPEND _str + " DFTRACER_GIT_VERSION: ${DFTRACER_GIT_VERSION}\n") + string(APPEND _str + " GLIBC_VERSION: ${GLIBC_VERSION}\n") + string(APPEND _str + " DFTRACER_PYTHON_EXE: ${DFTRACER_PYTHON_EXE}\n") + string(APPEND _str + " DFTRACER_PYTHON_SITE: ${DFTRACER_PYTHON_SITE}\n") + string(APPEND _str + " MAIN_PYTHON_SITE_PACKAGES: ${MAIN_PYTHON_SITE_PACKAGES}\n") + string(APPEND _str + " DEPENDENCY_LIB: ${DEPENDENCY_LIB}\n") + string(APPEND _str + " CMAKE_BUILD_RPATH: ${CMAKE_BUILD_RPATH}\n") + string(APPEND _str + " CMAKE_INSTALL_RPATH: ${CMAKE_INSTALL_RPATH}\n") + + # Print the true/false variables + append_str_tf(_str + DFTRACER_GNU_LINUX + DFTRACER_LIBDIR_AS_LIB + DFTRACER_ENABLE_FTRACING + DFTRACER_ENABLE_HIP_TRACING + DFTRACER_ENABLE_MPI + DFTRACER_DISABLE_HWLOC + DFTRACER_USE_CLANG_LIBCXX + DFTRACER_WARNINGS_AS_ERRORS + DFTRACER_BUILD_PYTHON_BINDINGS + DFTRACER_ENABLE_TESTS + DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS + DFTRACER_ENABLE_PAPER_TESTS + DFTRACER_WRITER_TYPE_STDIO + DFTRACER_WRITER_TYPE_MOFKA + ) + string(APPEND _str + "\n== End DFTRACER Configuration Summary ==\n") + + # Output to stdout + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${_str}") + set(_str) + + # ############################################################################## + # Write a basic modulefile + # ############################################################################## + set(DFTRACER_MODULEFILE_NAME "dftracer-${DFTRACER_PACKAGE_VERSION}.lua") + + # CACHE STRING + # "The name of the DFTRACER modulefile to install. Must end in .lua." + if(NOT(DFTRACER_MODULEFILE_NAME MATCHES ".+\.lua")) + message(WARNING + "DFTRACER_MODULEFILE_NAME must have extension \".lua\". Appending.") + set(DFTRACER_MODULEFILE_NAME "${DFTRACER_MODULEFILE_NAME}.lua" + CACHE STRING "" FORCE) + endif() + + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/configure_files/dftracer_module.lua.in" + "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" + @ONLY) + install( + FILES "${CMAKE_BINARY_DIR}/dftracer_module.lua.install" + RENAME "${DFTRACER_MODULEFILE_NAME}" + DESTINATION "${DFTRACER_INSTALL_SYSCONFDIR}" + ) endif() diff --git a/cmake/configure_files/dftracer_config.hpp.in b/cmake/configure_files/dftracer_config.hpp.in index afc939d4..4f8280ff 100644 --- a/cmake/configure_files/dftracer_config.hpp.in +++ b/cmake/configure_files/dftracer_config.hpp.in @@ -37,6 +37,7 @@ #cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" #cmakedefine01 DFTRACER_WRITER_TYPE_STDIO #cmakedefine01 DFTRACER_WRITER_TYPE_MOFKA +#cmakedefine01 DFTRACER_WRITER_TYPE_ZMQ //========================== // Common macro definitions diff --git a/cmake/configure_files/dftracer_config_dbg.hpp.in b/cmake/configure_files/dftracer_config_dbg.hpp.in index 07428aab..23595808 100644 --- a/cmake/configure_files/dftracer_config_dbg.hpp.in +++ b/cmake/configure_files/dftracer_config_dbg.hpp.in @@ -37,6 +37,7 @@ #cmakedefine DFTRACER_WRITER_TYPE "@DFTRACER_WRITER_TYPE@" #cmakedefine01 DFTRACER_WRITER_TYPE_STDIO #cmakedefine01 DFTRACER_WRITER_TYPE_MOFKA +#cmakedefine01 DFTRACER_WRITER_TYPE_ZMQ #define DFTRACER_LOGGER_CPP_LOGGER 1 #define DFTRACER_LOGGER_LEVEL_TRACE 1 diff --git a/pyproject.toml b/pyproject.toml index 4d2c0a7c..63b771b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,11 @@ [build-system] requires = [ - "setuptools>=64", - "setuptools-scm>=8", - "wheel", - "ninja", - "cmake>=3.12", - "pybind11" + "setuptools>=64", + "setuptools-scm>=8", + "wheel", + "ninja", + "cmake>=3.12", + "pybind11", ] build-backend = "setuptools.build_meta" @@ -16,15 +16,15 @@ readme = "README.md" requires-python = '>=3.7' authors = [ - { name = "Hariharan Devarajan (Hari)", email = "hariharandev1@llnl.gov" } + { name = "Hariharan Devarajan (Hari)", email = "hariharandev1@llnl.gov" }, ] keywords = [ - "profiler", - "deep learning", - "I/O", - "benchmark", - "NPZ", - "pytorch benchmark", + "profiler", + "deep learning", + "I/O", + "benchmark", + "NPZ", + "pytorch benchmark", "tensorflow benchmark", ] classifiers = [ @@ -49,11 +49,11 @@ classifiers = [ ] dynamic = ["version"] dependencies = [ - "pybind11", - "setuptools>=64", + "pybind11", + "setuptools>=64", "setuptools-scm>=8", "dftracer-utils>=0.0.5", - "pydftracer>=2.0.2" + "pydftracer>=2.0.2", ] [project.urls] @@ -64,25 +64,23 @@ Documentation = "https://dftracer.readthedocs.io/en/latest/" [project.optional-dependencies] test = ['pytest>=6.0'] -dfanalyzer = [ - 'dftracer-analyzer>=0.0.5' -] +dfanalyzer = ['dftracer-analyzer>=0.0.5'] dfanalyzer_old = [ - 'seaborn>=0.13.2', - 'bokeh>=2.4.2', - 'pybind11', - 'pandas>=2.0.3', - 'dask>=2023.5.0', - 'distributed', - 'numpy>=1.24.3', - 'pyarrow>=12.0.1', - 'rich>=13.6.0', - 'python-intervals>=1.10.0.post1', - 'matplotlib>=3.7.3' -] -dynamo = [ - 'torch>=2.5.1' + 'seaborn>=0.13.2', + 'bokeh>=2.4.2', + 'pybind11', + 'pandas>=2.0.3', + 'dask>=2023.5.0', + 'distributed', + 'numpy>=1.24.3', + 'pyarrow>=12.0.1', + 'rich>=13.6.0', + 'python-intervals>=1.10.0.post1', + 'matplotlib>=3.7.3', ] +dynamo = ['torch>=2.5.1'] +streaming-mofka = [] +streaming-zmq = ['pyzmq>=27.0.0'] [tool] files = "setup.py" @@ -121,7 +119,7 @@ extend-select = [ "UP", # pyupgrade ] extend-ignore = [ - "E501", # Line too long + "E501", # Line too long ] target-version = "py38" @@ -134,4 +132,3 @@ script-files = [ [tool.setuptools_scm] local_scheme = "no-local-version" write_to = "python/dftracer/_version.py" - diff --git a/src/dftracer/core/buffer/buffer.cpp b/src/dftracer/core/buffer/buffer.cpp index 3bcca78e..9ca48466 100644 --- a/src/dftracer/core/buffer/buffer.cpp +++ b/src/dftracer/core/buffer/buffer.cpp @@ -5,7 +5,9 @@ #if DFTRACER_WRITER_TYPE_MOFKA #include -#elif DFTRACER_WRITER_TYPE_STDIO +#elif DFTRACER_WRITER_TYPE_ZMQ +#include +#else #include #endif @@ -50,6 +52,9 @@ int BufferManager::initialize(const char* filename, HashType hostname_hash) { #if DFTRACER_WRITER_TYPE_MOFKA this->writer = std::static_pointer_cast( dftracer::Singleton::get_instance()); +#elif DFTRACER_WRITER_TYPE_ZMQ + this->writer = std::static_pointer_cast( + dftracer::Singleton::get_instance()); #else this->writer = std::static_pointer_cast( dftracer::Singleton::get_instance()); diff --git a/src/dftracer/core/common/enumeration.h b/src/dftracer/core/common/enumeration.h index a93e56ac..28564a41 100644 --- a/src/dftracer/core/common/enumeration.h +++ b/src/dftracer/core/common/enumeration.h @@ -12,6 +12,7 @@ enum WriterType : uint8_t { WRITER_TYPE_STDIO = 0, WRITER_TYPE_MOFKA = 1, + WRITER_TYPE_ZMQ = 2, }; enum ProfilerStage : uint8_t { PROFILER_INIT = 0, @@ -105,6 +106,8 @@ inline std::string to_string(const AggregationType& type) { inline void convert(const std::string& s, WriterType& type) { if (s == "MOFKA") { type = WriterType::WRITER_TYPE_MOFKA; + } else if (s == "ZMQ") { + type = WriterType::WRITER_TYPE_ZMQ; } else { type = WriterType::WRITER_TYPE_STDIO; } diff --git a/src/dftracer/core/utils/configuration_manager.cpp b/src/dftracer/core/utils/configuration_manager.cpp index 4b7330e7..cd9a36bf 100644 --- a/src/dftracer/core/utils/configuration_manager.cpp +++ b/src/dftracer/core/utils/configuration_manager.cpp @@ -70,6 +70,8 @@ dftracer::ConfigurationManager::ConfigurationManager() write_buffer_size(16 * 1024 * 1024), #if DFTRACER_WRITER_TYPE_MOFKA writer_type(WriterType::WRITER_TYPE_MOFKA), +#elif DFTRACER_WRITER_TYPE_ZMQ + writer_type(WriterType::WRITER_TYPE_ZMQ), #else writer_type(WriterType::WRITER_TYPE_STDIO), #endif @@ -396,6 +398,12 @@ dftracer::ConfigurationManager::ConfigurationManager() this->compression = false; } } + if (this->writer_type == WriterType::WRITER_TYPE_ZMQ) { + if (this->compression) { + DFTRACER_LOG_WARN("Compression is not supported for ZMQ writer", ""); + this->compression = false; + } + } derive_configurations(); DFTRACER_LOG_DEBUG("ENV ConfigurationManager finished", ""); } diff --git a/src/dftracer/core/writer/zmq_writer.cpp b/src/dftracer/core/writer/zmq_writer.cpp new file mode 100644 index 00000000..4564ce06 --- /dev/null +++ b/src/dftracer/core/writer/zmq_writer.cpp @@ -0,0 +1,181 @@ +#include +#include +#include + +#include +#include +#include + +namespace dftracer { + +template <> +std::shared_ptr Singleton::instance = nullptr; +template <> +bool Singleton::stop_creating_instances = false; + +// Static pointer for fork handling +static ZMQWriter* writer_instance = nullptr; + +// Fork handler called in child process after fork +static void on_fork_child() { + if (writer_instance) { + DFTRACER_LOG_DEBUG("Fork child: re-initializing ZMQ socket.", ""); + writer_instance->reconnect(); + } +} + +ZMQWriter::ZMQWriter() + : context_(nullptr), socket_(nullptr), initialized_(false), init_pid_(0) { + DFTRACER_LOG_DEBUG("ZMQWriter.ZMQWriter", ""); +} + +ZMQWriter::~ZMQWriter() { finalize(0); } + +void ZMQWriter::initialize(const char* filename) { + if (initialized_) { + DFTRACER_LOG_INFO("ZMQWriter already initialized", ""); + return; + } + + // Use environment variable if filename is not provided + const char* env_endpoint = std::getenv("DFTRACER_ZMQ_ENDPOINT"); + if (env_endpoint && strlen(env_endpoint) > 0) { + endpoint_ = env_endpoint; + } else { + endpoint_ = filename ? filename : "tcp://localhost:5555"; + } + + try { + context_ = std::make_unique(1); + socket_ = + std::make_unique(*context_, zmq::socket_type::push); + + if (!socket_) { + DFTRACER_LOG_ERROR("Unable to create ZeroMQ socket for %s", + endpoint_.c_str()); + throw std::runtime_error("Failed to create ZeroMQ socket"); + } + + socket_->connect(endpoint_); + initialized_ = true; + init_pid_ = getpid(); + + // Register fork handler for child process reconnection + writer_instance = this; + pthread_atfork(nullptr, nullptr, on_fork_child); + + DFTRACER_LOG_INFO("ZMQWriter connected to %s with fork handling (PID %d)", + endpoint_.c_str(), init_pid_); + } catch (const zmq::error_t& e) { + DFTRACER_LOG_ERROR("ZeroMQ error during initialization: %s", e.what()); + throw std::runtime_error(std::string("ZeroMQ initialization failed: ") + + e.what()); + } +} + +size_t ZMQWriter::write(const char* data, size_t len, bool force) { + if (!initialized_ || !socket_) { + DFTRACER_LOG_ERROR("ZMQWriter not initialized or socket is null", ""); + return 0; + } + + if (len == 0 || !data) { + return 0; + } + + try { + zmq::message_t message(data, len); + auto result = socket_->send(message, zmq::send_flags::dontwait); + + if (result) { + DFTRACER_LOG_DEBUG("ZMQWriter sent %zu bytes", len); + return len; + } else { + DFTRACER_LOG_ERROR("ZMQWriter failed to send message (would block)", ""); + return 0; + } + } catch (const zmq::error_t& e) { + DFTRACER_LOG_ERROR("ZMQWriter send error: %s", e.what()); + return 0; + } +} + +void ZMQWriter::finalize(int index) { + if (!initialized_) { + DFTRACER_LOG_DEBUG("ZMQWriter already finalized or not initialized", ""); + return; + } + + // Check if we're in a child process - skip finalization to avoid hang + if (getpid() != init_pid_) { + DFTRACER_LOG_INFO( + "ZMQWriter::finalize called in child process (Init PID: %d, Current " + "PID: %d). Skipping finalization.", + init_pid_, getpid()); + // Release ownership to avoid destructor calls + if (socket_) socket_.release(); + if (context_) context_.release(); + initialized_ = false; + return; + } + + DFTRACER_LOG_INFO("ZMQWriter finalizing", ""); + + try { + if (socket_) { + socket_->close(); + socket_.reset(); + } + if (context_) { + context_->close(); + context_.reset(); + } + } catch (const zmq::error_t& e) { + DFTRACER_LOG_ERROR("ZeroMQ error during finalization: %s", e.what()); + } + + if (writer_instance == this) { + writer_instance = nullptr; + } + + initialized_ = false; + DFTRACER_LOG_INFO("ZMQWriter finalized", ""); +} + +void ZMQWriter::reconnect() { + DFTRACER_LOG_DEBUG("Child process starting ZMQ reconnect", ""); + + // Release ownership of the inherited pointers. + // This prevents the destructor (and zmq_close) from being called. + // The old state is invalid and must be abandoned. + if (socket_) socket_.release(); + if (context_) context_.release(); + + DFTRACER_LOG_DEBUG("Child process abandoned inherited ZMQ state", ""); + + // Create a brand new context and socket for this child process. + try { + context_ = std::make_unique(1); + socket_ = + std::make_unique(*context_, zmq::socket_type::push); + + if (!socket_) { + DFTRACER_LOG_ERROR("Unable to create new ZeroMQ socket in child for %s", + endpoint_.c_str()); + initialized_ = false; + return; + } + + // Connect the new socket to the original destination. + socket_->connect(endpoint_); + init_pid_ = getpid(); + DFTRACER_LOG_INFO( + "Child process successfully reconnected ZMQ socket to %s (PID %d)", + endpoint_.c_str(), init_pid_); + } catch (const zmq::error_t& e) { + DFTRACER_LOG_ERROR("ZeroMQ error during reconnect: %s", e.what()); + initialized_ = false; + } +} + +} // namespace dftracer diff --git a/src/dftracer/core/writer/zmq_writer.h b/src/dftracer/core/writer/zmq_writer.h new file mode 100644 index 00000000..074b5f66 --- /dev/null +++ b/src/dftracer/core/writer/zmq_writer.h @@ -0,0 +1,40 @@ +#ifndef DFTRACER_ZMQ_WRITER_H +#define DFTRACER_ZMQ_WRITER_H + +#include +#include +#include +#include + +#include +#include +#include + +namespace dftracer { + +class ZMQWriter : public WriterInterface { + private: + std::unique_ptr context_; + std::unique_ptr socket_; + std::string endpoint_; + bool initialized_; + pid_t init_pid_; + + public: + ZMQWriter(); + ~ZMQWriter() override; + + void initialize(const char* filename) override; + size_t write(const char* data, size_t len, bool force = false) override; + void finalize(int index) override; + + /** + * @brief Re-initializes the ZMQ socket. This is intended to be called + * in a child process after a fork(). + */ + void reconnect(); +}; + +} // namespace dftracer + +#endif // DFTRACER_ZMQ_WRITER_H diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e302dc2f..7342a5d3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,6 +4,10 @@ include_directories(${DFTRACER_PROJECT_DIR}/include) set(MOFKA_GROUP_FILE "${CMAKE_CURRENT_BINARY_DIR}/mofka.group.json") set(MOFKA_SERVER_FIXTURE "MOFKA_SERVER") +set(ZMQ_EVENT_PORT 5555) +set(ZMQ_CONTROL_PORT 5556) +set(ZMQ_SINK_FIXTURE "ZMQ_SINK") + find_program(BASH_EXE bash) if(DFTRACER_WRITER_TYPE_MOFKA) @@ -14,6 +18,13 @@ if(DFTRACER_WRITER_TYPE_MOFKA) set_tests_properties(mofka_server_stop PROPERTIES FIXTURES_CLEANUP ${MOFKA_SERVER_FIXTURE}) endif() +if(DFTRACER_WRITER_TYPE_ZMQ) + add_test(zmq_sink_start ${CMAKE_CURRENT_SOURCE_DIR}/zmq_sink_start.sh ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_BINARY_DIR}/zmq_sink.log ${ZMQ_EVENT_PORT} ${ZMQ_CONTROL_PORT}) + add_test(zmq_sink_stop ${CMAKE_CURRENT_SOURCE_DIR}/zmq_sink_stop.sh ${ZMQ_CONTROL_PORT}) + set_tests_properties(zmq_sink_start PROPERTIES FIXTURES_SETUP ${ZMQ_SINK_FIXTURE}) + set_tests_properties(zmq_sink_stop PROPERTIES FIXTURES_CLEANUP ${ZMQ_SINK_FIXTURE}) +endif() + function(df_add_test) add_test(${ARGV}) set_tests_properties(${ARGV0} PROPERTIES @@ -32,6 +43,10 @@ function(df_check_test test_name expected_count) set_tests_properties(check_${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${MOFKA_GROUP_FILE}) set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) + elseif(DFTRACER_WRITER_TYPE_ZMQ) + df_add_test(check_${test_name} + ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_zmq_sink.py ${test_name} ${expected_count} --control-port ${ZMQ_CONTROL_PORT}) + set_tests_properties(check_${test_name} PROPERTIES FIXTURES_REQUIRED ${ZMQ_SINK_FIXTURE}) else() if(${expected_count} EQUAL 0) df_add_test(check_${test_name} @@ -83,6 +98,11 @@ function(set_common_properties test_name) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) endif() + + if(DFTRACER_WRITER_TYPE_ZMQ) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ZMQ_ENDPOINT=tcp://localhost:${ZMQ_EVENT_PORT}) + set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${ZMQ_SINK_FIXTURE}) + endif() endfunction() file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data) diff --git a/test/check_zmq_sink.py b/test/check_zmq_sink.py new file mode 100755 index 00000000..87f4e86b --- /dev/null +++ b/test/check_zmq_sink.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +""" +Check ZMQ Sink for DFTracer Testing + +This script queries the ZMQ sink to: +1. Get the count of collected events +2. Validate events are valid JSON +3. Clear the event buffer for the next test + +Usage: check_zmq_sink.py [control_port] +""" + +import sys +import os +import json +import argparse +import zmq + + +def send_command(control_port, cmd): + """Send a command to the ZMQ sink and return the response.""" + context = zmq.Context() + socket = context.socket(zmq.REQ) + socket.setsockopt(zmq.RCVTIMEO, 5000) # 5 second timeout + socket.setsockopt(zmq.SNDTIMEO, 5000) + + try: + socket.connect(f"tcp://localhost:{control_port}") + socket.send_json(cmd) + response = socket.recv_json() + return response + except zmq.error.Again: + print(f"Error: Timeout connecting to ZMQ sink on port {control_port}") + return None + except Exception as e: + print(f"Error communicating with ZMQ sink: {e}") + return None + finally: + socket.close() + context.term() + + +def validate_events(events): + """Validate that all events are valid JSON objects.""" + for i, event in enumerate(events): + if not isinstance(event, dict): + print(f"Error: Event {i} is not a JSON object: {type(event)}") + return False + + # Check for required fields (based on dftracer format) + required_fields = ["name", "cat", "ph"] + for field in required_fields: + if field not in event: + print(f"Warning: Event {i} missing field '{field}'") + # Not a hard error, just warning + + return True + + +def main(): + parser = argparse.ArgumentParser(description="Check ZMQ Sink for DFTracer testing") + parser.add_argument("test_name", help="Name of the test (for logging)") + parser.add_argument( + "expected_count", + type=int, + help="Minimum number of events expected (0 = expect no events)", + ) + parser.add_argument( + "--control-port", + type=int, + default=5556, + help="Control port for ZMQ sink (default: 5556)", + ) + parser.add_argument( + "--no-clear", action="store_true", help="Don't clear events after checking" + ) + args = parser.parse_args() + + print(f"Checking ZMQ sink for test '{args.test_name}'...") + print(f"Expected at least {args.expected_count} events") + + # Get event count + response = send_command(args.control_port, {"cmd": "count"}) + if response is None: + print("Error: Failed to get event count from sink") + sys.exit(1) + + count = response.get("count", 0) + print(f"Found {count} events in sink") + + # Handle expected_count == 0 case (disabled test) + if args.expected_count == 0: + if count == 0: + print("Success: Found 0 events as expected") + sys.exit(0) + else: + print(f"Failure: Expected 0 events, found {count}") + # Get and print events for debugging + events_response = send_command(args.control_port, {"cmd": "get_events"}) + if events_response: + print( + "Events found:", + json.dumps(events_response.get("events", []), indent=2), + ) + sys.exit(1) + + # Check if we have enough events + if count < args.expected_count: + print(f"Failure: Expected at least {args.expected_count} events, found {count}") + sys.exit(1) + + # Get events for validation + events_response = send_command(args.control_port, {"cmd": "get_events"}) + if events_response is None: + print("Error: Failed to get events from sink") + sys.exit(1) + + events = events_response.get("events", []) + + # Validate events + if not validate_events(events): + print("Failure: Event validation failed") + sys.exit(1) + + print(f"Success: Validated {count} events (>= {args.expected_count})") + + # Clear events for next test + if not args.no_clear: + clear_response = send_command(args.control_port, {"cmd": "clear"}) + if clear_response is None or clear_response.get("status") != "ok": + print("Warning: Failed to clear events from sink") + else: + print("Cleared events from sink") + + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/test/zmq_sink.py b/test/zmq_sink.py new file mode 100755 index 00000000..18629bed --- /dev/null +++ b/test/zmq_sink.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +""" +ZMQ Sink Process for DFTracer Testing + +This script runs a persistent ZeroMQ sink that: +1. Receives events on a PULL socket (port 5555) +2. Accepts control commands on a REP socket (port 5556) + +Control commands (JSON): +- {"cmd": "count"} -> {"count": N} +- {"cmd": "get_events"} -> {"events": [...]} +- {"cmd": "clear"} -> {"status": "ok"} +- {"cmd": "stop"} -> {"status": "stopping"} +""" + +import sys +import os +import json +import signal +import argparse +import threading +import time +import zmq + + +class ZMQSink: + def __init__(self, event_port=5555, control_port=5556): + self.event_port = event_port + self.control_port = control_port + self.events = [] + self.events_lock = threading.Lock() + self.running = True + self.context = None + self.event_socket = None + self.control_socket = None + + def setup_sockets(self): + self.context = zmq.Context() + + # PULL socket for receiving events + self.event_socket = self.context.socket(zmq.PULL) + self.event_socket.bind(f"tcp://*:{self.event_port}") + print(f"ZMQ Sink: Event socket bound to tcp://*:{self.event_port}") + + # REP socket for control commands + self.control_socket = self.context.socket(zmq.REP) + self.control_socket.bind(f"tcp://*:{self.control_port}") + print(f"ZMQ Sink: Control socket bound to tcp://*:{self.control_port}") + + def handle_event(self): + """Receive and store an event from the PULL socket.""" + try: + # Receive raw data - may contain multiple JSON lines + message = self.event_socket.recv(flags=zmq.NOBLOCK) + data = message.decode("utf-8") + + # Split by newlines and parse each JSON line + with self.events_lock: + for line in data.strip().split("\n"): + if line.strip(): + try: + event = json.loads(line) + self.events.append(event) + except json.JSONDecodeError as e: + print(f"ZMQ Sink: Error parsing JSON: {e}", file=sys.stderr) + return True + except zmq.Again: + return False + except Exception as e: + print(f"ZMQ Sink: Error receiving event: {e}", file=sys.stderr) + return False + + def handle_control(self): + """Handle a control command from the REP socket.""" + try: + message = self.control_socket.recv_json(flags=zmq.NOBLOCK) + cmd = message.get("cmd", "") + + if cmd == "count": + with self.events_lock: + count = len(self.events) + self.control_socket.send_json({"count": count}) + + elif cmd == "get_events": + with self.events_lock: + events = list(self.events) + self.control_socket.send_json({"events": events}) + + elif cmd == "clear": + with self.events_lock: + self.events.clear() + self.control_socket.send_json({"status": "ok"}) + + elif cmd == "stop": + self.control_socket.send_json({"status": "stopping"}) + self.running = False + + else: + self.control_socket.send_json({"error": f"Unknown command: {cmd}"}) + + return True + except zmq.Again: + return False + except Exception as e: + print(f"ZMQ Sink: Error handling control: {e}", file=sys.stderr) + return False + + def run(self): + """Main event loop using polling.""" + self.setup_sockets() + + poller = zmq.Poller() + poller.register(self.event_socket, zmq.POLLIN) + poller.register(self.control_socket, zmq.POLLIN) + + print("ZMQ Sink: Starting main loop...") + + while self.running: + try: + socks = dict(poller.poll(timeout=100)) # 100ms timeout + + if self.event_socket in socks: + self.handle_event() + + if self.control_socket in socks: + self.handle_control() + + except KeyboardInterrupt: + print("ZMQ Sink: Interrupted") + break + except Exception as e: + print(f"ZMQ Sink: Error in main loop: {e}", file=sys.stderr) + + self.cleanup() + print("ZMQ Sink: Stopped") + + def cleanup(self): + """Clean up sockets and context.""" + if self.event_socket: + self.event_socket.close() + if self.control_socket: + self.control_socket.close() + if self.context: + self.context.term() + + +def main(): + parser = argparse.ArgumentParser(description="ZMQ Sink for DFTracer testing") + parser.add_argument( + "--event-port", + type=int, + default=5555, + help="Port for event PULL socket (default: 5555)", + ) + parser.add_argument( + "--control-port", + type=int, + default=5556, + help="Port for control REP socket (default: 5556)", + ) + args = parser.parse_args() + + sink = ZMQSink(event_port=args.event_port, control_port=args.control_port) + + # Handle SIGTERM gracefully + def signal_handler(signum, frame): + print("ZMQ Sink: Received signal to stop") + sink.running = False + + signal.signal(signal.SIGTERM, signal_handler) + signal.signal(signal.SIGINT, signal_handler) + + sink.run() + + +if __name__ == "__main__": + main() diff --git a/test/zmq_sink_start.sh b/test/zmq_sink_start.sh new file mode 100755 index 00000000..aa1f2ce8 --- /dev/null +++ b/test/zmq_sink_start.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Start the ZMQ sink process for testing +# Usage: zmq_sink_start.sh [event_port] [control_port] + +PYTHON_EXE=$1 +LOG_FILE=$2 +EVENT_PORT=${3:-5555} +CONTROL_PORT=${4:-5556} + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Kill any existing sink on these ports +pkill -f "zmq_sink.py.*--event-port ${EVENT_PORT}" 2>/dev/null || true + +# Start the sink in background +$PYTHON_EXE $SCRIPT_DIR/zmq_sink.py --event-port $EVENT_PORT --control-port $CONTROL_PORT > "$LOG_FILE" 2>&1 & +SINK_PID=$! + +# Save PID for later cleanup +echo $SINK_PID > "${LOG_FILE}.pid" + +# Wait for sink to be ready (poll control socket using ZMQ) +MAX_RETRIES=30 +RETRY_COUNT=0 +while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do + # Use Python to check if sink is up (ZMQ sockets need ZMQ protocol) + RESULT=$($PYTHON_EXE -c " +import zmq +import sys +ctx = zmq.Context() +sock = ctx.socket(zmq.REQ) +sock.setsockopt(zmq.RCVTIMEO, 100) +sock.setsockopt(zmq.SNDTIMEO, 100) +sock.connect('tcp://localhost:$CONTROL_PORT') +try: + sock.send_json({'cmd': 'count'}) + result = sock.recv_json() + print('OK') + sys.exit(0) +except: + sys.exit(1) +finally: + sock.close() + ctx.term() +" 2>/dev/null) + if [ "$RESULT" = "OK" ]; then + echo "ZMQ Sink started with PID $SINK_PID on event port $EVENT_PORT, control port $CONTROL_PORT" + exit 0 + fi + RETRY_COUNT=$((RETRY_COUNT + 1)) + sleep 0.1 +done + +echo "Failed to start ZMQ Sink" >&2 +exit 1 diff --git a/test/zmq_sink_stop.sh b/test/zmq_sink_stop.sh new file mode 100755 index 00000000..3628ee34 --- /dev/null +++ b/test/zmq_sink_stop.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Stop the ZMQ sink process +# Usage: zmq_sink_stop.sh + +CONTROL_PORT=${1:-5556} + +# Send stop command via control socket +echo '{"cmd": "stop"}' | timeout 5 nc -q 1 localhost $CONTROL_PORT > /dev/null 2>&1 + +# Give it a moment to shut down gracefully +sleep 0.5 + +# Force kill if still running +pkill -f "zmq_sink.py" 2>/dev/null || true + +echo "ZMQ Sink stopped" +exit 0 From 3804866a30f0d8a5db1946dad9af291e228f8c41 Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Sun, 22 Feb 2026 15:43:49 -0800 Subject: [PATCH 30/33] feat(tests): enhance dlio_benchmark tests with fixture requirements for Mofka and ZMQ writers --- test/CMakeLists.txt | 13 ++++----- test/dlio_benchmark/CMakeLists.txt | 42 +++++++++++++++++++----------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7342a5d3..3db3faae 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,7 @@ set_property(GLOBAL PROPERTY COVERAGE_FILES "") include_directories(${DFTRACER_PROJECT_DIR}/include) +set(DFTRACER_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(MOFKA_GROUP_FILE "${CMAKE_CURRENT_BINARY_DIR}/mofka.group.json") set(MOFKA_SERVER_FIXTURE "MOFKA_SERVER") @@ -39,23 +40,23 @@ endfunction() function(df_check_test test_name expected_count) if(DFTRACER_WRITER_TYPE_MOFKA) df_add_test(check_${test_name} - ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_mofka_topic.py ${test_name} ${expected_count}) + ${DFTRACER_PYTHON_EXE} ${DFTRACER_TEST_DIR}/check_mofka_topic.py ${test_name} ${expected_count}) set_tests_properties(check_${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${MOFKA_GROUP_FILE}) set_property(TEST check_${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) elseif(DFTRACER_WRITER_TYPE_ZMQ) df_add_test(check_${test_name} - ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_zmq_sink.py ${test_name} ${expected_count} --control-port ${ZMQ_CONTROL_PORT}) + ${DFTRACER_PYTHON_EXE} ${DFTRACER_TEST_DIR}/check_zmq_sink.py ${test_name} ${expected_count} --control-port ${ZMQ_CONTROL_PORT}) set_tests_properties(check_${test_name} PROPERTIES FIXTURES_REQUIRED ${ZMQ_SINK_FIXTURE}) else() if(${expected_count} EQUAL 0) df_add_test(check_${test_name} - ${BASH_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_not.sh + ${BASH_EXE} ${DFTRACER_TEST_DIR}/check_file_not.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* ) else() df_add_test(check_${test_name} - ${BASH_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/check_file_at_least.sh + ${BASH_EXE} ${DFTRACER_TEST_DIR}/check_file_at_least.sh ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* ${expected_count} ) endif() @@ -328,7 +329,7 @@ df_check_test(${test_name} 71) # ######################################################################## set(TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/util.h) -if(ENABLE_DLIO_BENCHMARK_TESTS) +if(DFTRACER_ENABLE_DLIO_BENCHMARK_TESTS) set(test_name python_test_py_disable_only) df_add_test(${test_name} ${DFTRACER_PYTHON_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/py/python_test.py --format=npz) set_common_properties(${test_name}) @@ -368,7 +369,7 @@ if(ENABLE_DLIO_BENCHMARK_TESTS) add_subdirectory(dlio_benchmark) endif() -if(ENABLE_PAPER_TESTS) +if(DFTRACER_ENABLE_PAPER_TESTS) add_subdirectory(paper) endif() diff --git a/test/dlio_benchmark/CMakeLists.txt b/test/dlio_benchmark/CMakeLists.txt index 0a779921..dfeb7589 100644 --- a/test/dlio_benchmark/CMakeLists.txt +++ b/test/dlio_benchmark/CMakeLists.txt @@ -1,7 +1,7 @@ set(DLIO_BENCHMARK_EXE ${MAIN_PYTHON_SITE_PACKAGES}/dlio_benchmark/main.py) message("-- Found dlio_benchmark at location " ${DLIO_BENCHMARK_EXE}) find_program(PYTHON_EXE python) -set(COMMON_ARGS workload=unet3d ++workload.train.computation_time=0.05 +set(COMMON_ARGS workload=unet3d_v100 ++workload.train.computation_time=0.05 ++workload.evaluation.eval_time=0.01 ++workload.train.epochs=2 ++workload.workflow.train=True ++workload.workflow.generate_data=True ++workload.dataset.num_files_train=16 ++workload.dataset.num_files_eval=16 ++workload.reader.read_threads=2 @@ -12,18 +12,30 @@ set(lines 2055 1159 715 935 903) list(LENGTH formats formats_length) math(EXPR formats_length "${formats_length} - 1") message(STATUS "Number of formats: ${formats_length}") -foreach (index RANGE ${formats_length}) - list(GET formats ${index} format) - list(GET lines ${index} line) - set(test_name dlio_${format}) - df_add_test(${test_name} ${PYTHON_EXE} ${DLIO_BENCHMARK_EXE} ${COMMON_ARGS} ++workload.dataset.format=${format} - ++workload.output.folder=${CMAKE_CURRENT_BINARY_DIR}/output_${format}) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=1) - #set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_FILE=${CMAKE_CURRENT_BINARY_DIR}/output_${format}/trace) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=INFO) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_TRACE_COMPRESSION=0) - df_add_test(${test_name}_check_file_exists ${BASH_PROGRAM} ${CMAKE_SOURCE_DIR}/test/check_file.sh ${CMAKE_CURRENT_BINARY_DIR}/output_${format}/.trace*.pfw* ${line}) - set_tests_properties(${test_name}_check_file_exists PROPERTIES DEPENDS ${test_name}) -endforeach () +foreach(index RANGE ${formats_length}) + list(GET formats ${index} format) + list(GET lines ${index} line) + set(test_name dlio_${format}) + df_add_test(${test_name} ${PYTHON_EXE} ${DLIO_BENCHMARK_EXE} ${COMMON_ARGS} ++workload.dataset.format=${format} + ++workload.output.folder=${CMAKE_CURRENT_BINARY_DIR}/output_${format}) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ENABLE=1) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_LOG_LEVEL=INFO) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_TRACE_COMPRESSION=0) + + # Add fixture requirements for streaming writers + if(DFTRACER_WRITER_TYPE_MOFKA) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_GROUP_FILE=${MOFKA_GROUP_FILE}) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_MOFKA_TOPIC_NAME=${test_name}) + set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${MOFKA_SERVER_FIXTURE}) + endif() + + if(DFTRACER_WRITER_TYPE_ZMQ) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_ZMQ_ENDPOINT=tcp://localhost:${ZMQ_EVENT_PORT}) + set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${ZMQ_SINK_FIXTURE}) + endif() + + # Use df_check_test for all writer types (handles STDIO, Mofka, ZMQ) + df_check_test(${test_name} ${line}) +endforeach() From 8b5349f20d1ab2d117d9a484e075a74592f0132f Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Mon, 2 Mar 2026 14:57:19 -0800 Subject: [PATCH 31/33] feat(writer): implement control hooks in MofkaWriter for event handling --- src/dftracer/core/buffer/buffer.cpp | 13 + src/dftracer/core/buffer/buffer.h | 10 +- src/dftracer/core/common/utils.h | 45 +++ src/dftracer/core/writer/mofka_writer.cpp | 299 +++++++++++++++++++- src/dftracer/core/writer/mofka_writer.h | 11 + src/dftracer/core/writer/writer_interface.h | 11 + 6 files changed, 373 insertions(+), 16 deletions(-) create mode 100644 src/dftracer/core/common/utils.h diff --git a/src/dftracer/core/buffer/buffer.cpp b/src/dftracer/core/buffer/buffer.cpp index 9ca48466..044545da 100644 --- a/src/dftracer/core/buffer/buffer.cpp +++ b/src/dftracer/core/buffer/buffer.cpp @@ -60,6 +60,7 @@ int BufferManager::initialize(const char* filename, HashType hostname_hash) { dftracer::Singleton::get_instance()); #endif this->writer->initialize(filename); + this->control_hooks_enabled = this->writer->control_hooks_enabled(); this->serializer = dftracer::Singleton::get_instance(); this->aggregator = dftracer::Singleton::get_instance(); if (this->config->compression) { @@ -106,6 +107,10 @@ void BufferManager::log_data_event(int index, ConstEventNameType event_name, ProcessID process_id, ThreadID tid) { std::unique_lock lock(mtx); DFTRACER_LOG_DEBUG("BufferManager.log_data_event %d", index); + if (this->control_hooks_enabled) { + this->writer->before_write( + dftracer::EventContext{event_name, category, "X", process_id, tid}); + } size_t size = 0; bool enable_tracing = true; if (this->config->aggregation_enable && strcmp(category, "dftracer") != 0) { @@ -142,6 +147,10 @@ void BufferManager::log_counter_event(int index, ConstEventNameType name, dftracer::Metadata* metadata) { std::unique_lock lock(mtx); DFTRACER_LOG_DEBUG("BufferManager.log_counter_event %d", index); + if (this->control_hooks_enabled) { + this->writer->before_write( + dftracer::EventContext{name, category, "C", process_id, thread_id}); + } size_t size = this->serializer->counter(buffer + buffer_pos, index, name, category, start_time, process_id, thread_id, metadata); @@ -155,6 +164,10 @@ void BufferManager::log_metadata_event(ConstEventNameType name, bool is_string) { std::unique_lock lock(mtx); DFTRACER_LOG_DEBUG("BufferManager.log_metadata_event %s", value); + if (this->control_hooks_enabled) { + this->writer->before_write( + dftracer::EventContext{ph, "dftracer", "M", process_id, tid}); + } size_t size = this->serializer->metadata(buffer + buffer_pos, name, value, ph, process_id, tid, is_string); compress_and_write_if_needed(size); diff --git a/src/dftracer/core/buffer/buffer.h b/src/dftracer/core/buffer/buffer.h index accbd792..b7ae284c 100644 --- a/src/dftracer/core/buffer/buffer.h +++ b/src/dftracer/core/buffer/buffer.h @@ -20,7 +20,12 @@ namespace dftracer { class BufferManager { public: BufferManager() - : buffer(nullptr), buffer_pos(0), mtx(), app_name(), rank(-1) {} + : buffer(nullptr), + buffer_pos(0), + mtx(), + app_name(), + rank(-1), + control_hooks_enabled(false) {} ~BufferManager() {} void inline set_app_name(const char* name) { app_name = name; } @@ -56,6 +61,7 @@ class BufferManager { std::shared_mutex mtx; std::string app_name; int rank; + bool control_hooks_enabled; std::shared_ptr config; std::shared_ptr serializer; @@ -64,4 +70,4 @@ class BufferManager { std::shared_ptr aggregator; }; } // namespace dftracer -#endif // DFTRACER_BUFFER_H \ No newline at end of file +#endif // DFTRACER_BUFFER_H diff --git a/src/dftracer/core/common/utils.h b/src/dftracer/core/common/utils.h new file mode 100644 index 00000000..6b071d5e --- /dev/null +++ b/src/dftracer/core/common/utils.h @@ -0,0 +1,45 @@ +#ifndef DFTRACER_COMMON_UTILS_H +#define DFTRACER_COMMON_UTILS_H + +#include +#include +#include +#include +#include + +namespace dftracer { + +inline bool parse_positive_size_t(const char* value, size_t* parsed) { + if (!value || !parsed || value[0] == '\0') return false; + + errno = 0; + char* end = nullptr; + unsigned long long v = std::strtoull(value, &end, 10); + if (errno != 0 || end == value || *end != '\0' || v == 0 || + v > std::numeric_limits::max()) { + return false; + } + + *parsed = static_cast(v); + return true; +} + +inline std::string trim_copy(const std::string& value) { + if (value.empty()) return value; + size_t first = 0; + while (first < value.size() && + std::isspace(static_cast(value[first]))) { + ++first; + } + if (first == value.size()) return std::string{}; + size_t last = value.size() - 1; + while (last > first && + std::isspace(static_cast(value[last]))) { + --last; + } + return value.substr(first, last - first + 1); +} + +} // namespace dftracer + +#endif // DFTRACER_COMMON_UTILS_H diff --git a/src/dftracer/core/writer/mofka_writer.cpp b/src/dftracer/core/writer/mofka_writer.cpp index 60ed968e..39b7874a 100644 --- a/src/dftracer/core/writer/mofka_writer.cpp +++ b/src/dftracer/core/writer/mofka_writer.cpp @@ -1,14 +1,74 @@ #include #include +#include #include #include -#include +#include +#include +#include #include #include +#include +#include #include +#include +#include +#include namespace dftracer { +namespace { + +bool parse_ordering(const char* value, diaspora::Ordering* ordering) { + if (!value || !ordering) return false; + if (std::strcmp(value, "strict") == 0 || std::strcmp(value, "STRICT") == 0) { + *ordering = diaspora::Ordering::Strict; + return true; + } + if (std::strcmp(value, "loose") == 0 || std::strcmp(value, "LOOSE") == 0) { + *ordering = diaspora::Ordering::Loose; + return true; + } + return false; +} + +void parse_control_event_names(const char* value, + std::vector* names) { + if (!names) return; + names->clear(); + if (!value) return; + std::stringstream ss(value); + std::string token; + while (std::getline(ss, token, ',')) { + auto trimmed = trim_copy(token); + if (!trimmed.empty()) names->push_back(std::move(trimmed)); + } +} + +bool is_control_trigger_event( + ConstEventNameType event_name, + const std::vector& control_trigger_event_names) { + if (!event_name || event_name[0] == '\0') return false; + for (const auto& trigger_name : control_trigger_event_names) { + if (std::strcmp(event_name, trigger_name.c_str()) == 0) return true; + } + return false; +} + +void ensure_topic_exists(diaspora::Driver* driver, + const std::string& topic_name) { + if (!driver) return; + if (driver->topicExists(topic_name)) return; + diaspora::Validator validator; + diaspora::Serializer serializer; + diaspora::PartitionSelector selector; + driver->createTopic(topic_name, diaspora::Metadata{}, validator, selector, + serializer); + driver->as().addMemoryPartition(topic_name, 0); +} + +} // namespace + template <> std::shared_ptr Singleton::instance = nullptr; template <> @@ -27,6 +87,10 @@ void MofkaWriter::initialize(const char* filename) { group_file_ = group_file_env; const char* topic_name_env = std::getenv("DFTRACER_MOFKA_TOPIC_NAME"); topic_name_ = topic_name_env ? topic_name_env : "dftracer_events"; + trace_events_written_ = 0; + control_hooks_enabled_ = false; + control_trigger_event_names_.clear(); + control_topic_name_.clear(); // Allow Mofka/Mercury to access this process's memory for shared memory // transport @@ -46,15 +110,10 @@ void MofkaWriter::initialize(const char* filename) { DFTRACER_LOG_INFO("Mofka driver initialized", ""); if (driver_->topicExists(topic_name_)) { - DFTRACER_LOG_INFO("Mofka topic exists", ""); + DFTRACER_LOG_INFO("Mofka trace topic exists", ""); } else { - diaspora::Validator validator; - diaspora::Serializer serializer; - diaspora::PartitionSelector selector; - driver_->createTopic(topic_name_, diaspora::Metadata{}, validator, - selector, serializer); - driver_->as().addMemoryPartition(topic_name_, 0); - DFTRACER_LOG_INFO("Mofka topic created", ""); + ensure_topic_exists(driver_.get(), topic_name_); + DFTRACER_LOG_INFO("Mofka trace topic created", ""); } topic_ = std::make_unique( @@ -62,12 +121,166 @@ void MofkaWriter::initialize(const char* filename) { DFTRACER_LOG_INFO("Mofka topic opened", ""); diaspora::BatchSize batchSize = diaspora::BatchSize::Adaptive(); - diaspora::ThreadCount threadCount = diaspora::ThreadCount{1}; + const char* batch_size_env_name = "DFTRACER_MOFKA_PRODUCER_BATCH_SIZE"; + const char* batch_size_env = std::getenv(batch_size_env_name); + size_t parsed_batch_size = 0; + if (batch_size_env) { + if (parse_positive_size_t(batch_size_env, &parsed_batch_size)) { + batchSize = diaspora::BatchSize{parsed_batch_size}; + DFTRACER_LOG_INFO("Mofka producer batch size set from %s=%zu", + batch_size_env_name, parsed_batch_size); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; using Adaptive batch size", + batch_size_env_name, batch_size_env); + } + } + + diaspora::MaxNumBatches max_num_batches = diaspora::MaxNumBatches{2}; + const char* max_num_batches_env_name = + "DFTRACER_MOFKA_PRODUCER_MAX_NUM_BATCHES"; + const char* max_num_batches_env = std::getenv(max_num_batches_env_name); + size_t parsed_max_num_batches = 0; + if (max_num_batches_env) { + if (parse_positive_size_t(max_num_batches_env, + &parsed_max_num_batches)) { + max_num_batches = diaspora::MaxNumBatches{ + static_cast(parsed_max_num_batches)}; + DFTRACER_LOG_INFO("Mofka producer max num batches set from %s=%zu", + max_num_batches_env_name, parsed_max_num_batches); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; using default of 2", + max_num_batches_env_name, max_num_batches_env); + } + } + diaspora::Ordering ordering = diaspora::Ordering::Strict; - producer_ = std::make_unique( - topic_->producer("dftracer", batchSize, threadCount, ordering)); + const char* ordering_env_name = "DFTRACER_MOFKA_PRODUCER_ORDERING"; + const char* ordering_env = std::getenv(ordering_env_name); + if (ordering_env) { + if (parse_ordering(ordering_env, &ordering)) { + DFTRACER_LOG_INFO("Mofka producer ordering set from %s=%s", + ordering_env_name, ordering_env); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; using strict ordering", + ordering_env_name, ordering_env); + } + } + + const char* producer_thread_count_env_name = + "DFTRACER_MOFKA_PRODUCER_THREAD_COUNT"; + const char* producer_thread_count_env = + std::getenv(producer_thread_count_env_name); + size_t producer_thread_count = 0; + diaspora::ThreadPool producer_thread_pool{}; + if (producer_thread_count_env) { + if (parse_positive_size_t(producer_thread_count_env, + &producer_thread_count)) { + producer_thread_pool = driver_->makeThreadPool( + diaspora::ThreadCount{producer_thread_count}); + DFTRACER_LOG_INFO("Mofka producer thread count set from %s=%zu", + producer_thread_count_env_name, + producer_thread_count); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; using default thread pool", + producer_thread_count_env_name, + producer_thread_count_env); + } + } + + const char* flush_every_n_writes_env_name = + "DFTRACER_MOFKA_PRODUCER_FLUSH_EVERY_N_WRITES"; + const char* flush_every_n_writes_env = + std::getenv(flush_every_n_writes_env_name); + size_t parsed_flush_every_n_writes = 0; + flush_every_n_writes_ = 0; + writes_since_flush_ = 0; + if (flush_every_n_writes_env) { + if (parse_positive_size_t(flush_every_n_writes_env, + &parsed_flush_every_n_writes)) { + flush_every_n_writes_ = parsed_flush_every_n_writes; + DFTRACER_LOG_INFO("Mofka periodic flush set from %s=%zu", + flush_every_n_writes_env_name, + parsed_flush_every_n_writes); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; disabling periodic flush", + flush_every_n_writes_env_name, + flush_every_n_writes_env); + } + } + + const char* control_topic_env_name = "DFTRACER_MOFKA_CONTROL_TOPIC_NAME"; + const char* control_topic_env = std::getenv(control_topic_env_name); + if (control_topic_env && control_topic_env[0] != '\0') { + control_topic_name_ = control_topic_env; + } else { + control_topic_name_ = "control_events"; + DFTRACER_LOG_INFO("%s unset; defaulting to %s", control_topic_env_name, + control_topic_name_.c_str()); + } + + const char* control_event_names_env_name = + "DFTRACER_MOFKA_CONTROL_EVENT_NAMES"; + const char* control_event_names_env = + std::getenv(control_event_names_env_name); + if (control_event_names_env) { + parse_control_event_names(control_event_names_env, + &control_trigger_event_names_); + if (control_trigger_event_names_.empty()) { + DFTRACER_LOG_WARN( + "%s is set but empty; control-event producer disabled", + control_event_names_env_name); + } else { + DFTRACER_LOG_INFO("Mofka control trigger names loaded from %s", + control_event_names_env_name); + } + } else { + // Default trigger names to avoid requiring extra env setup. + control_trigger_event_names_.push_back("epoch.start"); + control_trigger_event_names_.push_back("epoch.block"); + DFTRACER_LOG_INFO( + "%s unset; defaulting control-event triggers to " + "epoch.start,epoch.block", + control_event_names_env_name); + } + + if (producer_thread_pool) { + producer_ = std::make_unique( + topic_->producer("dftracer", batchSize, max_num_batches, ordering, + producer_thread_pool)); + } else { + producer_ = std::make_unique( + topic_->producer("dftracer", batchSize, max_num_batches, ordering)); + } DFTRACER_LOG_INFO("Mofka producer created", ""); + if (!control_trigger_event_names_.empty()) { + if (driver_->topicExists(control_topic_name_)) { + DFTRACER_LOG_INFO("Mofka control topic exists", ""); + } else { + ensure_topic_exists(driver_.get(), control_topic_name_); + DFTRACER_LOG_INFO("Mofka control topic created", ""); + } + control_topic_ = std::make_unique( + driver_->openTopic(control_topic_name_)); + + const diaspora::BatchSize control_batch_size{1}; + const diaspora::Ordering control_ordering = diaspora::Ordering::Strict; + if (producer_thread_pool) { + control_producer_ = + std::make_unique(control_topic_->producer( + "dftracer_control", control_batch_size, max_num_batches, + control_ordering, producer_thread_pool)); + } else { + control_producer_ = std::make_unique( + control_topic_->producer("dftracer_control", control_batch_size, + max_num_batches, control_ordering)); + } + DFTRACER_LOG_INFO( + "Mofka control producer enabled: topic=%s trigger_count=%zu", + control_topic_name_.c_str(), control_trigger_event_names_.size()); + control_hooks_enabled_ = true; + } + init_pid_ = getpid(); DFTRACER_LOG_INFO("MofkaWriter initialized with PID %d", init_pid_); } catch (const std::exception& e) { @@ -77,13 +290,55 @@ void MofkaWriter::initialize(const char* filename) { } } +void MofkaWriter::before_write(const EventContext& event) { + if (!control_producer_) return; + if (!is_control_trigger_event(event.event_name, control_trigger_event_names_)) + return; + try { + const auto now_ns = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + diaspora::Metadata control_metadata; + control_metadata.json()["type"] = "boundary_event"; + control_metadata.json()["trace_topic"] = topic_name_; + control_metadata.json()["control_topic"] = control_topic_name_; + control_metadata.json()["events_written"] = trace_events_written_ + 1; + control_metadata.json()["trigger_event_name"] = event.event_name; + control_metadata.json()["trigger_category"] = + event.category ? event.category : ""; + control_metadata.json()["trigger_phase"] = event.phase ? event.phase : ""; + control_metadata.json()["pid"] = event.process_id; + control_metadata.json()["tid"] = + static_cast(event.thread_id); + control_metadata.json()["ts_unix_ns"] = now_ns; + control_producer_->push(std::move(control_metadata), diaspora::DataView{}); + } catch (const std::exception& e) { + DFTRACER_LOG_WARN("Mofka control event push failed: %s", e.what()); + } +} + size_t MofkaWriter::write(const char* data, size_t len, bool force) { if (!topic_) { DFTRACER_LOG_ERROR("Mofka topic not initialized", ""); return 0; } try { - producer_->push(diaspora::Metadata{data}, diaspora::DataView{}); + // Use string_view with explicit length and parse=false to store raw data + // without JSON parsing (which would fail on binary data with null bytes) + std::string_view data_view(data, len); + producer_->push(diaspora::Metadata{data_view, false}, diaspora::DataView{}); + ++trace_events_written_; + + if (flush_every_n_writes_ > 0) { + ++writes_since_flush_; + if (writes_since_flush_ >= flush_every_n_writes_) { + producer_->flush().wait(-1); + if (control_producer_) { + control_producer_->flush().wait(-1); + } + writes_since_flush_ = 0; + } + } return len; } catch (const std::exception& e) { DFTRACER_LOG_ERROR("Mofka write failed", e.what()); @@ -104,20 +359,36 @@ void MofkaWriter::finalize(int index) { if (producer_) { producer_.release(); } + if (control_producer_) { + control_producer_.release(); + } if (topic_) { topic_.release(); } + if (control_topic_) { + control_topic_.release(); + } if (driver_) { driver_.release(); } return; } + if (control_producer_) { + control_producer_->flush().wait(-1); + DFTRACER_LOG_INFO("Mofka control producer flushed", ""); + control_producer_.reset(); + DFTRACER_LOG_INFO("Mofka control producer reset", ""); + } if (producer_) { producer_->flush().wait(-1); DFTRACER_LOG_INFO("Mofka producer flushed", ""); producer_.reset(); DFTRACER_LOG_INFO("Mofka producer reset", ""); } + if (control_topic_) { + control_topic_.reset(); + DFTRACER_LOG_INFO("Mofka control topic reset", ""); + } if (topic_) { topic_.reset(); DFTRACER_LOG_INFO("Mofka topic reset", ""); @@ -128,4 +399,4 @@ void MofkaWriter::finalize(int index) { } } -} // namespace dftracer \ No newline at end of file +} // namespace dftracer diff --git a/src/dftracer/core/writer/mofka_writer.h b/src/dftracer/core/writer/mofka_writer.h index 1c272fcd..290dbed6 100644 --- a/src/dftracer/core/writer/mofka_writer.h +++ b/src/dftracer/core/writer/mofka_writer.h @@ -7,6 +7,7 @@ #include #include #include +#include namespace dftracer { @@ -14,16 +15,26 @@ class MofkaWriter : public WriterInterface { private: std::string group_file_; std::string topic_name_; + std::string control_topic_name_; std::unique_ptr driver_; std::unique_ptr producer_; + std::unique_ptr control_producer_; std::unique_ptr topic_; + std::unique_ptr control_topic_; pid_t init_pid_ = 0; + size_t flush_every_n_writes_ = 0; + size_t writes_since_flush_ = 0; + size_t trace_events_written_ = 0; + bool control_hooks_enabled_ = false; + std::vector control_trigger_event_names_; public: MofkaWriter(); ~MofkaWriter() override; void initialize(const char* filename) override; + bool control_hooks_enabled() const override { return control_hooks_enabled_; } + void before_write(const EventContext& event) override; size_t write(const char* data, size_t len, bool force = false) override; void finalize(int index) override; }; diff --git a/src/dftracer/core/writer/writer_interface.h b/src/dftracer/core/writer/writer_interface.h index b275b1c3..59dcb7bb 100644 --- a/src/dftracer/core/writer/writer_interface.h +++ b/src/dftracer/core/writer/writer_interface.h @@ -2,11 +2,22 @@ #define DFTRACER_WRITER_INTERFACE_H #include +#include namespace dftracer { +struct EventContext { + ConstEventNameType event_name; + ConstEventNameType category; + ConstEventNameType phase; + ProcessID process_id; + ThreadID thread_id; +}; + class WriterInterface { public: virtual void initialize(const char* filename) = 0; + virtual bool control_hooks_enabled() const { return false; } + virtual void before_write(const EventContext& event) {} virtual size_t write(const char* data, size_t len, bool force = false) = 0; virtual void finalize(int index) = 0; virtual ~WriterInterface() = default; From 3faf8f835d41f84d8169af08f584b43b14ad134b Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Tue, 3 Mar 2026 13:37:25 -0800 Subject: [PATCH 32/33] fix(dependencies): update pydftracer to use specific git repository for lazy imports --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 63b771b6..c0fd859a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ dependencies = [ "setuptools>=64", "setuptools-scm>=8", "dftracer-utils>=0.0.5", - "pydftracer>=2.0.2", + "pydftracer @ git+https://github.com/izzet/pydftracer.git@fix/lazy-dynamo-imports", ] [project.urls] From 149d37318f8870712328c3c7f62ff2b2d6aa4cef Mon Sep 17 00:00:00 2001 From: Izzet Yildirim Date: Fri, 6 Mar 2026 15:14:54 -0800 Subject: [PATCH 33/33] feat(writer): support forked child processes in MofkaWriter Detect fork via pid mismatch and rebuild Mofka driver/producer state in child processes. This allows PyTorch DataLoader workers (forked from the main process) to send POSIX I/O events through Mofka mid-run. Previously, forked children inherited stale Mofka connections that silently failed, so only main-process events were captured. --- src/dftracer/core/writer/mofka_writer.cpp | 363 +++++++++++----------- 1 file changed, 188 insertions(+), 175 deletions(-) diff --git a/src/dftracer/core/writer/mofka_writer.cpp b/src/dftracer/core/writer/mofka_writer.cpp index 39b7874a..e9bfea39 100644 --- a/src/dftracer/core/writer/mofka_writer.cpp +++ b/src/dftracer/core/writer/mofka_writer.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace dftracer { @@ -87,206 +88,220 @@ void MofkaWriter::initialize(const char* filename) { group_file_ = group_file_env; const char* topic_name_env = std::getenv("DFTRACER_MOFKA_TOPIC_NAME"); topic_name_ = topic_name_env ? topic_name_env : "dftracer_events"; - trace_events_written_ = 0; - control_hooks_enabled_ = false; - control_trigger_event_names_.clear(); - control_topic_name_.clear(); + auto current_pid = getpid(); // Allow Mofka/Mercury to access this process's memory for shared memory // transport // prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0); if (driver_) { - DFTRACER_LOG_INFO("MofkaWriter already initialized", ""); - } else { - try { - diaspora::Metadata options; - options.json()["group_file"] = group_file_; - options.json()["margo"] = nlohmann::json::object(); - options.json()["margo"]["use_progress_thread"] = true; - - driver_ = std::make_unique( - diaspora::Driver::New("mofka", options)); - DFTRACER_LOG_INFO("Mofka driver initialized", ""); - - if (driver_->topicExists(topic_name_)) { - DFTRACER_LOG_INFO("Mofka trace topic exists", ""); + if (init_pid_ == current_pid) { + DFTRACER_LOG_INFO("MofkaWriter already initialized", ""); + return; + } + DFTRACER_LOG_INFO( + "Detected forked child; rebuilding MofkaWriter state (parent pid=%d, " + "child pid=%d)", + init_pid_, current_pid); + (void)control_producer_.release(); + (void)producer_.release(); + (void)control_topic_.release(); + (void)topic_.release(); + (void)driver_.release(); + } + + trace_events_written_ = 0; + control_hooks_enabled_ = false; + control_trigger_event_names_.clear(); + control_topic_name_.clear(); + + try { + diaspora::Metadata options; + options.json()["group_file"] = group_file_; + options.json()["margo"] = nlohmann::json::object(); + options.json()["margo"]["use_progress_thread"] = true; + + driver_ = std::make_unique( + diaspora::Driver::New("mofka", options)); + DFTRACER_LOG_INFO("Mofka driver initialized", ""); + + if (driver_->topicExists(topic_name_)) { + DFTRACER_LOG_INFO("Mofka trace topic exists", ""); + } else { + ensure_topic_exists(driver_.get(), topic_name_); + DFTRACER_LOG_INFO("Mofka trace topic created", ""); + } + + topic_ = std::make_unique( + driver_->openTopic(topic_name_)); + DFTRACER_LOG_INFO("Mofka topic opened", ""); + + diaspora::BatchSize batchSize = diaspora::BatchSize::Adaptive(); + const char* batch_size_env_name = "DFTRACER_MOFKA_PRODUCER_BATCH_SIZE"; + const char* batch_size_env = std::getenv(batch_size_env_name); + size_t parsed_batch_size = 0; + if (batch_size_env) { + if (parse_positive_size_t(batch_size_env, &parsed_batch_size)) { + batchSize = diaspora::BatchSize{parsed_batch_size}; + DFTRACER_LOG_INFO("Mofka producer batch size set from %s=%zu", + batch_size_env_name, parsed_batch_size); } else { - ensure_topic_exists(driver_.get(), topic_name_); - DFTRACER_LOG_INFO("Mofka trace topic created", ""); + DFTRACER_LOG_WARN("Invalid %s value '%s'; using Adaptive batch size", + batch_size_env_name, batch_size_env); } + } - topic_ = std::make_unique( - driver_->openTopic(topic_name_)); - DFTRACER_LOG_INFO("Mofka topic opened", ""); - - diaspora::BatchSize batchSize = diaspora::BatchSize::Adaptive(); - const char* batch_size_env_name = "DFTRACER_MOFKA_PRODUCER_BATCH_SIZE"; - const char* batch_size_env = std::getenv(batch_size_env_name); - size_t parsed_batch_size = 0; - if (batch_size_env) { - if (parse_positive_size_t(batch_size_env, &parsed_batch_size)) { - batchSize = diaspora::BatchSize{parsed_batch_size}; - DFTRACER_LOG_INFO("Mofka producer batch size set from %s=%zu", - batch_size_env_name, parsed_batch_size); - } else { - DFTRACER_LOG_WARN("Invalid %s value '%s'; using Adaptive batch size", - batch_size_env_name, batch_size_env); - } + diaspora::MaxNumBatches max_num_batches = diaspora::MaxNumBatches{2}; + const char* max_num_batches_env_name = + "DFTRACER_MOFKA_PRODUCER_MAX_NUM_BATCHES"; + const char* max_num_batches_env = std::getenv(max_num_batches_env_name); + size_t parsed_max_num_batches = 0; + if (max_num_batches_env) { + if (parse_positive_size_t(max_num_batches_env, + &parsed_max_num_batches)) { + max_num_batches = diaspora::MaxNumBatches{ + static_cast(parsed_max_num_batches)}; + DFTRACER_LOG_INFO("Mofka producer max num batches set from %s=%zu", + max_num_batches_env_name, parsed_max_num_batches); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; using default of 2", + max_num_batches_env_name, max_num_batches_env); } + } - diaspora::MaxNumBatches max_num_batches = diaspora::MaxNumBatches{2}; - const char* max_num_batches_env_name = - "DFTRACER_MOFKA_PRODUCER_MAX_NUM_BATCHES"; - const char* max_num_batches_env = std::getenv(max_num_batches_env_name); - size_t parsed_max_num_batches = 0; - if (max_num_batches_env) { - if (parse_positive_size_t(max_num_batches_env, - &parsed_max_num_batches)) { - max_num_batches = diaspora::MaxNumBatches{ - static_cast(parsed_max_num_batches)}; - DFTRACER_LOG_INFO("Mofka producer max num batches set from %s=%zu", - max_num_batches_env_name, parsed_max_num_batches); - } else { - DFTRACER_LOG_WARN("Invalid %s value '%s'; using default of 2", - max_num_batches_env_name, max_num_batches_env); - } + diaspora::Ordering ordering = diaspora::Ordering::Strict; + const char* ordering_env_name = "DFTRACER_MOFKA_PRODUCER_ORDERING"; + const char* ordering_env = std::getenv(ordering_env_name); + if (ordering_env) { + if (parse_ordering(ordering_env, &ordering)) { + DFTRACER_LOG_INFO("Mofka producer ordering set from %s=%s", + ordering_env_name, ordering_env); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; using strict ordering", + ordering_env_name, ordering_env); } + } - diaspora::Ordering ordering = diaspora::Ordering::Strict; - const char* ordering_env_name = "DFTRACER_MOFKA_PRODUCER_ORDERING"; - const char* ordering_env = std::getenv(ordering_env_name); - if (ordering_env) { - if (parse_ordering(ordering_env, &ordering)) { - DFTRACER_LOG_INFO("Mofka producer ordering set from %s=%s", - ordering_env_name, ordering_env); - } else { - DFTRACER_LOG_WARN("Invalid %s value '%s'; using strict ordering", - ordering_env_name, ordering_env); - } + const char* producer_thread_count_env_name = + "DFTRACER_MOFKA_PRODUCER_THREAD_COUNT"; + const char* producer_thread_count_env = + std::getenv(producer_thread_count_env_name); + size_t producer_thread_count = 0; + diaspora::ThreadPool producer_thread_pool{}; + if (producer_thread_count_env) { + if (parse_positive_size_t(producer_thread_count_env, + &producer_thread_count)) { + producer_thread_pool = driver_->makeThreadPool( + diaspora::ThreadCount{producer_thread_count}); + DFTRACER_LOG_INFO("Mofka producer thread count set from %s=%zu", + producer_thread_count_env_name, + producer_thread_count); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; using default thread pool", + producer_thread_count_env_name, + producer_thread_count_env); } + } - const char* producer_thread_count_env_name = - "DFTRACER_MOFKA_PRODUCER_THREAD_COUNT"; - const char* producer_thread_count_env = - std::getenv(producer_thread_count_env_name); - size_t producer_thread_count = 0; - diaspora::ThreadPool producer_thread_pool{}; - if (producer_thread_count_env) { - if (parse_positive_size_t(producer_thread_count_env, - &producer_thread_count)) { - producer_thread_pool = driver_->makeThreadPool( - diaspora::ThreadCount{producer_thread_count}); - DFTRACER_LOG_INFO("Mofka producer thread count set from %s=%zu", - producer_thread_count_env_name, - producer_thread_count); - } else { - DFTRACER_LOG_WARN("Invalid %s value '%s'; using default thread pool", - producer_thread_count_env_name, - producer_thread_count_env); - } + const char* flush_every_n_writes_env_name = + "DFTRACER_MOFKA_PRODUCER_FLUSH_EVERY_N_WRITES"; + const char* flush_every_n_writes_env = + std::getenv(flush_every_n_writes_env_name); + size_t parsed_flush_every_n_writes = 0; + flush_every_n_writes_ = 0; + writes_since_flush_ = 0; + if (flush_every_n_writes_env) { + if (parse_positive_size_t(flush_every_n_writes_env, + &parsed_flush_every_n_writes)) { + flush_every_n_writes_ = parsed_flush_every_n_writes; + DFTRACER_LOG_INFO("Mofka periodic flush set from %s=%zu", + flush_every_n_writes_env_name, + parsed_flush_every_n_writes); + } else { + DFTRACER_LOG_WARN("Invalid %s value '%s'; disabling periodic flush", + flush_every_n_writes_env_name, + flush_every_n_writes_env); } + } - const char* flush_every_n_writes_env_name = - "DFTRACER_MOFKA_PRODUCER_FLUSH_EVERY_N_WRITES"; - const char* flush_every_n_writes_env = - std::getenv(flush_every_n_writes_env_name); - size_t parsed_flush_every_n_writes = 0; - flush_every_n_writes_ = 0; - writes_since_flush_ = 0; - if (flush_every_n_writes_env) { - if (parse_positive_size_t(flush_every_n_writes_env, - &parsed_flush_every_n_writes)) { - flush_every_n_writes_ = parsed_flush_every_n_writes; - DFTRACER_LOG_INFO("Mofka periodic flush set from %s=%zu", - flush_every_n_writes_env_name, - parsed_flush_every_n_writes); - } else { - DFTRACER_LOG_WARN("Invalid %s value '%s'; disabling periodic flush", - flush_every_n_writes_env_name, - flush_every_n_writes_env); - } - } + const char* control_topic_env_name = "DFTRACER_MOFKA_CONTROL_TOPIC_NAME"; + const char* control_topic_env = std::getenv(control_topic_env_name); + if (control_topic_env && control_topic_env[0] != '\0') { + control_topic_name_ = control_topic_env; + } else { + control_topic_name_ = "control_events"; + DFTRACER_LOG_INFO("%s unset; defaulting to %s", control_topic_env_name, + control_topic_name_.c_str()); + } - const char* control_topic_env_name = "DFTRACER_MOFKA_CONTROL_TOPIC_NAME"; - const char* control_topic_env = std::getenv(control_topic_env_name); - if (control_topic_env && control_topic_env[0] != '\0') { - control_topic_name_ = control_topic_env; + const char* control_event_names_env_name = + "DFTRACER_MOFKA_CONTROL_EVENT_NAMES"; + const char* control_event_names_env = + std::getenv(control_event_names_env_name); + if (control_event_names_env) { + parse_control_event_names(control_event_names_env, + &control_trigger_event_names_); + if (control_trigger_event_names_.empty()) { + DFTRACER_LOG_WARN( + "%s is set but empty; control-event producer disabled", + control_event_names_env_name); } else { - control_topic_name_ = "control_events"; - DFTRACER_LOG_INFO("%s unset; defaulting to %s", control_topic_env_name, - control_topic_name_.c_str()); + DFTRACER_LOG_INFO("Mofka control trigger names loaded from %s", + control_event_names_env_name); } + } else { + // Default trigger names to avoid requiring extra env setup. + control_trigger_event_names_.push_back("epoch.start"); + control_trigger_event_names_.push_back("epoch.block"); + DFTRACER_LOG_INFO( + "%s unset; defaulting control-event triggers to " + "epoch.start,epoch.block", + control_event_names_env_name); + } - const char* control_event_names_env_name = - "DFTRACER_MOFKA_CONTROL_EVENT_NAMES"; - const char* control_event_names_env = - std::getenv(control_event_names_env_name); - if (control_event_names_env) { - parse_control_event_names(control_event_names_env, - &control_trigger_event_names_); - if (control_trigger_event_names_.empty()) { - DFTRACER_LOG_WARN( - "%s is set but empty; control-event producer disabled", - control_event_names_env_name); - } else { - DFTRACER_LOG_INFO("Mofka control trigger names loaded from %s", - control_event_names_env_name); - } + if (producer_thread_pool) { + producer_ = std::make_unique( + topic_->producer("dftracer", batchSize, max_num_batches, ordering, + producer_thread_pool)); + } else { + producer_ = std::make_unique( + topic_->producer("dftracer", batchSize, max_num_batches, ordering)); + } + DFTRACER_LOG_INFO("Mofka producer created", ""); + + if (!control_trigger_event_names_.empty()) { + if (driver_->topicExists(control_topic_name_)) { + DFTRACER_LOG_INFO("Mofka control topic exists", ""); } else { - // Default trigger names to avoid requiring extra env setup. - control_trigger_event_names_.push_back("epoch.start"); - control_trigger_event_names_.push_back("epoch.block"); - DFTRACER_LOG_INFO( - "%s unset; defaulting control-event triggers to " - "epoch.start,epoch.block", - control_event_names_env_name); + ensure_topic_exists(driver_.get(), control_topic_name_); + DFTRACER_LOG_INFO("Mofka control topic created", ""); } + control_topic_ = std::make_unique( + driver_->openTopic(control_topic_name_)); + const diaspora::BatchSize control_batch_size{1}; + const diaspora::Ordering control_ordering = diaspora::Ordering::Strict; if (producer_thread_pool) { - producer_ = std::make_unique( - topic_->producer("dftracer", batchSize, max_num_batches, ordering, - producer_thread_pool)); + control_producer_ = + std::make_unique(control_topic_->producer( + "dftracer_control", control_batch_size, max_num_batches, + control_ordering, producer_thread_pool)); } else { - producer_ = std::make_unique( - topic_->producer("dftracer", batchSize, max_num_batches, ordering)); + control_producer_ = std::make_unique( + control_topic_->producer("dftracer_control", control_batch_size, + max_num_batches, control_ordering)); } - DFTRACER_LOG_INFO("Mofka producer created", ""); - - if (!control_trigger_event_names_.empty()) { - if (driver_->topicExists(control_topic_name_)) { - DFTRACER_LOG_INFO("Mofka control topic exists", ""); - } else { - ensure_topic_exists(driver_.get(), control_topic_name_); - DFTRACER_LOG_INFO("Mofka control topic created", ""); - } - control_topic_ = std::make_unique( - driver_->openTopic(control_topic_name_)); - - const diaspora::BatchSize control_batch_size{1}; - const diaspora::Ordering control_ordering = diaspora::Ordering::Strict; - if (producer_thread_pool) { - control_producer_ = - std::make_unique(control_topic_->producer( - "dftracer_control", control_batch_size, max_num_batches, - control_ordering, producer_thread_pool)); - } else { - control_producer_ = std::make_unique( - control_topic_->producer("dftracer_control", control_batch_size, - max_num_batches, control_ordering)); - } - DFTRACER_LOG_INFO( - "Mofka control producer enabled: topic=%s trigger_count=%zu", - control_topic_name_.c_str(), control_trigger_event_names_.size()); - control_hooks_enabled_ = true; - } - - init_pid_ = getpid(); - DFTRACER_LOG_INFO("MofkaWriter initialized with PID %d", init_pid_); - } catch (const std::exception& e) { - DFTRACER_LOG_ERROR("Failed to initialize MofkaWriter", e.what()); - throw; + DFTRACER_LOG_INFO( + "Mofka control producer enabled: topic=%s trigger_count=%zu", + control_topic_name_.c_str(), control_trigger_event_names_.size()); + control_hooks_enabled_ = true; } + + init_pid_ = current_pid; + DFTRACER_LOG_INFO("MofkaWriter initialized with PID %d", init_pid_); + } catch (const std::exception& e) { + DFTRACER_LOG_ERROR("Failed to initialize MofkaWriter", e.what()); + throw; } } @@ -323,10 +338,8 @@ size_t MofkaWriter::write(const char* data, size_t len, bool force) { return 0; } try { - // Use string_view with explicit length and parse=false to store raw data - // without JSON parsing (which would fail on binary data with null bytes) std::string_view data_view(data, len); - producer_->push(diaspora::Metadata{data_view, false}, diaspora::DataView{}); + producer_->push(diaspora::Metadata{data_view}, diaspora::DataView{}); ++trace_events_written_; if (flush_every_n_writes_ > 0) {