diff --git a/.gitignore b/.gitignore index ca84613d..69d948e4 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,7 @@ pydftracer.egg-info # Debug files /*.core +tmp/ dfanalyzer_old/dask/run_dir dfanalyzer_old/dask/logs 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 diff --git a/.vscode/settings.json b/.vscode/settings.json index 90c739a6..efb58aca 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,17 +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_MPI=OFF" + "-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", @@ -98,9 +107,5 @@ "*.in": "cpp", "text_encoding": "cpp" }, - "editor.formatOnSave": true, - "cSpell.words": [ - "DFTRACER", - "dlio" - ] + "git.ignoreLimitWarning": true } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 36397fd6..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,331 +22,432 @@ 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_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) +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, 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_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_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 "") + # 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}) + 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 () + else() message(FATAL_ERROR "-- [CPP_LOGGER] is needed for ${PROJECT_NAME} build") -endif () + 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) - 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() - else () - message(FATAL_ERROR "-- [DFTRACER] mpi is needed for ${PROJECT_NAME} build") - endif () -endif() + if(DFTRACER_ENABLE_MPI) + find_package(MPI COMPONENTS CXX REQUIRED) -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(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}) -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}) - endif() - if (DEFINED ZLIB_LIBRARY_DIRS) - list(APPEND DEPENDENCY_LIBRARY_DIRS ${ZLIB_LIBRARY_DIRS}) + # 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() -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") - endif() -endif() + endforeach() -# 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) + list(REMOVE_DUPLICATES MPI_CXX_LIBRARY_DIRS) -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) + 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() + + 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() + + 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}) + 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(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(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() + + 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) -set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/posix.cpp + 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 @@ -361,15 +462,14 @@ set(DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/brahma/posix ${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 @@ -384,76 +484,73 @@ set(DFTRACER_CORE_PRIVATE_INCLUDE ${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) - - -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() -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 + + 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() + list(APPEND DFTRACER_CORE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/dftracer/core/writer/stdio_writer.cpp) + endif() + + 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() + + 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 @@ -461,382 +558,294 @@ set_target_properties(${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( + 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 + ) + 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 + 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} + 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}) - 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( + 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 + 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( + 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) + 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") - 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(FILES ${EXECUTABLE_OUTPUT_PATH}/dftracer_validate DESTINATION bin) 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) + + 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() -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 + 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 + 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 + 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(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() -# 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 -) -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}") + 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 e4062215..4f8280ff 100644 --- a/cmake/configure_files/dftracer_config.hpp.in +++ b/cmake/configure_files/dftracer_config.hpp.in @@ -29,11 +29,15 @@ #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_HWLOC_ENABLE 1 +#cmakedefine DFTRACER_GNU_LINUX 1 #cmakedefine DFTRACER_HIP_TRACING_ENABLE 1 +#cmakedefine DFTRACER_HWLOC_ENABLE 1 +#cmakedefine DFTRACER_MPI_ENABLE 1 +#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 fc63c524..23595808 100644 --- a/cmake/configure_files/dftracer_config_dbg.hpp.in +++ b/cmake/configure_files/dftracer_config_dbg.hpp.in @@ -29,11 +29,15 @@ #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_HWLOC_ENABLE 1 +#cmakedefine DFTRACER_GNU_LINUX 1 #cmakedefine DFTRACER_HIP_TRACING_ENABLE 1 +#cmakedefine DFTRACER_HWLOC_ENABLE 1 +#cmakedefine DFTRACER_MPI_ENABLE 1 +#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/cmake/modules/dftracer-utils.cmake b/cmake/modules/dftracer-utils.cmake index 1e50a842..7d8d82dc 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,68 @@ 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_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 + LOG_DOWNLOAD ON ) include_directories(${install_prefix}/include) link_directories(${install_prefix}/lib) @@ -148,10 +162,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 178f82ff..0ec0e5b5 100644 --- a/dependency/CMakeLists.txt +++ b/dependency/CMakeLists.txt @@ -1,16 +1,25 @@ 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) -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") +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) 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") +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/include/dftracer/core/common/constants.h b/include/dftracer/core/common/constants.h index 397f66be..094f61bc 100644 --- a/include/dftracer/core/common/constants.h +++ b/include/dftracer/core/common/constants.h @@ -28,6 +28,7 @@ #define DFTRACER_WRITE_BUFFER_SIZE "DFTRACER_WRITE_BUFFER_SIZE" #define DFTRACER_TRACE_INTERVAL_MS "DFTRACER_TRACE_INTERVAL_MS" #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/common/typedef.h b/include/dftracer/core/common/typedef.h index 59edcbdf..57c208e9 100644 --- a/include/dftracer/core/common/typedef.h +++ b/include/dftracer/core/common/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 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 a73dbe43..17b9388a 100644 --- a/include/dftracer/dftracer.h +++ b/include/dftracer/dftracer.h @@ -15,10 +15,10 @@ #ifdef __cplusplus extern "C" { #endif -void initialize_main(const char *log_file, const char *data_dirs, - int *process_id); -void initialize_no_bind(const char *log_file, const char *data_dirs, - int *process_id); +void initialize_main(const char* log_file, const char* data_dirs, + int* process_id); +void initialize_no_bind(const char* log_file, const char* data_dirs, + int* process_id); void finalize(); #ifdef __cplusplus } @@ -42,16 +42,16 @@ class DFTracer { ConstEventNameType name; ConstEventNameType cat; TimeResolution start_time; - dftracer::Metadata *metadata; + dftracer::Metadata* metadata; public: DFTracer(ConstEventNameType _name, ConstEventNameType _cat, int event_type = DF_DATA_EVENT); - void update(const char *key, int value, + void update(const char* key, int value, MetadataType type = MetadataType::MT_KEY); - void update(const char *key, const char *value, + void update(const char* key, const char* value, MetadataType type = MetadataType::MT_KEY); void finalize(); @@ -66,7 +66,7 @@ class DFTracer { #define DFTRACER_CPP_FINI() finalize() #define DFTRACER_CPP_FUNCTION() \ DFTracer profiler_dft_fn = \ - DFTracer((char *)__FUNCTION__, CPP_LOG_CATEGORY, DF_DATA_EVENT); + DFTracer((char*)__FUNCTION__, CPP_LOG_CATEGORY, DF_DATA_EVENT); #define DFTRACER_CPP_METADATA(name, key, value) \ { \ @@ -77,7 +77,7 @@ class DFTracer { DFTracer profiler_##name = DFTracer(#name, CPP_LOG_CATEGORY, DF_DATA_EVENT); #define DFTRACER_CPP_REGION_START(name) \ - DFTracer *profiler_##name = \ + DFTracer* profiler_##name = \ new DFTracer(#name, CPP_LOG_CATEGORY, DF_DATA_EVENT); #define DFTRACER_CPP_REGION_END(name) delete profiler_##name @@ -104,21 +104,21 @@ extern "C" { // C APIs struct DFTracerData { - void *profiler; + void* profiler; }; __attribute__((unused)) static ConstEventNameType C_LOG_CATEGORY = "C_APP"; -struct DFTracerData *initialize_region(ConstEventNameType name, +struct DFTracerData* initialize_region(ConstEventNameType name, ConstEventNameType cat, int event_type); -void finalize_region(struct DFTracerData *data); -void update_metadata_int(struct DFTracerData *data, const char *key, int value); -void update_metadata_string(struct DFTracerData *data, const char *key, - const char *value); +void finalize_region(struct DFTracerData* data); +void update_metadata_int(struct DFTracerData* data, const char* key, int value); +void update_metadata_string(struct DFTracerData* data, const char* key, + const char* value); -void update_metadata_int_type(struct DFTracerData *data, const char *key, +void update_metadata_int_type(struct DFTracerData* data, const char* key, int value, int type); -void update_metadata_string_type(struct DFTracerData *data, const char *key, - const char *value, int type); +void update_metadata_string_type(struct DFTracerData* data, const char* key, + const char* value, int type); #define DFTRACER_C_INIT(log_file, data_dirs, process_id) \ initialize_main(log_file, data_dirs, process_id); @@ -127,20 +127,20 @@ void update_metadata_string_type(struct DFTracerData *data, const char *key, #define DFTRACER_C_FINI() finalize() #define DFTRACER_C_FUNCTION_START() \ - struct DFTracerData *data_fn = \ + struct DFTracerData* data_fn = \ initialize_region(__func__, C_LOG_CATEGORY, DF_DATA_EVENT); #define DFTRACER_C_FUNCTION_END() finalize_region(data_fn); #define DFTRACER_C_REGION_START(name) \ - struct DFTracerData *data_##name = \ + struct DFTracerData* data_##name = \ initialize_region(#name, C_LOG_CATEGORY, DF_DATA_EVENT); #define DFTRACER_C_REGION_END(name) finalize_region(data_##name); #define DFTRACER_C_METADATA(name, key, val) \ { \ - struct DFTracerData *data_##name = \ + struct DFTracerData* data_##name = \ initialize_region(key, val, DF_METADATA_EVENT); \ finalize_region(data_##name); \ } diff --git a/pyproject.toml b/pyproject.toml index 4d2c0a7c..c0fd859a 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 @ git+https://github.com/izzet/pydftracer.git@fix/lazy-dynamo-imports", ] [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/setup.py b/setup.py index e742b314..ea07f9b1 100644 --- a/setup.py +++ b/setup.py @@ -18,10 +18,9 @@ } - - 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: @@ -81,7 +80,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}"] @@ -94,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"] @@ -114,6 +126,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", "STDIO") + 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", "") @@ -142,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" @@ -154,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 @@ -164,18 +201,27 @@ def build_extension(self, ext: CMakeExtension) -> None: f"-Dyaml-cpp_DIR={install_prefix}", f"-Dpybind11_DIR={py_cmake_dir}", ] - - + if "DFTRACER_CMAKE_ARGS" in os.environ: - cmake_args += [item for item in os.environ["DFTRACER_CMAKE_ARGS"].split(";") if item] + cmake_args += [ + 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 @@ -183,8 +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"), diff --git a/src/dftracer/core/buffer/buffer.cpp b/src/dftracer/core/buffer/buffer.cpp index 492135b7..044545da 100644 --- a/src/dftracer/core/buffer/buffer.cpp +++ b/src/dftracer/core/buffer/buffer.cpp @@ -1,4 +1,16 @@ #include + +#include +#include + +#if DFTRACER_WRITER_TYPE_MOFKA +#include +#elif DFTRACER_WRITER_TYPE_ZMQ +#include +#else +#include +#endif + template <> std::shared_ptr dftracer::Singleton::instance = nullptr; @@ -8,6 +20,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,8 +49,18 @@ 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()); +#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()); +#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) { @@ -49,6 +74,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 +90,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); @@ -80,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) { @@ -116,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); @@ -129,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 0695cb13..b7ae284c 100644 --- a/src/dftracer/core/buffer/buffer.h +++ b/src/dftracer/core/buffer/buffer.h @@ -1,26 +1,31 @@ #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: 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,12 +61,13 @@ class BufferManager { std::shared_mutex mtx; std::string app_name; int rank; + bool control_hooks_enabled; 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 -#endif // DFTRACER_BUFFER_H \ No newline at end of file +#endif // DFTRACER_BUFFER_H diff --git a/src/dftracer/core/common/enumeration.h b/src/dftracer/core/common/enumeration.h index 5d8d93f7..28564a41 100644 --- a/src/dftracer/core/common/enumeration.h +++ b/src/dftracer/core/common/enumeration.h @@ -5,7 +5,15 @@ #ifndef DFTRACER_ENUMERATION_H #define DFTRACER_ENUMERATION_H #include -enum WriterType : uint8_t { CHROME = 0 }; + +#include +#include + +enum WriterType : uint8_t { + WRITER_TYPE_STDIO = 0, + WRITER_TYPE_MOFKA = 1, + WRITER_TYPE_ZMQ = 2, +}; enum ProfilerStage : uint8_t { PROFILER_INIT = 0, PROFILER_FINI = 1, @@ -31,7 +39,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) { @@ -43,7 +51,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) { @@ -55,7 +63,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") { @@ -64,7 +72,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") { @@ -75,7 +83,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") { @@ -84,7 +92,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"; @@ -95,6 +103,16 @@ 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; + } +} + #define METADATA_NAME_PROCESS "PR" #define METADATA_NAME_PROCESS_NAME "process_name" #define METADATA_NAME_THREAD_NAME "thread_name" 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/df_logger.h b/src/dftracer/core/df_logger.h index 40393b18..bfde90f1 100644 --- a/src/dftracer/core/df_logger.h +++ b/src/dftracer/core/df_logger.h @@ -115,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]); } @@ -139,7 +139,6 @@ class DFTLogger { if (dftracer_tid) { tid = df_gettid(); } - HashType hostname_hash; HashType cmd_hash; HashType exec_hash; @@ -155,36 +154,36 @@ 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); #ifdef DFTRACER_GIT_VERSION - meta->insert_or_assign("version", DFTRACER_GIT_VERSION); + metadata->insert_or_assign("version", DFTRACER_GIT_VERSION); #else #ifdef DFTRACER_VERSION - meta->insert_or_assign("version", DFTRACER_VERSION); + metadata->insert_or_assign("version", DFTRACER_VERSION); #endif #endif - meta->insert_or_assign("exec_hash", exec_hash); - meta->insert_or_assign("cmd_hash", cmd_hash); + 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->buffer_manager->set_app_name(exec_name.c_str()); } 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 (enable_core_affinity) { #ifdef DFTRACER_HWLOC_ENABLE @@ -298,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 @@ -350,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); @@ -372,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] = ' '; } @@ -395,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]; @@ -449,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(); \ @@ -462,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(); \ @@ -470,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 7a16e2fd..cd9a36bf 100644 --- a/src/dftracer/core/utils/configuration_manager.cpp +++ b/src/dftracer/core/utils/configuration_manager.cpp @@ -68,12 +68,19 @@ dftracer::ConfigurationManager::ConfigurationManager() bind_signals(false), throw_error(false), 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 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); @@ -85,7 +92,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); } @@ -224,8 +231,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]) { @@ -249,56 +256,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; @@ -310,41 +317,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; } @@ -357,13 +364,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; @@ -372,12 +379,30 @@ 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); + 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; + } + } + 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", ""); @@ -391,30 +416,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()); } @@ -425,4 +450,4 @@ void dftracer::ConfigurationManager::derive_configurations() { } DFTRACER_LOG_DEBUG("ConfigurationManager::derive_configurations finished", ""); -} \ No newline at end of file +} diff --git a/src/dftracer/core/utils/configuration_manager.h b/src/dftracer/core/utils/configuration_manager.h index 2090ba89..aa290293 100644 --- a/src/dftracer/core/utils/configuration_manager.h +++ b/src/dftracer/core/utils/configuration_manager.h @@ -32,6 +32,7 @@ class ConfigurationManager { bool bind_signals; bool throw_error; size_t write_buffer_size; + WriterType writer_type; size_t trace_interval_ms; bool aggregation_enable; AggregationType aggregation_type; diff --git a/src/dftracer/core/writer/mofka_writer.cpp b/src/dftracer/core/writer/mofka_writer.cpp new file mode 100644 index 00000000..e9bfea39 --- /dev/null +++ b/src/dftracer/core/writer/mofka_writer.cpp @@ -0,0 +1,415 @@ +#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 <> +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"; + 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_) { + 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 { + 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; + 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_ = 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; + } +} + +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 { + std::string_view data_view(data, len); + producer_->push(diaspora::Metadata{data_view}, 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()); + return 0; + } +} + +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 (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", ""); + } + if (driver_) { + driver_.reset(); + DFTRACER_LOG_INFO("Mofka driver reset", ""); + } +} + +} // namespace dftracer diff --git a/src/dftracer/core/writer/mofka_writer.h b/src/dftracer/core/writer/mofka_writer.h new file mode 100644 index 00000000..290dbed6 --- /dev/null +++ b/src/dftracer/core/writer/mofka_writer.h @@ -0,0 +1,44 @@ +#ifndef DFTRACER_MOFKA_WRITER_H +#define DFTRACER_MOFKA_WRITER_H + +#include + +#include +#include +#include +#include +#include + +namespace dftracer { + +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; +}; + +} // namespace dftracer + +#endif // DFTRACER_MOFKA_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_interface.h b/src/dftracer/core/writer/writer_interface.h new file mode 100644 index 00000000..59dcb7bb --- /dev/null +++ b/src/dftracer/core/writer/writer_interface.h @@ -0,0 +1,27 @@ +#ifndef DFTRACER_WRITER_INTERFACE_H +#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; +}; +} // namespace dftracer + +#endif // DFTRACER_WRITER_INTERFACE_H 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 1b2118aa..3db3faae 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,15 +1,70 @@ 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") + +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) + 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() + +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 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} + ${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} ${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} ${DFTRACER_TEST_DIR}/check_file_not.sh + ${CMAKE_CURRENT_BINARY_DIR}/${test_name}* + ) + else() + df_add_test(check_${test_name} + ${BASH_EXE} ${DFTRACER_TEST_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) @@ -19,6 +74,7 @@ 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}_core_dbg testlib) @@ -26,15 +82,28 @@ 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=$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}) + 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) @@ -44,17 +113,12 @@ df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY 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) @@ -66,15 +130,11 @@ df_add_test(${test_name} ${CMAKE_BINARY_DIR}/bin/test_cpp ${CMAKE_CURRENT_BINARY set_common_properties(${test_name}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_TRACE_COMPRESSION=1) - 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) @@ -82,44 +142,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) @@ -127,65 +174,48 @@ 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) 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}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT DFTRACER_INC_METADATA=1) - 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}) @@ -196,8 +226,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}) @@ -214,41 +242,30 @@ 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}) 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) 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}) 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) 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_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 @@ -256,83 +273,63 @@ set_tests_properties(check_file_exists_${test_name} PROPERTIES DEPENDS ${test_na 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}) 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) 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}) 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) 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}) 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) 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}) 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) 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}) 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 # ######################################################################## 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}) @@ -372,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/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..8e791b8e --- /dev/null +++ b/test/check_mofka_topic.py @@ -0,0 +1,147 @@ +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()}") + + 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/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/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/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() diff --git a/test/mofka.config.json b/test/mofka.config.json new file mode 100644 index 00000000..862605f7 --- /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.group.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.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 diff --git a/test/mofka_server_start.sh b/test/mofka_server_start.sh new file mode 100755 index 00000000..858d7e6b --- /dev/null +++ b/test/mofka_server_start.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# 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') + +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 new file mode 100755 index 00000000..273b6c1a --- /dev/null +++ b/test/mofka_server_stop.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# 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 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