Skip to content

[PROMETHEUS] Upgrade otelcpp to 1.29, add prometheus file exporter - #646

Open
owent wants to merge 3 commits into
open-telemetry:mainfrom
owent:prometheus_exporters
Open

owent wants to merge 3 commits into
open-telemetry:mainfrom
owent:prometheus_exporters

Conversation

@owent

@owent owent commented Aug 5, 2026

Copy link
Copy Markdown
Member

Fixes #713

  • Fixes some thread-safety problems.
  • Implement prometheus file exporter.
  • Upgrade otelcpp to 1.28.

Copilot AI lite review requested due to automatic review settings August 5, 2026 07:19
@owent
owent requested a review from a team as a code owner August 5, 2026 07:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_info and without_otel_scope flags.

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 sets is_shutdown to 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 if Shutdown() 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() updates rotate_index and calls ResetLogFile() without holding file_lock, even though ResetLogFile() explicitly assumes it is called under lock. This is a data race if AddMetricData() can be invoked concurrently, and can also conflict with OpenLogFile()/RotateLog() which use the same state under file_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.

Comment thread exporters/prometheus/tools.cmake
Comment thread exporters/prometheus/tools.cmake Outdated
Comment thread exporters/prometheus/src/file_exporter.cc Outdated
Comment on lines +26 to +27
class PrometheusFileExporter : public ::opentelemetry::sdk::metrics::PushMetricExporter
{

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not public header

Comment thread exporters/prometheus/src/file_exporter_factory.cc
Comment thread exporters/prometheus/vcpkg.json
@owent

owent commented Aug 9, 2026

Copy link
Copy Markdown
Member Author

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 proost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file.seekg(0, std::ios::end)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we should hold lock in here to call ResetLogFile. Am i correct?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there no need to set "is_shutdown" to true?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, is_shutdown is set now.

@owent
owent force-pushed the prometheus_exporters branch from 436105b to ac28893 Compare August 17, 2026 06:21
std::lock_guard<std::mutex> lock_guard{file_->background_thread_lock};
if (!file_->background_flush_thread)
{
break;

@proost proost Aug 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-blocking; no background flush thread and "is_shutdown" is true, can we return earlier right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@owent
owent force-pushed the prometheus_exporters branch from ba10b0e to 4156383 Compare August 20, 2026 06:18
@owent
owent requested a review from proost September 15, 2026 03:07
@owent

owent commented Sep 15, 2026

Copy link
Copy Markdown
Member Author

@proost Could you please review this PR again when you have time? Thanks.

@proost proost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

bool ForceFlush(std::chrono::microseconds timeout) noexcept
{
std::chrono::microseconds wait_interval = timeout / 256;
if (wait_interval <= std::chrono::microseconds{0})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-blocking; Maybe guarding unrealistic too large value too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@owent
owent force-pushed the prometheus_exporters branch 2 times, most recently from 692df86 to e7c574b Compare September 18, 2026 05:01
@owent owent changed the title [PROMETHEUS] Upgrade otelcpp to 1.28, add prometheus file exporter [PROMETHEUS] Upgrade otelcpp to 1.29, add prometheus file exporter Sep 18, 2026
@owent
owent force-pushed the prometheus_exporters branch from e7c574b to d54d8a5 Compare September 18, 2026 06:15

@proost proost left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread .github/workflows/prometheus.yml Outdated
Comment on lines +61 to +60
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 //...

@thompson-tomo thompson-tomo Sep 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@thompson-tomo

Copy link
Copy Markdown
Contributor

@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
@owent
owent force-pushed the prometheus_exporters branch from d54d8a5 to 91b903a Compare September 22, 2026 08:28
@github-actions github-actions Bot added the exporter:prometheus Prometheus Exporter label Sep 22, 2026
@owent

owent commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

@owent could you please take a look at resolving the conflicts.

Conflicts are resolved, unit tests are enabled now.

Comment on lines 26 to +67
@@ -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 //...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@owent can you put this back to running as a matrix

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@owent

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.

Comment on lines +131 to +132
# Install both features before OpenTelemetry can build a pull-only dependency.
vcpkg install "prometheus-cpp[pull,push]" --triplet=x64-linux --classic

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be needed as apt-packages install it without vcpkg

Comment on lines 136 to +150
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread exporters/prometheus/CMakeLists.txt
Comment on lines -10 to +13
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")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we downgrading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a bad merge.

@owent

Please fix.

name = "opentelemetry-cpp-contrib-prometheus",
version = "1.19.0",
version = "1.29.0",
compatibility_level = 0,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
compatibility_level = 0,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@owent

Please remove compatibility_level. This is needed to upgrade bazel to 8.8.0.

Comment thread exporters/prometheus/MODULE.bazel
Comment on lines -14 to +16
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")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we downgrading?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@owent

Please fix.

@marcalff

Copy link
Copy Markdown
Member

@owent could you please take a look at resolving the conflicts.

Conflicts are resolved, unit tests are enabled now.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

exporter:prometheus Prometheus Exporter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prometheus tests are disabled on ubuntu

5 participants