diff --git a/.bazeliskrc b/.bazeliskrc deleted file mode 100644 index 95447bd..0000000 --- a/.bazeliskrc +++ /dev/null @@ -1 +0,0 @@ -USE_BAZEL_VERSION=5.4.0 \ No newline at end of file diff --git a/.bazelrc b/.bazelrc deleted file mode 100644 index b51b048..0000000 --- a/.bazelrc +++ /dev/null @@ -1,40 +0,0 @@ -build --cxxopt='-std=c++17' --cxxopt='-Wall' --cxxopt='-fno-omit-frame-pointer' - -# Address sanitizer -# To use it: bazel build --config asan -build:asan --strip=never -build:asan --copt -fsanitize=address -build:asan --copt -DADDRESS_SANITIZER -build:asan --copt -O1 -build:asan --copt -g -build:asan --copt -fno-omit-frame-pointer -build:asan --linkopt -fsanitize=address - -# Thread sanitizer -# bazel build --config tsan -build:tsan --strip=never -build:tsan --copt -fsanitize=thread -build:tsan --copt -DTHREAD_SANITIZER -build:tsan --copt -DDYNAMIC_ANNOTATIONS_ENABLED=1 -build:tsan --copt -DDYNAMIC_ANNOTATIONS_EXTERNAL_IMPL=1 -build:tsan --copt -O1 -build:tsan --copt -fno-omit-frame-pointer -build:tsan --linkopt -fsanitize=thread - -# --config msan: Memory sanitizer -build:msan --strip=never -build:msan --copt -fsanitize=memory -build:msan --copt -DADDRESS_SANITIZER -build:msan --copt -O1 -build:msan --copt -fno-omit-frame-pointer -build:msan --linkopt -fsanitize=memory - -# --config ubsan: Undefined Behavior Sanitizer -build:ubsan --strip=never -build:ubsan --copt -fsanitize=undefined -build:ubsan --copt -O1 -build:ubsan --copt -fno-omit-frame-pointer -build:ubsan --linkopt -fsanitize=undefined -build:ubsan --linkopt -lubsan - -test --test_output=streamed diff --git a/.clang-format b/.clang-format index 1996112..865f732 100644 --- a/.clang-format +++ b/.clang-format @@ -21,7 +21,7 @@ BinPackArguments: true BinPackParameters: true BraceWrapping: AfterClass: false - AfterControlStatement: false + AfterControlStatement: Never AfterEnum: false AfterFunction: false AfterNamespace: false @@ -86,4 +86,3 @@ Standard: Auto TabWidth: 8 UseTab: Never ... - diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51959c5..f80fca2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,30 +11,49 @@ jobs: if: ${{ github.repository == 'Netflix/spectator-cpp' }} runs-on: ubuntu-latest env: + BUILD_DIR: "cmake-build" CC: "gcc-11" CXX: "g++-11" LANG: "en_US.UTF-8" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - name: Bazel Cache + - name: Conan+Cmake Cache uses: actions/cache@v3 with: - path: ~/.cache/bazel - key: ${{ runner.os }}-bazel + path: | + ~/.conan + ~/work/spectatord/spectatord/cmake-build + key: ${{ runner.os }}-conan-cmake - name: Install System Dependencies run: | - curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg - sudo mv bazel.gpg /etc/apt/trusted.gpg.d/ - echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-get update && sudo apt-get install -y bazel-5.4.0 binutils-dev g++-11 + sudo apt-get update && sudo apt-get install -y binutils-dev g++-11 libiberty-dev + + echo "==== cmake ====" + cmake -version + + echo "==== python ====" + python3 -V + + echo "==== conan ====" + pip install "conan==1.61.0" + conan --version + if [[ ! -f ~/.conan/profiles/default ]]; then conan profile new default --detect; fi + conan profile update settings.compiler.libcxx=libstdc++11 default + + - name: Install Project Dependencies + run: | + conan install . --build=missing --install-folder $BUILD_DIR - name: Build spectator-cpp run: | - bazel-5.4.0 --output_user_root=~/.cache/bazel --batch build --config asan spectator_test spectator + cd $BUILD_DIR + cmake .. -DCMAKE_BUILD_TYPE=Debug + cmake --build . - name: Test spectator-cpp run: | - GTEST_COLOR=1 ./bazel-bin/spectator_test + cd $BUILD_DIR + GTEST_COLOR=1 ctest --verbose diff --git a/.gitignore b/.gitignore index 54b6549..0b6bfbc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -.clwb/ +.DS_Store .idea/ -.vscode/ -bazel-* -build-* +cmake-build-debug/ +cmake-build/ +venv/ diff --git a/BUILD.bazel b/BUILD.bazel deleted file mode 100644 index 1955d40..0000000 --- a/BUILD.bazel +++ /dev/null @@ -1,51 +0,0 @@ -cc_library( - name = "spectator", - srcs = [ - "spectator/logger.cc", - "spectator/publisher.cc", - ], - hdrs = [ - "spectator/config.h", - "spectator/id.h", - "spectator/logger.h", - "spectator/measurement.h", - "spectator/meter_type.h", - "spectator/publisher.h", - "spectator/registry.h", - "spectator/stateful_meters.h", - "spectator/stateless_meters.h", - ], - visibility = ["//visibility:public"], - deps = [ - "@asio", - "@com_github_fmtlib_fmt//:fmtlib", - "@com_github_gabime_spdlog//:spdlog", - "@com_google_absl//absl/container:flat_hash_map", - "@com_google_absl//absl/strings", - ], -) - -cc_test( - name = "spectator_test", - srcs = glob([ - "spectator/*_test.cc", - "spectator/test_*.cc", - "spectator/test_*.h", - ]), - linkopts = select({ - "@bazel_tools//src/conditions:linux_x86_64": [ - "-lbfd", - "-ldl", - ], - "//conditions:default": [], - }), - local_defines = select({ - "@bazel_tools//src/conditions:linux_x86_64": ["BACKWARD_HAS_BFD=1"], - "//conditions:default": [], - }), - deps = [ - ":spectator", - "@com_github_bombela_backward//:backward", - "@com_google_googletest//:gtest", - ], -) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8317b8a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.13) + +project(spectator) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +if(APPLE) + # Address Sanitizer is finicky on MacOS Apple Silicon, so skip it + add_compile_options(-fno-omit-frame-pointer) + add_link_options(-fno-omit-frame-pointer) +else() + add_compile_options(-fno-omit-frame-pointer "$<$:-fsanitize=address>") + add_link_options(-fno-omit-frame-pointer "$<$:-fsanitize=address>") +endif() + +include(CTest) +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +#-- spectator_test test executable +file(GLOB spectator_test_source_files + "spectator/*_test.cc" + "spectator/test_*.cc" + "spectator/test_*.h" +) +add_executable(spectator_test ${spectator_test_source_files}) +target_link_libraries(spectator_test spectator ${CONAN_LIBS}) +add_test( + NAME spectator_test + COMMAND spectator_test + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +) + +#-- spectator library +add_library(spectator + "spectator/logger.cc" + "spectator/publisher.cc" + "spectator/config.h" + "spectator/id.h" + "spectator/logger.h" + "spectator/measurement.h" + "spectator/meter_type.h" + "spectator/publisher.h" + "spectator/registry.h" + "spectator/stateful_meters.h" + "spectator/stateless_meters.h" +) +target_link_libraries(spectator ${CONAN_LIBS}) +target_link_options(spectator PRIVATE "$<$:-static-libstdc++>") diff --git a/README.md b/README.md index 6d5616f..5bdfc57 100644 --- a/README.md +++ b/README.md @@ -84,3 +84,15 @@ int main() { By default, the library sends every meter change to the spectatord sidecar immediately. This involves a blocking `send` call and underlying system calls, and may not be the most efficient way to publish metrics in high-volume use cases. For this purpose a simple buffering functionality in `Publisher` is implemented, and it can be turned on by passing a buffer size to the `spectator::Config` constructor. It is important to note that, until this buffer fills up, the `Publisher` will not send nay meters to the sidecar. Therefore, if your application doesn't emit meters at a high rate, you should either keep the buffer very small, or do not configure a buffer size at all, which will fall back to the "publish immediately" mode of operation. + +## Local Development + +```shell +./setup-venv.sh +source venv/bin/activate +./build.sh # [clean|skiptest] +``` + +* CLion > Preferences > Plugins > Marketplace > Conan > Install +* CLion > Preferences > Build, Execution, Deploy > Conan > Conan Executable: $PROJECT_HOME/venv/bin/conan +* CLion > Bottom Bar: Conan > Left Button: Match Profile > CMake Profile: Debug, Conan Profile: default diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index 3ef93e2..0000000 --- a/WORKSPACE +++ /dev/null @@ -1,5 +0,0 @@ -workspace(name = "spectator") - -load("@spectator//:dependencies.bzl", "spectator_dependencies") - -spectator_dependencies() diff --git a/bazel/BUILD b/bazel/BUILD deleted file mode 100644 index e69de29..0000000 diff --git a/bazel/abseil.patch b/bazel/abseil.patch deleted file mode 100644 index d525564..0000000 --- a/bazel/abseil.patch +++ /dev/null @@ -1,42 +0,0 @@ -# Force internal versions of std classes per -# https://abseil.io/docs/cpp/guides/options -diff --git a/absl/base/options.h b/absl/base/options.h -index 230bf1e..6e1b9e5 100644 ---- a/absl/base/options.h -+++ b/absl/base/options.h -@@ -100,7 +100,7 @@ - // User code should not inspect this macro. To check in the preprocessor if - // absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY. - --#define ABSL_OPTION_USE_STD_ANY 2 -+#define ABSL_OPTION_USE_STD_ANY 0 - - - // ABSL_OPTION_USE_STD_OPTIONAL -@@ -127,7 +127,7 @@ - // absl::optional is a typedef of std::optional, use the feature macro - // ABSL_USES_STD_OPTIONAL. - --#define ABSL_OPTION_USE_STD_OPTIONAL 2 -+#define ABSL_OPTION_USE_STD_OPTIONAL 0 - - - // ABSL_OPTION_USE_STD_STRING_VIEW -@@ -154,7 +154,7 @@ - // absl::string_view is a typedef of std::string_view, use the feature macro - // ABSL_USES_STD_STRING_VIEW. - --#define ABSL_OPTION_USE_STD_STRING_VIEW 2 -+#define ABSL_OPTION_USE_STD_STRING_VIEW 0 - - // ABSL_OPTION_USE_STD_VARIANT - // -@@ -180,7 +180,7 @@ - // absl::variant is a typedef of std::variant, use the feature macro - // ABSL_USES_STD_VARIANT. - --#define ABSL_OPTION_USE_STD_VARIANT 2 -+#define ABSL_OPTION_USE_STD_VARIANT 0 - - - // ABSL_OPTION_USE_INLINE_NAMESPACE diff --git a/build.sh b/build.sh index 22e3435..de691d4 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,44 @@ -#!/bin/bash +#!/usr/bin/env bash -bazel --output_user_root=$HOME/.cache/bazel --batch build --config asan spectator_test spectator -GTEST_COLOR=1 ./bazel-bin/spectator_test +BUILD_DIR=cmake-build +# Choose: Debug, Release, RelWithDebInfo and MinSizeRel +BUILD_TYPE=Debug + +BLUE="\033[0;34m" +NC="\033[0m" + +if [[ "$1" == "clean" ]]; then + echo -e "${BLUE}==== clean ====${NC}" + rm -rf $BUILD_DIR +fi + +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + export CC=gcc-11 + export CXX=g++-11 +fi + +if [[ ! -d $BUILD_DIR ]]; then + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + echo -e "${BLUE}==== configure default profile ====${NC}" + conan profile new default --detect + conan profile update settings.compiler.libcxx=libstdc++11 default + fi + + echo -e "${BLUE}==== install required dependencies ====${NC}" + conan install . --build=missing --install-folder $BUILD_DIR +fi + +pushd $BUILD_DIR || exit 1 + +echo -e "${BLUE}==== generate build files ====${NC}" +cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE || exit 1 + +echo -e "${BLUE}==== build ====${NC}" +cmake --build . || exit 1 + +if [[ "$1" != "skiptest" ]]; then + echo -e "${BLUE}==== test ====${NC}" + GTEST_COLOR=1 ctest --verbose +fi + +popd || exit 1 diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..42a1603 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,16 @@ +from conans import ConanFile + + +class SpectatorDConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + requires = ( + "abseil/20230125.3", + "asio/1.28.1", + "backward-cpp/1.6", + "benchmark/1.8.3", + "fmt/10.1.1", + "gtest/1.14.0", + "spdlog/1.12.0" + ) + generators = "cmake" + default_options = {} diff --git a/dependencies.bzl b/dependencies.bzl deleted file mode 100644 index c0244fd..0000000 --- a/dependencies.bzl +++ /dev/null @@ -1,64 +0,0 @@ -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -def spectator_dependencies(): - http_archive( - name = "com_github_fmtlib_fmt", - build_file = "@spectator//third_party:fmtlib.BUILD", - strip_prefix = "fmt-8.0.1", - sha256 = "a627a56eab9554fc1e5dd9a623d0768583b3a383ff70a4312ba68f94c9d415bf", - urls = ["https://github.com/fmtlib/fmt/releases/download/8.0.1/fmt-8.0.1.zip"], - ) - - http_archive( - name = "com_github_gabime_spdlog", - build_file = "@spectator//third_party:spdlog.BUILD", - strip_prefix = "spdlog-1.9.1", - sha256 = "9a452cfa24408baccc9b2bc2d421d68172a7630c99e9504a14754be840d31a62", - urls = ["https://github.com/gabime/spdlog/archive/v1.9.1.tar.gz"], - ) - - http_archive( - name = "com_google_googletest", - urls = ["https://github.com/google/googletest/archive/release-1.10.0.tar.gz"], - strip_prefix = "googletest-release-1.10.0", - sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb", - ) - - http_archive( - name = "com_google_benchmark", - urls = ["https://github.com/google/benchmark/archive/v1.5.1.tar.gz"], - strip_prefix = "benchmark-1.5.1", - sha256 = "23082937d1663a53b90cb5b61df4bcc312f6dee7018da78ba00dd6bd669dfef2", - ) - - http_archive( - name = "asio", - build_file = "@spectator//third_party:asio.BUILD", - urls = ["https://github.com/chriskohlhoff/asio/archive/asio-1-14-0.zip"], - strip_prefix = "asio-asio-1-14-0", - sha256 = "7887c91704a92dc8425385b1ff6f3e432e8869745b2ee2f896a1e7eb2a60e729", - ) - - http_archive( - name = "com_google_absl", - urls = ["https://github.com/abseil/abseil-cpp/archive/17c954d90d5661e27db8fc5f086085690a8372d9.zip"], - strip_prefix = "abseil-cpp-17c954d90d5661e27db8fc5f086085690a8372d9", - sha256 = "aee7688bb669402c1322d9512d7992a6f361a70444e54d98a8709a8ad4dd60c3", - patches = ["@//bazel:abseil.patch"], - patch_args = ["-p1"], - ) - - http_archive( - name = "com_github_bombela_backward", - urls = ["https://github.com/bombela/backward-cpp/archive/1efdd145b5fa84f457fb6727677ce0bc9f2c7b5b.zip"], - strip_prefix = "backward-cpp-1efdd145b5fa84f457fb6727677ce0bc9f2c7b5b", - build_file = "@spectator//third_party:backward.BUILD", - sha256 = "97ddc265cc42afadf870ccfa9b079382766eb9e46e8fc1994a61a92ff547c851", - ) - - http_archive( - name = "com_grail_bazel_compdb", - strip_prefix = "bazel-compilation-database-71edeae2eda57e4be679394d22b8ef7a60ca3860", - sha256 = "7504feffad927af7ba54213e741975b4e1e890c6cc7d1bc186ea4024508acd4c", - urls = ["https://github.com/grailbio/bazel-compilation-database/archive/71edeae2eda57e4be679394d22b8ef7a60ca3860.zip"], - ) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f50948a --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +conan==1.61.0 diff --git a/scripts/gen-compdb b/scripts/gen-compdb deleted file mode 100755 index 348b07e..0000000 --- a/scripts/gen-compdb +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -bazel build spectator_compdb -outfile="$(bazel info bazel-bin)/compile_commands.json" -execroot=$(bazel info execution_root) -sed -i.bak "s@__EXEC_ROOT__@${execroot}@" "${outfile}" -echo "Compilation Database: ${outfile}" diff --git a/setup-venv.sh b/setup-venv.sh new file mode 100755 index 0000000..7f50e7f --- /dev/null +++ b/setup-venv.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +PYTHON3=$(which python3) + +if [[ -z $PYTHON3 ]]; then + echo "python3 is not available - please install" + exit 1 +fi + +python3 -m venv venv + +source venv/bin/activate + +if [[ -f requirements.txt ]]; then + pip3 install --upgrade pip wheel + pip3 install --requirement requirements.txt +fi diff --git a/spectator/registry.h b/spectator/registry.h index 0154bd3..4e54780 100644 --- a/spectator/registry.h +++ b/spectator/registry.h @@ -102,11 +102,11 @@ struct single_table_state { } absl::Mutex mutex_; - // use a single table so we can easily check whether a meter + // use a single table, so we can easily check whether a meter // was previously registered as a different type absl::flat_hash_map, std::hash, std::equal_to> - meters_ GUARDED_BY(mutex_); + meters_ ABSL_GUARDED_BY(mutex_); }; template diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel deleted file mode 100644 index e69de29..0000000 diff --git a/third_party/asio.BUILD b/third_party/asio.BUILD deleted file mode 100644 index 1f36e06..0000000 --- a/third_party/asio.BUILD +++ /dev/null @@ -1,9 +0,0 @@ -cc_library( - name = "asio", - hdrs = glob([ - "**/*.hpp", - "**/*.ipp", - ]), - includes = ["asio/include"], - visibility = ["//visibility:public"], -) diff --git a/third_party/backward.BUILD b/third_party/backward.BUILD deleted file mode 100644 index 82393da..0000000 --- a/third_party/backward.BUILD +++ /dev/null @@ -1,10 +0,0 @@ -load("@rules_cc//cc:defs.bzl", "cc_library") - -licenses(["notice"]) # MIT License - -cc_library( - name = "backward", - srcs = ["backward.cpp"], - hdrs = ["backward.hpp"], - visibility = ["//visibility:public"], -) diff --git a/third_party/fmtlib.BUILD b/third_party/fmtlib.BUILD deleted file mode 100644 index 17832ea..0000000 --- a/third_party/fmtlib.BUILD +++ /dev/null @@ -1,14 +0,0 @@ -# https://github.com/envoyproxy/envoy/blob/master/bazel/external/fmtlib.BUILD. - -cc_library( - name = "fmtlib", - srcs = glob([ - "fmt/*.cc", - ]), - hdrs = glob([ - "include/fmt/*.h", - ]), - defines = ["FMT_HEADER_ONLY"], - includes = ["include"], - visibility = ["//visibility:public"], -) diff --git a/third_party/spdlog.BUILD b/third_party/spdlog.BUILD deleted file mode 100644 index 6b12bc8..0000000 --- a/third_party/spdlog.BUILD +++ /dev/null @@ -1,13 +0,0 @@ -# https://github.com/envoyproxy/envoy/blob/master/bazel/external/spdlog.BUILD. - -cc_library( - name = "spdlog", - hdrs = glob([ - "include/**/*.cc", - "include/**/*.h", - ]), - defines = ["SPDLOG_FMT_EXTERNAL"], - includes = ["include"], - visibility = ["//visibility:public"], - deps = ["@com_github_fmtlib_fmt//:fmtlib"], -)