Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the Prometheus exporter module to OpenTelemetry C++ 1.28 and adds a new Prometheus file exporter implementation alongside the existing push exporter.
Changes:
- Bump Prometheus module versions/references from 1.19.0 to 1.28.0 (CMake/Bazel/GitHub Actions/vcpkg).
- Add a new Prometheus file exporter (implementation, options, factory) and wire it into CMake + Bazel builds.
- Extend Prometheus push exporter options/translation path with
populate_target_infoandwithout_otel_scopeflags.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| exporters/prometheus/vcpkg.json | Adds vcpkg manifest for the Prometheus contrib module (now needs metadata aligned with push + file exporters). |
| exporters/prometheus/tools.cmake | Introduces CMake helpers for import/export visibility; contains Windows attribute and SunPro detection issues. |
| exporters/prometheus/src/push_exporter.cc | Plumbs new translation options through push exporter collection/translation. |
| exporters/prometheus/src/push_exporter_factory.cc | Exports the factory Create symbol via the new API macro. |
| exporters/prometheus/src/file_exporter.cc | Adds the new rotating-file exporter implementation (includes time/path formatting, background flush thread). |
| exporters/prometheus/src/file_exporter_factory.cc | Adds factory entry point for constructing the new file exporter. |
| exporters/prometheus/MODULE.bazel | Updates Bazel module + dependency versions to 1.28.0. |
| exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h | Minor formatting-only change. |
| exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_options.h | Adds new options + API visibility macro definition. |
| exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_factory.h | Exposes factory Create with API macro and includes options header. |
| exporters/prometheus/include/opentelemetry/exporters/prometheus/file_exporter.h | Adds public header for the new file exporter (needs API export annotation). |
| exporters/prometheus/include/opentelemetry/exporters/prometheus/file_exporter_options.h | Adds options + API visibility macro definition for file exporter. |
| exporters/prometheus/include/opentelemetry/exporters/prometheus/file_exporter_factory.h | Adds public factory header for the file exporter. |
| exporters/prometheus/CMakeLists.txt | Updates project version, adds new library target, and adds import/export macro wiring. |
| exporters/prometheus/BUILD | Adds Bazel cc_library target for the file exporter. |
| .github/workflows/prometheus.yml | Updates CI to test against opentelemetry-cpp v1.28.0. |
Suppressed comments (3)
exporters/prometheus/tools.cmake:44
- Same issue as the export path:
__attribute__((__dllimport__))is not the standard GCC/Clang attribute spelling. This likely results in no import decoration on Windows with MinGW/Clang.
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang|Intel|XL|XLClang")
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(${OUTPUT_VARNAME}
"__attribute__((__dllimport__))"
PARENT_SCOPE)
exporters/prometheus/src/file_exporter.cc:693
~PrometheusFileBackend()joins the background flush thread but never setsis_shutdownto stop it. The thread can run for up to 1 minute before exiting (idle timeout), so destroying the exporter can block for a long time ifShutdown()wasn’t called.
~PrometheusFileBackend()
{
if (file_)
{
file_->background_thread_waker_cv.notify_all();
std::unique_ptr<std::thread> background_flush_thread;
exporters/prometheus/src/file_exporter.cc:1089
CheckUpdate()updatesrotate_indexand callsResetLogFile()without holdingfile_lock, even thoughResetLogFile()explicitly assumes it is called under lock. This is a data race ifAddMetricData()can be invoked concurrently, and can also conflict withOpenLogFile()/RotateLog()which use the same state underfile_lock.
// Reset rotate index when directory changes
if (new_dir != old_dir)
{
file_->rotate_index = 0;
}
ResetLogFile();
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| class PrometheusFileExporter : public ::opentelemetry::sdk::metrics::PushMetricExporter | ||
| { |
7b153bb to
da9b374
Compare
|
Sorry for it's be a long time to update this package. Could you please review it again when you have time? @ThomsonTan @esigo @lalitb |
proost
left a comment
There was a problem hiding this comment.
Maintainers looks very busy, so i'd like to help out.
Can you add test cases for file exporter?
| return 0; | ||
| } | ||
|
|
||
| file.seekg(std::ios::end); |
There was a problem hiding this comment.
file.seekg(0, std::ios::end)
There was a problem hiding this comment.
Thanks, unit tests are added.
| std::string new_dir = FileSystemUtil::DirName(new_file_path); | ||
| std::string old_dir = FileSystemUtil::DirName(old_file_path); | ||
|
|
||
| // Reset rotate index when directory changes |
There was a problem hiding this comment.
Looks like we should hold lock in here to call ResetLogFile. Am i correct?
There was a problem hiding this comment.
It's not required to be very precise in file size calculation. So I changed all the variables in ResetLogFile tobe atomic.And no lock is reauired neither.
| file_->flushed_metric_family_count.store(0); | ||
| } | ||
|
|
||
| ~PrometheusFileBackend() |
There was a problem hiding this comment.
Are there no need to set "is_shutdown" to true?
There was a problem hiding this comment.
Thanks, is_shutdown is set now.
436105b to
ac28893
Compare
| std::lock_guard<std::mutex> lock_guard{file_->background_thread_lock}; | ||
| if (!file_->background_flush_thread) | ||
| { | ||
| break; |
There was a problem hiding this comment.
non-blocking; no background flush thread and "is_shutdown" is true, can we return earlier right?
There was a problem hiding this comment.
Sorry, I'm not sure I follow. When there's been no IO for a while, the background thread exits on its own, so it shouldn't matter whether it's explicitly shut down or not.
ba10b0e to
4156383
Compare
|
@proost Could you please review this PR again when you have time? Thanks. |
| bool ForceFlush(std::chrono::microseconds timeout) noexcept | ||
| { | ||
| std::chrono::microseconds wait_interval = timeout / 256; | ||
| if (wait_interval <= std::chrono::microseconds{0}) |
There was a problem hiding this comment.
non-blocking; Maybe guarding unrealistic too large value too?
There was a problem hiding this comment.
Max wait interval is added. And I also upgrade the upstream otel-cpp to 1.29. Could you please review again when you have time? @proost
692df86 to
e7c574b
Compare
e7c574b to
d54d8a5
Compare
| bazel --output_user_root=$HOME/.cache/bazel build --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... | ||
| bazel --output_user_root=$HOME/.cache/bazel test --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... | ||
| bazel --output_user_root=$HOME/.cache/bazel build --@io_opentelemetry_cpp//api:with_abseil //... | ||
| bazel --output_user_root=$HOME/.cache/bazel test --@io_opentelemetry_cpp//api:with_abseil //... |
There was a problem hiding this comment.
It looks like to me that the tests are now not actually being run especially when comparing the logs from this pr to https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/runs/35523736398/job/106334223469#step:4:1
|
@owent could you please take a look at resolving the conflicts. |
^ Conflicts: ^ exporters/prometheus/MODULE.bazel Update bazel modules Fixes bazel and cmake support Fixes prometheus linking Fixes document Fixes compatibility Fixes compatibility of localtime_s usage Make all variables in ResetLogFile atomic Add unit test for PrometheusFileExporter Merge concunrrency fixes from <open-telemetry/opentelemetry-cpp#4365> Update otel-cpp to 1.29.0 Limit max value for wait interval ^ Conflicts: ^ exporters/prometheus/MODULE.bazel ^ Conflicts: ^ .github/workflows/prometheus.yml ^ exporters/prometheus/.bazelversion ^ exporters/prometheus/CMakeLists.txt ^ exporters/prometheus/MODULE.bazel ^ exporters/prometheus/repository.bzl
d54d8a5 to
91b903a
Compare
Fixes test environment
91b903a to
e71e9d2
Compare
Conflicts are resolved, unit tests are enabled now. |
| @@ -44,17 +38,33 @@ jobs: | |||
| cache-name: bazel_cache | |||
| with: | |||
| path: /home/runner/.cache/bazel | |||
| key: bazel_${{ matrix.os }} | |||
| key: bazel_linux | |||
| - name: run build | |||
| working-directory: otel_cpp_contrib/exporters/prometheus | |||
| run: | | |||
| bazel --output_user_root=$HOME/.cache/bazel build --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... | |||
| bazel --output_user_root=$HOME/.cache/bazel build --@io_opentelemetry_cpp//api:with_abseil //... | |||
| bazel --output_user_root=$HOME/.cache/bazel test --test_output=all --@io_opentelemetry_cpp//api:with_abseil //... | |||
| prometheus_bazel_osx: | |||
| name: Bazel on MacOS | |||
| runs-on: macos-latest | |||
| steps: | |||
| - name: checkout otel contrib prometheus | |||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |||
| with: | |||
| persist-credentials: false | |||
| path: "otel_cpp_contrib" | |||
| - name: Mount Bazel Cache | |||
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |||
| env: | |||
| cache-name: bazel_cache | |||
| with: | |||
| path: /Users/runner/.cache/bazel | |||
| key: bazel_osx | |||
| - name: run tests | |||
| if: ${{ !startsWith(matrix.os, 'ubuntu') }} | |||
| working-directory: otel_cpp_contrib/exporters/prometheus | |||
| run: | | |||
| bazel --output_user_root=$HOME/.cache/bazel test --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... | |||
|
|
|||
| bazel --output_user_root=$HOME/.cache/bazel build --@io_opentelemetry_cpp//api:with_abseil //... | |||
| bazel --output_user_root=$HOME/.cache/bazel test --test_output=all --@io_opentelemetry_cpp//api:with_abseil //... | |||
There was a problem hiding this comment.
@owent can you put this back to running as a matrix
There was a problem hiding this comment.
I was about to ask about this too: what is the rationale for going back to 2 separate ci tasks ?
A matrix is easier to extend and avoids duplication.
| # Install both features before OpenTelemetry can build a pull-only dependency. | ||
| vcpkg install "prometheus-cpp[pull,push]" --triplet=x64-linux --classic |
There was a problem hiding this comment.
This shouldn't be needed as apt-packages install it without vcpkg
| cd "$GITHUB_WORKSPACE/otel_cpp/build_jobs_ci" | ||
| cmake .. \ | ||
| -G Ninja \ | ||
| -DWITH_PROMETHEUS=ON \ | ||
| -DWITH_METRICS_PREVIEW=OFF \ | ||
| -DBUILD_TESTING=OFF -DWITH_EXAMPLES=OFF -DOPENTELEMETRY_INSTALL=ON "-DWITH_FUNC_TESTS=OFF" | ||
| cmake --build . -j$(nproc) | ||
| cmake --install . --prefix="${GITHUB_WORKSPACE}/sandbox" | ||
| cmake .. -DOTELCPP_WITH_PROMETHEUS=ON -DCMAKE_BUILD_TYPE=Debug \ | ||
| -DVCPKG_TARGET_TRIPLET=x64-linux \ | ||
| "-DCMAKE_INSTALL_PREFIX=$HOME/prebuilt-otel" \ | ||
| "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" \ | ||
| "-DBUILD_TESTING=OFF" "-DOTELCPP_WITH_EXAMPLES=OFF" "-DOTELCPP_WITH_FUNC_TESTS=OFF" | ||
| cmake --build . -j --config Debug || cmake --build . -j2 --config Debug || cmake --build . --config Debug | ||
| cmake --install . --prefix "$HOME/prebuilt-otel" --config Debug | ||
| mkdir -p "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build_jobs_ci" | ||
| cd "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build_jobs_ci" | ||
| cmake .. \ | ||
| -G Ninja \ | ||
| -DCMAKE_PREFIX_PATH="${GITHUB_WORKSPACE}/sandbox" \ | ||
| -DCMAKE_BUILD_TYPE=Debug | ||
| cmake --build . -j$(nproc) | ||
| cmake .. "-DCMAKE_PREFIX_PATH=$HOME/prebuilt-otel" -DCMAKE_BUILD_TYPE=Debug \ | ||
| -DVCPKG_TARGET_TRIPLET=x64-linux \ | ||
| "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" \ | ||
| "-DVCPKG_MANIFEST_MODE=OFF" | ||
| cmake --build . -j --config Debug || cmake --build . -j2 --config Debug || cmake --build . --config Debug |
There was a problem hiding this comment.
Let's revert this so that we can maintain the native cmake ci.
If a vcpkg ci is wanted, let's add this as a dedicated job.
| bazel_dep(name = "abseil-cpp", version = "20260526.0", repo_name = "com_google_absl") | ||
| bazel_dep(name = "abseil-cpp", version = "20260107.1", repo_name = "com_google_absl") | ||
| bazel_dep(name = "opentelemetry-cpp", version = "1.29.0", repo_name = "io_opentelemetry_cpp") | ||
| bazel_dep(name = "prometheus-cpp", version = "1.3.0.bcr.3", repo_name = "com_github_jupp0r_prometheus_cpp") | ||
| bazel_dep(name = "prometheus-cpp", version = "1.3.0.bcr.2", repo_name = "com_github_jupp0r_prometheus_cpp") |
There was a problem hiding this comment.
Why are we downgrading
There was a problem hiding this comment.
| name = "opentelemetry-cpp-contrib-prometheus", | ||
| version = "1.19.0", | ||
| version = "1.29.0", | ||
| compatibility_level = 0, |
There was a problem hiding this comment.
| compatibility_level = 0, |
There was a problem hiding this comment.
Please remove compatibility_level. This is needed to upgrade bazel to 8.8.0.
| bazel_dep(name = "googletest", version = "1.18.0.bcr.1", dev_dependency = True, repo_name = "com_google_googletest") | ||
| bazel_dep(name = "googletest", version = "1.17.0.bcr.2", dev_dependency = True, repo_name = "com_google_googletest") |
There was a problem hiding this comment.
Why are we downgrading?
Thanks, but it looks like there is some code rolled back during conflict resolution. Please check, looking to merge this PR once makefiles and CI yaml files looks ok. |
Fixes #713