Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions tpu_sync/telemetry/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ cc_library(
# Disables Clang header modules due to incompatibility with prometheus-cpp / CivetWeb headers.
features = ["-use_header_modules"],
deps = [
":exporter_util",
":metrics_backend",
"@com_github_jupp0r_prometheus_cpp//core",
"@com_github_jupp0r_prometheus_cpp//pull",
Expand Down Expand Up @@ -114,6 +115,7 @@ cc_library(
srcs = ["buffered_metrics_exporter.cc"],
hdrs = ["buffered_metrics_exporter.h"],
deps = [
":exporter_util",
":metrics_backend",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_map",
Expand Down Expand Up @@ -190,3 +192,61 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "prometheus_shm_exporter",
srcs = ["prometheus_shm_exporter.cc"],
hdrs = ["prometheus_shm_exporter.h"],
# -fexceptions is required because prometheus-cpp Exposer throws C++
# exceptions (std::runtime_error) on socket binding and initialization failure.
copts = ["-fexceptions"],
# Disables Clang header modules due to incompatibility with prometheus-cpp / CivetWeb headers.
features = ["-use_header_modules"],
deps = [
":base_shm_exporter",
":exporter_util",
":label_util",
":metrics_backend",
"//tpu_sync/telemetry/shm:shm_collector",
"//tpu_sync/telemetry/shm:shm_layout",
"@com_github_jupp0r_prometheus_cpp//core",
"@com_github_jupp0r_prometheus_cpp//pull",
"@com_google_absl//absl/algorithm:container",
"@com_google_absl//absl/log",
"@com_google_absl//absl/strings",
],
)

cc_test(
name = "prometheus_shm_exporter_test",
srcs = ["prometheus_shm_exporter_test.cc"],
deps = [
":metrics_backend",
":prometheus_shm_exporter",
":test_util",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:string_view",
"@com_google_absl//absl/synchronization",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "exporter_util",
srcs = ["exporter_util.cc"],
hdrs = ["exporter_util.h"],
deps = [
"@com_google_absl//absl/strings",
],
)

cc_test(
name = "exporter_util_test",
srcs = ["exporter_util_test.cc"],
deps = [
":exporter_util",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:string_view",
"@com_google_googletest//:gtest_main",
],
)
13 changes: 6 additions & 7 deletions tpu_sync/telemetry/buffered_metrics_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "tpu_sync/telemetry/exporter_util.h"
#include "tpu_sync/telemetry/metrics_backend.h"

namespace tpu_raiden::telemetry {

namespace {

constexpr absl::string_view kMetricPrefix = "tpu_raiden_";

std::string EscapeLabelValue(absl::string_view value) {
std::string escaped;
escaped.reserve(value.size());
Expand Down Expand Up @@ -154,8 +153,8 @@ BufferedMetricsExporter::GetAndResetMetricSamples() {
LockFreeCounterAccumulator* counter) {
uint64_t delta = counter->ExchangeAndReset();
if (delta > 0) {
std::string full_name =
absl::StrCat(kMetricPrefix, name, canonical_labels);
const std::string full_name =
absl::StrCat(kPrometheusMetricPrefix, name, canonical_labels);
result[full_name].push_back(static_cast<double>(delta));
}
});
Expand All @@ -166,8 +165,8 @@ BufferedMetricsExporter::GetAndResetMetricSamples() {
[&](absl::string_view canonical_labels, QueueBuffer<>* gauge) {
std::vector<double> samples = gauge->ExtractAndReset();
if (!samples.empty()) {
std::string full_name =
absl::StrCat(kMetricPrefix, name, canonical_labels);
const std::string full_name =
absl::StrCat(kPrometheusMetricPrefix, name, canonical_labels);
result[full_name] = std::move(samples);
}
});
Expand All @@ -179,7 +178,7 @@ BufferedMetricsExporter::GetAndResetMetricSamples() {
std::vector<double> samples = histogram->ExtractAndReset();
if (!samples.empty()) {
std::string full_name =
absl::StrCat(kMetricPrefix, name, canonical_labels);
absl::StrCat(kPrometheusMetricPrefix, name, canonical_labels);
result[full_name] = std::move(samples);
}
});
Expand Down
32 changes: 32 additions & 0 deletions tpu_sync/telemetry/exporter_util.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2026 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tpu_sync/telemetry/exporter_util.h"

#include <string>

#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"

namespace tpu_raiden::telemetry {

std::string JoinHostPort(absl::string_view host, int port) {
if (absl::StrContains(host, ':') && !absl::StartsWith(host, "[")) {
return absl::StrCat("[", host, "]:", port);
}
return absl::StrCat(host, ":", port);
}

} // namespace tpu_raiden::telemetry
40 changes: 40 additions & 0 deletions tpu_sync/telemetry/exporter_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2026 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef THIRD_PARTY_TPU_RAIDEN_TPU_SYNC_TELEMETRY_EXPORTER_UTIL_H_
#define THIRD_PARTY_TPU_RAIDEN_TPU_SYNC_TELEMETRY_EXPORTER_UTIL_H_

#include <string>

#include "absl/strings/string_view.h"

namespace tpu_raiden::telemetry {

// Common metric namespace prefix prepended to all Prometheus metric family
// names.
inline constexpr absl::string_view kPrometheusMetricPrefix = "tpu_raiden_";

// Reserved Prometheus histogram bucket upper-bound label ("less than or
// equal").
inline constexpr absl::string_view kPrometheusLeLabel = "le";

// Formats a host string and port into a valid endpoint address (e.g.
// "127.0.0.1:8080"). If the host contains ':' and is not already bracketed
// (IPv6 address), it wraps the host in brackets (e.g. "[::1]:8080") per RFC
// 3986.
std::string JoinHostPort(absl::string_view host, int port);

} // namespace tpu_raiden::telemetry

#endif // THIRD_PARTY_TPU_RAIDEN_TPU_SYNC_TELEMETRY_EXPORTER_UTIL_H_
54 changes: 54 additions & 0 deletions tpu_sync/telemetry/exporter_util_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2026 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tpu_sync/telemetry/exporter_util.h"

#include <gtest/gtest.h>
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"

namespace tpu_raiden::telemetry {
namespace {

TEST(ExporterUtilTest, JoinHostPort) {
struct TestCase {
absl::string_view host;
int port;
absl::string_view expected;
};

constexpr TestCase kTestCases[] = {
// Standard IPv4
{"127.0.0.1", 8080, "127.0.0.1:8080"},
{"0.0.0.0", 9090, "0.0.0.0:9090"},
// IPv6 without brackets (must be bracketed per RFC 3986)
{"::1", 8080, "[::1]:8080"},
{"2001:db8::1", 9090, "[2001:db8::1]:9090"},
// Pre-bracketed IPv6 (must not be double-bracketed)
{"[::1]", 8080, "[::1]:8080"},
{"[2001:db8::1]", 9090, "[2001:db8::1]:9090"},
// Edge cases
{"", 8080, ":8080"},
{"localhost", 0, "localhost:0"},
{"localhost", 65535, "localhost:65535"},
};

for (const auto& [host, port, expected] : kTestCases) {
SCOPED_TRACE(absl::StrCat("host: '", host, "', port: ", port));
EXPECT_EQ(JoinHostPort(host, port), expected);
}
}

} // namespace
} // namespace tpu_raiden::telemetry
16 changes: 4 additions & 12 deletions tpu_sync/telemetry/prometheus_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,15 @@
#include "prometheus/text_serializer.h"
#include "absl/container/flat_hash_map.h"
#include "absl/log/log.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "tpu_sync/telemetry/exporter_util.h"
#include "tpu_sync/telemetry/metrics_backend.h"

namespace tpu_raiden::telemetry {

namespace {

constexpr absl::string_view kMetricPrefix = "tpu_raiden_";

std::map<std::string, std::string> ConvertLabels(LabelSpan labels) {
if (labels.empty()) {
return {};
Expand All @@ -52,13 +50,6 @@ std::map<std::string, std::string> ConvertLabels(LabelSpan labels) {
return result;
}

std::string JoinHostPort(absl::string_view host, int port) {
if (absl::StrContains(host, ':') && !absl::StartsWith(host, "[")) {
return absl::StrCat("[", host, "]:", port);
}
return absl::StrCat(host, ":", port);
}

} // namespace

void PrometheusExporter::RegisterKnownFamilies() {
Expand All @@ -68,7 +59,8 @@ void PrometheusExporter::RegisterKnownFamilies() {
histogram_families_.contains(meta.name)) {
continue;
}
std::string prometheus_name = absl::StrCat(kMetricPrefix, meta.name);
const std::string prometheus_name =
absl::StrCat(kPrometheusMetricPrefix, meta.name);
switch (meta.type) {
case MetricType::kCounter: {
auto* family = &prometheus::BuildCounter()
Expand Down Expand Up @@ -118,7 +110,7 @@ PrometheusExporter::PrometheusExporter(const ExporterOptions& options)
<< ": " << e.what();
exposer_.reset();
}
} else if (options_.port != 0) {
} else if (options_.port > 0) {
LOG(WARNING) << "Invalid port configured for Prometheus HTTP exporter: "
<< options_.port << ". Expected port in range [" << kMinPort
<< ", " << kMaxPort << "].";
Expand Down
Loading
Loading