1717#include " google/cloud/bigtable/internal/metrics.h"
1818#include " google/cloud/bigtable/version.h"
1919#include " absl/strings/charconv.h"
20+ #include " absl/strings/escaping.h"
2021#include " absl/strings/match.h"
2122#include " absl/strings/numbers.h"
2223#include " absl/strings/str_split.h"
@@ -38,13 +39,23 @@ auto constexpr kMeterInstrumentationScopeVersion = "v1";
3839// to the map should be more performant than performing a set_difference every
3940// time.
4041LabelMap IntoLabelMap (ResourceLabels const & r, DataLabels const & d,
41- std::set<std::string> const & filtered_data_labels) {
42+ std::set<std::string> const & filtered_data_labels,
43+ std::optional<PeerInfoLabels> const & peer_info_labels) {
4244 LabelMap labels = {
4345 {" project_id" , r.project_id },
4446 {" instance" , r.instance },
4547 {" table" , r.table },
4648 {" cluster" , r.cluster .empty () ? " <unspecified>" : r.cluster },
4749 {" zone" , r.zone .empty () ? " global" : r.zone }};
50+
51+ if (peer_info_labels) {
52+ labels.insert ({
53+ {" transport_type" , peer_info_labels->transport_type },
54+ {" transport_region" , peer_info_labels->transport_region },
55+ {" transport_subzone" , peer_info_labels->transport_subzone },
56+ });
57+ }
58+
4859 std::map<std::string, std::string> data = {{
4960 {" method" , d.method },
5061 {" streaming" , d.streaming },
@@ -74,6 +85,7 @@ LabelMap IntoLabelMap(ResourceLabels const& r, DataLabels const& d,
7485 std::set_difference (data.begin (), data.end (), filtered_data_labels.begin (),
7586 filtered_data_labels.end (),
7687 std::inserter (labels, labels.begin ()), Compare ());
88+
7789 return labels;
7890}
7991
@@ -103,6 +115,33 @@ GetResponseParamsFromTrailingMetadata(
103115 return absl::nullopt ;
104116}
105117
118+ std::optional<google::bigtable::v2::PeerInfo> GetPeerInfoFromServerMetadata (
119+ grpc::ClientContext const & client_context) {
120+ // The peer info is sent in the initial metadata and encoded in WebSafeBase64.
121+ std::string decoded;
122+ auto const & init_metadata = client_context.GetServerInitialMetadata ();
123+ auto iter_init = init_metadata.find (" bigtable-peer-info" );
124+ if (iter_init == init_metadata.end () ||
125+ !absl::WebSafeBase64Unescape (
126+ absl::string_view{iter_init->second .data (), iter_init->second .size ()},
127+ &decoded)) {
128+ // Find it in trailing metadata if not found in initial metadata or failed
129+ // to decode.
130+ auto const & trailing_metadata = client_context.GetServerTrailingMetadata ();
131+ auto iter_trailing = trailing_metadata.find (" bigtable-peer-info" );
132+ if (iter_trailing == trailing_metadata.end () ||
133+ !absl::WebSafeBase64Unescape (
134+ absl::string_view{iter_trailing->second .data (),
135+ iter_trailing->second .size ()},
136+ &decoded)) {
137+ return std::nullopt ;
138+ }
139+ }
140+ google::bigtable::v2::PeerInfo p;
141+ if (p.ParseFromString (decoded)) return p;
142+ return std::nullopt ;
143+ }
144+
106145absl::optional<double > GetServerLatencyFromInitialMetadata (
107146 grpc::ClientContext const & client_context) {
108147 auto const & initial_metadata = client_context.GetServerInitialMetadata ();
@@ -199,7 +238,7 @@ AttemptLatency::AttemptLatency(
199238
200239void AttemptLatency::PreCall (opentelemetry::context::Context const &,
201240 PreCallParams const & p) {
202- attempt_start_ = std::move ( p.attempt_start ) ;
241+ attempt_start_ = p.attempt_start ;
203242}
204243
205244void AttemptLatency::PostCall (opentelemetry::context::Context const & context,
@@ -225,6 +264,56 @@ std::unique_ptr<Metric> AttemptLatency::clone(ResourceLabels resource_labels,
225264 return m;
226265}
227266
267+ AttemptLatency2::AttemptLatency2 (
268+ std::string const & instrumentation_scope,
269+ opentelemetry::nostd::shared_ptr<
270+ opentelemetry::metrics::MeterProvider> const & provider)
271+ : attempt_latencies2_(provider
272+ ->GetMeter (instrumentation_scope,
273+ kMeterInstrumentationScopeVersion )
274+ ->CreateDoubleHistogram(" attempt_latencies2" )) {}
275+
276+ void AttemptLatency2::PreCall (opentelemetry::context::Context const &,
277+ PreCallParams const & p) {
278+ attempt_start_ = p.attempt_start ;
279+ }
280+
281+ void AttemptLatency2::PostCall (opentelemetry::context::Context const & context,
282+ grpc::ClientContext const & client_context,
283+ PostCallParams const & p) {
284+ auto response_params = GetResponseParamsFromTrailingMetadata (client_context);
285+ if (response_params) {
286+ resource_labels_.cluster = response_params->cluster_id ();
287+ resource_labels_.zone = response_params->zone_id ();
288+ }
289+
290+ auto peer_info = GetPeerInfoFromServerMetadata (client_context);
291+ peer_info_labels_.transport_type =
292+ absl::AsciiStrToLower (google::bigtable::v2::PeerInfo::TransportType_Name (
293+ peer_info ? peer_info->transport_type ()
294+ : google::bigtable::v2::PeerInfo::TRANSPORT_TYPE_UNKNOWN));
295+ if (peer_info) {
296+ peer_info_labels_.transport_region =
297+ peer_info->application_frontend_region ();
298+ peer_info_labels_.transport_subzone =
299+ peer_info->application_frontend_subzone ();
300+ }
301+
302+ data_labels_.status = StatusCodeToString (p.attempt_status .code ());
303+ auto attempt_elapsed = std::chrono::duration_cast<LatencyDuration>(
304+ p.attempt_end - attempt_start_);
305+ auto m = IntoLabelMap (resource_labels_, data_labels_, {}, peer_info_labels_);
306+ attempt_latencies2_->Record (attempt_elapsed.count (), std::move (m), context);
307+ }
308+
309+ std::unique_ptr<Metric> AttemptLatency2::clone (ResourceLabels resource_labels,
310+ DataLabels data_labels) const {
311+ auto m = std::make_unique<AttemptLatency2>(*this );
312+ m->resource_labels_ = std::move (resource_labels);
313+ m->data_labels_ = std::move (data_labels);
314+ return m;
315+ }
316+
228317RetryCount::RetryCount (
229318 std::string const & instrumentation_scope,
230319 opentelemetry::nostd::shared_ptr<
0 commit comments