Skip to content
Open
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
56 changes: 56 additions & 0 deletions tpu_raiden/telemetry/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# 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.

# Copyright 2026 Google LLC

load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")

package(default_visibility = ["//visibility:public"])

licenses(["notice"])

cc_library(
name = "metrics_api",
srcs = ["metrics_api.cc"],
hdrs = ["metrics_api.h"],
copts = [
"-fno-strict-aliasing",
"-fexceptions",
],
# -use_header_modules required due to -fexceptions mismatch with precompiled header modules.
features = ["-use_header_modules"],
deps = [
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/log",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/types:span",
],
)

cc_test(
name = "metrics_api_test",
srcs = ["metrics_api_test.cc"],
copts = [
"-fno-strict-aliasing",
"-fexceptions",
],
# -use_header_modules required due to -fexceptions mismatch with precompiled header modules.
features = ["-use_header_modules"],
deps = [
":metrics_api",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
],
)
151 changes: 151 additions & 0 deletions tpu_raiden/telemetry/metrics_api.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// 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.

// 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_raiden/telemetry/metrics_api.h"

#include <atomic>
#include <cstdint>
#include <exception>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"

namespace tpu_raiden::telemetry {

RaidenMetricStore& RaidenMetricStore::GetGlobalMetricStore() {
static RaidenMetricStore* global_store = new RaidenMetricStore();
return *global_store;
}

void RaidenMetricStore::AddBackend(
std::shared_ptr<MetricsBackend> backend) noexcept {
if (!backend) return;
absl::MutexLock lock(mutex_);
for (const auto& b : backends_) {
if (b == backend) return;
}
backends_.push_back(std::move(backend));
has_backends_.store(true, std::memory_order_release);
}

void RaidenMetricStore::ClearBackends() noexcept {
absl::MutexLock lock(mutex_);
backends_.clear();
has_backends_.store(false, std::memory_order_release);
}

bool RaidenMetricStore::HasBackends() const noexcept {
return has_backends_.load(std::memory_order_relaxed);
}

void RaidenMetricStore::IncrementCounter(absl::string_view name, uint64_t val,
LabelSpan labels) noexcept {
if (!has_backends_.load(std::memory_order_relaxed)) return;
absl::MutexLock lock(mutex_);
if (backends_.empty()) return;
for (const auto& backend : backends_) {
try {
backend->IncrementCounter(name, val, labels);
} catch (const std::exception& e) {
LOG_EVERY_N_SEC(ERROR, 10) << "RaidenMetricStore::IncrementCounter "
"swallowed exception for metric '"
<< name << "': " << e.what();
} catch (...) {
LOG_EVERY_N_SEC(ERROR, 10) << "RaidenMetricStore::IncrementCounter "
"swallowed unknown exception for metric '"
<< name << "'";
}
}
}

void RaidenMetricStore::SetGauge(absl::string_view name, int64_t val,
LabelSpan labels) noexcept {
if (!has_backends_.load(std::memory_order_relaxed)) return;
absl::MutexLock lock(mutex_);
if (backends_.empty()) return;
for (const auto& backend : backends_) {
try {
backend->SetGauge(name, val, labels);
} catch (const std::exception& e) {
LOG_EVERY_N_SEC(ERROR, 10)
<< "RaidenMetricStore::SetGauge swallowed exception for metric '"
<< name << "': " << e.what();
} catch (...) {
LOG_EVERY_N_SEC(ERROR, 10) << "RaidenMetricStore::SetGauge swallowed "
"unknown exception for metric '"
<< name << "'";
}
}
}

void RaidenMetricStore::ObserveHistogram(absl::string_view name, double val,
LabelSpan labels) noexcept {
if (!has_backends_.load(std::memory_order_relaxed)) return;
absl::MutexLock lock(mutex_);
if (backends_.empty()) return;
for (const auto& backend : backends_) {
try {
backend->ObserveHistogram(name, val, labels);
} catch (const std::exception& e) {
LOG_EVERY_N_SEC(ERROR, 10) << "RaidenMetricStore::ObserveHistogram "
"swallowed exception for metric '"
<< name << "': " << e.what();
} catch (...) {
LOG_EVERY_N_SEC(ERROR, 10) << "RaidenMetricStore::ObserveHistogram "
"swallowed unknown exception for metric '"
<< name << "'";
}
}
}

std::string RaidenMetricStore::GetTextSnapshot() {
if (!has_backends_.load(std::memory_order_relaxed)) return "";
absl::MutexLock lock(mutex_);
std::string result;
for (const auto& backend : backends_) {
try {
absl::StrAppend(&result, backend->GetTextSnapshot());
} catch (const std::exception& e) {
LOG_EVERY_N_SEC(ERROR, 10)
<< "RaidenMetricStore::GetTextSnapshot swallowed exception: "
<< e.what();
} catch (...) {
LOG_EVERY_N_SEC(ERROR, 10)
<< "RaidenMetricStore::GetTextSnapshot swallowed unknown exception";
}
}
return result;
}

} // namespace tpu_raiden::telemetry
126 changes: 126 additions & 0 deletions tpu_raiden/telemetry/metrics_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// 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.

// 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_RAIDEN_TELEMETRY_METRICS_API_H_
#define THIRD_PARTY_TPU_RAIDEN_TPU_RAIDEN_TELEMETRY_METRICS_API_H_

#include <atomic>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/optimization.h"
#include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/types/span.h"

namespace tpu_raiden::telemetry {

namespace metrics {
inline constexpr absl::string_view kMetricSentBytesTotal =
"tpu_raiden_sent_bytes_total";
inline constexpr absl::string_view kMetricReceivedBytesTotal =
"tpu_raiden_received_bytes_total";
inline constexpr absl::string_view kMetricTransferDurationSeconds =
"tpu_raiden_transfer_duration_seconds";
inline constexpr absl::string_view kMetricStageLatencySeconds =
"tpu_raiden_stage_latency_seconds";
inline constexpr absl::string_view kMetricActiveTransfers =
"tpu_raiden_active_transfers";
inline constexpr absl::string_view kMetricBufferOccupancyBytes =
"tpu_raiden_buffer_occupancy_bytes";
inline constexpr absl::string_view kMetricTransferFailuresTotal =
"tpu_raiden_transfer_failures_total";
} // namespace metrics

// Allocation-free label view span type definition
using LabelSpan =
absl::Span<const std::pair<absl::string_view, absl::string_view>>;

// Abstract Dual-Backend Interface
class MetricsBackend {
public:
virtual ~MetricsBackend() = default;

virtual void IncrementCounter(absl::string_view name, uint64_t val = 1,
LabelSpan labels = {}) = 0;

virtual void SetGauge(absl::string_view name, int64_t val,
LabelSpan labels = {}) = 0;

virtual void ObserveHistogram(absl::string_view name, double val,
LabelSpan labels = {}) = 0;

virtual std::string GetTextSnapshot() = 0;
};

// Central Telemetry Facade with Multi-Backend Support & Fast-Path Exit
class RaidenMetricStore {
public:
static RaidenMetricStore& GetGlobalMetricStore();

RaidenMetricStore() = default;
~RaidenMetricStore() = default;

RaidenMetricStore(const RaidenMetricStore&) = delete;
RaidenMetricStore& operator=(const RaidenMetricStore&) = delete;

// Register one or more backends
void AddBackend(std::shared_ptr<MetricsBackend> backend) noexcept;

// Clear backends to disable telemetry instantly
void ClearBackends() noexcept;

// Returns whether any backends are registered
bool HasBackends() const noexcept;

// Telemetry API methods
void IncrementCounter(absl::string_view name, uint64_t val = 1,
LabelSpan labels = {}) noexcept;

void SetGauge(absl::string_view name, int64_t val,
LabelSpan labels = {}) noexcept;

void ObserveHistogram(absl::string_view name, double val,
LabelSpan labels = {}) noexcept;

std::string GetTextSnapshot();

private:
mutable absl::Mutex mutex_;
std::vector<std::shared_ptr<MetricsBackend>> backends_
ABSL_GUARDED_BY(mutex_);
std::atomic<bool> has_backends_{false};
};

} // namespace tpu_raiden::telemetry

#endif // THIRD_PARTY_TPU_RAIDEN_TPU_RAIDEN_TELEMETRY_METRICS_API_H_
Loading
Loading