1*cc02d7e2SAndroid Build Coastguard Worker //
2*cc02d7e2SAndroid Build Coastguard Worker // Copyright 2022 gRPC authors.
3*cc02d7e2SAndroid Build Coastguard Worker //
4*cc02d7e2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*cc02d7e2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*cc02d7e2SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*cc02d7e2SAndroid Build Coastguard Worker //
8*cc02d7e2SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
9*cc02d7e2SAndroid Build Coastguard Worker //
10*cc02d7e2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*cc02d7e2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*cc02d7e2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*cc02d7e2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*cc02d7e2SAndroid Build Coastguard Worker // limitations under the License.
15*cc02d7e2SAndroid Build Coastguard Worker //
16*cc02d7e2SAndroid Build Coastguard Worker
17*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/port_platform.h>
18*cc02d7e2SAndroid Build Coastguard Worker
19*cc02d7e2SAndroid Build Coastguard Worker #include <stdint.h>
20*cc02d7e2SAndroid Build Coastguard Worker
21*cc02d7e2SAndroid Build Coastguard Worker #include <algorithm>
22*cc02d7e2SAndroid Build Coastguard Worker #include <map>
23*cc02d7e2SAndroid Build Coastguard Worker #include <memory>
24*cc02d7e2SAndroid Build Coastguard Worker #include <string>
25*cc02d7e2SAndroid Build Coastguard Worker #include <utility>
26*cc02d7e2SAndroid Build Coastguard Worker #include <vector>
27*cc02d7e2SAndroid Build Coastguard Worker
28*cc02d7e2SAndroid Build Coastguard Worker #include "absl/status/status.h"
29*cc02d7e2SAndroid Build Coastguard Worker #include "absl/status/statusor.h"
30*cc02d7e2SAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
31*cc02d7e2SAndroid Build Coastguard Worker #include "absl/time/clock.h"
32*cc02d7e2SAndroid Build Coastguard Worker #include "absl/time/time.h"
33*cc02d7e2SAndroid Build Coastguard Worker #include "absl/types/optional.h"
34*cc02d7e2SAndroid Build Coastguard Worker #include "google/api/monitored_resource.pb.h"
35*cc02d7e2SAndroid Build Coastguard Worker #include "google/devtools/cloudtrace/v2/tracing.grpc.pb.h"
36*cc02d7e2SAndroid Build Coastguard Worker #include "google/monitoring/v3/metric_service.grpc.pb.h"
37*cc02d7e2SAndroid Build Coastguard Worker #include "opencensus/exporters/stats/stackdriver/stackdriver_exporter.h"
38*cc02d7e2SAndroid Build Coastguard Worker #include "opencensus/exporters/trace/stackdriver/stackdriver_exporter.h"
39*cc02d7e2SAndroid Build Coastguard Worker #include "opencensus/stats/stats.h"
40*cc02d7e2SAndroid Build Coastguard Worker #include "opencensus/trace/sampler.h"
41*cc02d7e2SAndroid Build Coastguard Worker #include "opencensus/trace/trace_config.h"
42*cc02d7e2SAndroid Build Coastguard Worker
43*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/grpc.h>
44*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/channel.h>
45*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/ext/gcp_observability.h>
46*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/opencensus.h>
47*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/security/credentials.h>
48*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/channel_arguments.h>
49*cc02d7e2SAndroid Build Coastguard Worker
50*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/ext/filters/logging/logging_filter.h"
51*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/crash.h"
52*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/notification.h"
53*cc02d7e2SAndroid Build Coastguard Worker #include "src/cpp/client/client_stats_interceptor.h"
54*cc02d7e2SAndroid Build Coastguard Worker #include "src/cpp/ext/filters/census/client_filter.h"
55*cc02d7e2SAndroid Build Coastguard Worker #include "src/cpp/ext/filters/census/grpc_plugin.h"
56*cc02d7e2SAndroid Build Coastguard Worker #include "src/cpp/ext/filters/census/open_census_call_tracer.h"
57*cc02d7e2SAndroid Build Coastguard Worker #include "src/cpp/ext/gcp/environment_autodetect.h"
58*cc02d7e2SAndroid Build Coastguard Worker #include "src/cpp/ext/gcp/observability_config.h"
59*cc02d7e2SAndroid Build Coastguard Worker #include "src/cpp/ext/gcp/observability_logging_sink.h"
60*cc02d7e2SAndroid Build Coastguard Worker
61*cc02d7e2SAndroid Build Coastguard Worker namespace grpc {
62*cc02d7e2SAndroid Build Coastguard Worker
63*cc02d7e2SAndroid Build Coastguard Worker namespace internal {
64*cc02d7e2SAndroid Build Coastguard Worker namespace {
65*cc02d7e2SAndroid Build Coastguard Worker
66*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::ObservabilityLoggingSink* g_logging_sink = nullptr;
67*cc02d7e2SAndroid Build Coastguard Worker
68*cc02d7e2SAndroid Build Coastguard Worker bool g_gcp_observability_initialized = false;
69*cc02d7e2SAndroid Build Coastguard Worker
70*cc02d7e2SAndroid Build Coastguard Worker // TODO(yashykt): These constants are currently derived from the example at
71*cc02d7e2SAndroid Build Coastguard Worker // https://cloud.google.com/traffic-director/docs/observability-proxyless#c++.
72*cc02d7e2SAndroid Build Coastguard Worker // We might want these to be configurable.
73*cc02d7e2SAndroid Build Coastguard Worker constexpr uint32_t kMaxAttributes = 128;
74*cc02d7e2SAndroid Build Coastguard Worker constexpr uint32_t kMaxAnnotations = 128;
75*cc02d7e2SAndroid Build Coastguard Worker constexpr uint32_t kMaxMessageEvents = 128;
76*cc02d7e2SAndroid Build Coastguard Worker constexpr uint32_t kMaxLinks = 128;
77*cc02d7e2SAndroid Build Coastguard Worker
78*cc02d7e2SAndroid Build Coastguard Worker constexpr char kGoogleStackdriverTraceAddress[] = "cloudtrace.googleapis.com";
79*cc02d7e2SAndroid Build Coastguard Worker constexpr char kGoogleStackdriverStatsAddress[] = "monitoring.googleapis.com";
80*cc02d7e2SAndroid Build Coastguard Worker
RegisterOpenCensusViewsForGcpObservability()81*cc02d7e2SAndroid Build Coastguard Worker void RegisterOpenCensusViewsForGcpObservability() {
82*cc02d7e2SAndroid Build Coastguard Worker // Register client default views for GCP observability
83*cc02d7e2SAndroid Build Coastguard Worker experimental::ClientStartedRpcs().RegisterForExport();
84*cc02d7e2SAndroid Build Coastguard Worker experimental::ClientCompletedRpcs().RegisterForExport();
85*cc02d7e2SAndroid Build Coastguard Worker experimental::ClientRoundtripLatency().RegisterForExport();
86*cc02d7e2SAndroid Build Coastguard Worker internal::ClientApiLatency().RegisterForExport();
87*cc02d7e2SAndroid Build Coastguard Worker experimental::ClientSentCompressedMessageBytesPerRpc().RegisterForExport();
88*cc02d7e2SAndroid Build Coastguard Worker experimental::ClientReceivedCompressedMessageBytesPerRpc()
89*cc02d7e2SAndroid Build Coastguard Worker .RegisterForExport();
90*cc02d7e2SAndroid Build Coastguard Worker // Register server default views for GCP observability
91*cc02d7e2SAndroid Build Coastguard Worker experimental::ServerStartedRpcs().RegisterForExport();
92*cc02d7e2SAndroid Build Coastguard Worker experimental::ServerCompletedRpcs().RegisterForExport();
93*cc02d7e2SAndroid Build Coastguard Worker experimental::ServerSentCompressedMessageBytesPerRpc().RegisterForExport();
94*cc02d7e2SAndroid Build Coastguard Worker experimental::ServerReceivedCompressedMessageBytesPerRpc()
95*cc02d7e2SAndroid Build Coastguard Worker .RegisterForExport();
96*cc02d7e2SAndroid Build Coastguard Worker experimental::ServerServerLatency().RegisterForExport();
97*cc02d7e2SAndroid Build Coastguard Worker }
98*cc02d7e2SAndroid Build Coastguard Worker
99*cc02d7e2SAndroid Build Coastguard Worker } // namespace
100*cc02d7e2SAndroid Build Coastguard Worker
GcpObservabilityInit()101*cc02d7e2SAndroid Build Coastguard Worker absl::Status GcpObservabilityInit() {
102*cc02d7e2SAndroid Build Coastguard Worker auto config = grpc::internal::GcpObservabilityConfig::ReadFromEnv();
103*cc02d7e2SAndroid Build Coastguard Worker if (!config.ok()) {
104*cc02d7e2SAndroid Build Coastguard Worker return config.status();
105*cc02d7e2SAndroid Build Coastguard Worker }
106*cc02d7e2SAndroid Build Coastguard Worker if (!config->cloud_trace.has_value() &&
107*cc02d7e2SAndroid Build Coastguard Worker !config->cloud_monitoring.has_value() &&
108*cc02d7e2SAndroid Build Coastguard Worker !config->cloud_logging.has_value()) {
109*cc02d7e2SAndroid Build Coastguard Worker return absl::OkStatus();
110*cc02d7e2SAndroid Build Coastguard Worker }
111*cc02d7e2SAndroid Build Coastguard Worker if (g_gcp_observability_initialized) {
112*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Crash("GCP Observability for gRPC was already initialized.");
113*cc02d7e2SAndroid Build Coastguard Worker }
114*cc02d7e2SAndroid Build Coastguard Worker g_gcp_observability_initialized = true;
115*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::EnvironmentAutoDetect::Create(config->project_id);
116*cc02d7e2SAndroid Build Coastguard Worker if (!config->cloud_trace.has_value()) {
117*cc02d7e2SAndroid Build Coastguard Worker // Disable OpenCensus tracing
118*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::EnableOpenCensusTracing(false);
119*cc02d7e2SAndroid Build Coastguard Worker }
120*cc02d7e2SAndroid Build Coastguard Worker if (!config->cloud_monitoring.has_value()) {
121*cc02d7e2SAndroid Build Coastguard Worker // Disable OpenCensus stats
122*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::EnableOpenCensusStats(false);
123*cc02d7e2SAndroid Build Coastguard Worker } else {
124*cc02d7e2SAndroid Build Coastguard Worker // Register the OpenCensus client stats interceptor factory if stats are
125*cc02d7e2SAndroid Build Coastguard Worker // enabled. Note that this is currently separate from the OpenCensus Plugin
126*cc02d7e2SAndroid Build Coastguard Worker // to avoid changing the behavior of the currently available OpenCensus
127*cc02d7e2SAndroid Build Coastguard Worker // plugin.
128*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::RegisterGlobalClientStatsInterceptorFactory(
129*cc02d7e2SAndroid Build Coastguard Worker new grpc::internal::OpenCensusClientInterceptorFactory);
130*cc02d7e2SAndroid Build Coastguard Worker }
131*cc02d7e2SAndroid Build Coastguard Worker if (config->cloud_logging.has_value()) {
132*cc02d7e2SAndroid Build Coastguard Worker g_logging_sink = new grpc::internal::ObservabilityLoggingSink(
133*cc02d7e2SAndroid Build Coastguard Worker config->cloud_logging.value(), config->project_id, config->labels);
134*cc02d7e2SAndroid Build Coastguard Worker grpc_core::RegisterLoggingFilter(g_logging_sink);
135*cc02d7e2SAndroid Build Coastguard Worker }
136*cc02d7e2SAndroid Build Coastguard Worker // If tracing or monitoring is enabled, we need to register the OpenCensus
137*cc02d7e2SAndroid Build Coastguard Worker // plugin as well.
138*cc02d7e2SAndroid Build Coastguard Worker if (config->cloud_trace.has_value() || config->cloud_monitoring.has_value()) {
139*cc02d7e2SAndroid Build Coastguard Worker grpc::RegisterOpenCensusPlugin();
140*cc02d7e2SAndroid Build Coastguard Worker }
141*cc02d7e2SAndroid Build Coastguard Worker // If tracing or monitoring is enabled, we need to detect the environment for
142*cc02d7e2SAndroid Build Coastguard Worker // OpenCensus, set the labels and attributes and prepare the StackDriver
143*cc02d7e2SAndroid Build Coastguard Worker // exporter.
144*cc02d7e2SAndroid Build Coastguard Worker // Note that this should be the last step of GcpObservabilityInit() since we
145*cc02d7e2SAndroid Build Coastguard Worker // can't register any more filters after grpc_init.
146*cc02d7e2SAndroid Build Coastguard Worker if (config->cloud_trace.has_value() || config->cloud_monitoring.has_value()) {
147*cc02d7e2SAndroid Build Coastguard Worker grpc_init();
148*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Notification notification;
149*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::EnvironmentAutoDetect::Get().NotifyOnDone(
150*cc02d7e2SAndroid Build Coastguard Worker [&]() { notification.Notify(); });
151*cc02d7e2SAndroid Build Coastguard Worker notification.WaitForNotification();
152*cc02d7e2SAndroid Build Coastguard Worker auto* resource = grpc::internal::EnvironmentAutoDetect::Get().resource();
153*cc02d7e2SAndroid Build Coastguard Worker if (config->cloud_trace.has_value()) {
154*cc02d7e2SAndroid Build Coastguard Worker // Set up attributes for constant tracing
155*cc02d7e2SAndroid Build Coastguard Worker std::vector<internal::OpenCensusRegistry::Attribute> attributes;
156*cc02d7e2SAndroid Build Coastguard Worker attributes.reserve(resource->labels.size() + config->labels.size());
157*cc02d7e2SAndroid Build Coastguard Worker // First insert in environment labels
158*cc02d7e2SAndroid Build Coastguard Worker for (const auto& resource_label : resource->labels) {
159*cc02d7e2SAndroid Build Coastguard Worker attributes.push_back(internal::OpenCensusRegistry::Attribute{
160*cc02d7e2SAndroid Build Coastguard Worker absl::StrCat(resource->resource_type, ".", resource_label.first),
161*cc02d7e2SAndroid Build Coastguard Worker resource_label.second});
162*cc02d7e2SAndroid Build Coastguard Worker }
163*cc02d7e2SAndroid Build Coastguard Worker // Then insert in labels from the GCP Observability config.
164*cc02d7e2SAndroid Build Coastguard Worker for (const auto& constant_label : config->labels) {
165*cc02d7e2SAndroid Build Coastguard Worker attributes.push_back(internal::OpenCensusRegistry::Attribute{
166*cc02d7e2SAndroid Build Coastguard Worker constant_label.first, constant_label.second});
167*cc02d7e2SAndroid Build Coastguard Worker }
168*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::OpenCensusRegistry::Get().RegisterConstantAttributes(
169*cc02d7e2SAndroid Build Coastguard Worker std::move(attributes));
170*cc02d7e2SAndroid Build Coastguard Worker }
171*cc02d7e2SAndroid Build Coastguard Worker if (config->cloud_monitoring.has_value()) {
172*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::OpenCensusRegistry::Get().RegisterConstantLabels(
173*cc02d7e2SAndroid Build Coastguard Worker config->labels);
174*cc02d7e2SAndroid Build Coastguard Worker RegisterOpenCensusViewsForGcpObservability();
175*cc02d7e2SAndroid Build Coastguard Worker }
176*cc02d7e2SAndroid Build Coastguard Worker // Note that we are setting up the exporters after registering the
177*cc02d7e2SAndroid Build Coastguard Worker // attributes and labels to avoid a case where the exporters start an RPC
178*cc02d7e2SAndroid Build Coastguard Worker // before we are ready.
179*cc02d7e2SAndroid Build Coastguard Worker if (config->cloud_trace.has_value()) {
180*cc02d7e2SAndroid Build Coastguard Worker // Set up the StackDriver Exporter for tracing.
181*cc02d7e2SAndroid Build Coastguard Worker opencensus::trace::TraceConfig::SetCurrentTraceParams(
182*cc02d7e2SAndroid Build Coastguard Worker {kMaxAttributes, kMaxAnnotations, kMaxMessageEvents, kMaxLinks,
183*cc02d7e2SAndroid Build Coastguard Worker opencensus::trace::ProbabilitySampler(
184*cc02d7e2SAndroid Build Coastguard Worker config->cloud_trace->sampling_rate)});
185*cc02d7e2SAndroid Build Coastguard Worker opencensus::exporters::trace::StackdriverOptions trace_opts;
186*cc02d7e2SAndroid Build Coastguard Worker trace_opts.project_id = config->project_id;
187*cc02d7e2SAndroid Build Coastguard Worker ChannelArguments args;
188*cc02d7e2SAndroid Build Coastguard Worker args.SetInt(GRPC_ARG_ENABLE_OBSERVABILITY, 0);
189*cc02d7e2SAndroid Build Coastguard Worker trace_opts.trace_service_stub =
190*cc02d7e2SAndroid Build Coastguard Worker ::google::devtools::cloudtrace::v2::TraceService::NewStub(
191*cc02d7e2SAndroid Build Coastguard Worker CreateCustomChannel(kGoogleStackdriverTraceAddress,
192*cc02d7e2SAndroid Build Coastguard Worker GoogleDefaultCredentials(), args));
193*cc02d7e2SAndroid Build Coastguard Worker opencensus::exporters::trace::StackdriverExporter::Register(
194*cc02d7e2SAndroid Build Coastguard Worker std::move(trace_opts));
195*cc02d7e2SAndroid Build Coastguard Worker }
196*cc02d7e2SAndroid Build Coastguard Worker if (config->cloud_monitoring.has_value()) {
197*cc02d7e2SAndroid Build Coastguard Worker // Set up the StackDriver Exporter for monitoring.
198*cc02d7e2SAndroid Build Coastguard Worker opencensus::exporters::stats::StackdriverOptions stats_opts;
199*cc02d7e2SAndroid Build Coastguard Worker stats_opts.project_id = config->project_id;
200*cc02d7e2SAndroid Build Coastguard Worker stats_opts.monitored_resource.set_type(resource->resource_type);
201*cc02d7e2SAndroid Build Coastguard Worker stats_opts.monitored_resource.mutable_labels()->insert(
202*cc02d7e2SAndroid Build Coastguard Worker resource->labels.begin(), resource->labels.end());
203*cc02d7e2SAndroid Build Coastguard Worker ChannelArguments args;
204*cc02d7e2SAndroid Build Coastguard Worker args.SetInt(GRPC_ARG_ENABLE_OBSERVABILITY, 0);
205*cc02d7e2SAndroid Build Coastguard Worker stats_opts.metric_service_stub =
206*cc02d7e2SAndroid Build Coastguard Worker google::monitoring::v3::MetricService::NewStub(
207*cc02d7e2SAndroid Build Coastguard Worker CreateCustomChannel(kGoogleStackdriverStatsAddress,
208*cc02d7e2SAndroid Build Coastguard Worker GoogleDefaultCredentials(), args));
209*cc02d7e2SAndroid Build Coastguard Worker opencensus::exporters::stats::StackdriverExporter::Register(
210*cc02d7e2SAndroid Build Coastguard Worker std::move(stats_opts));
211*cc02d7e2SAndroid Build Coastguard Worker }
212*cc02d7e2SAndroid Build Coastguard Worker grpc_shutdown();
213*cc02d7e2SAndroid Build Coastguard Worker }
214*cc02d7e2SAndroid Build Coastguard Worker return absl::OkStatus();
215*cc02d7e2SAndroid Build Coastguard Worker }
216*cc02d7e2SAndroid Build Coastguard Worker
GcpObservabilityClose()217*cc02d7e2SAndroid Build Coastguard Worker void GcpObservabilityClose() {
218*cc02d7e2SAndroid Build Coastguard Worker if (g_logging_sink != nullptr) {
219*cc02d7e2SAndroid Build Coastguard Worker g_logging_sink->FlushAndClose();
220*cc02d7e2SAndroid Build Coastguard Worker }
221*cc02d7e2SAndroid Build Coastguard Worker // Currently, GcpObservabilityClose() only supports flushing logs. Stats and
222*cc02d7e2SAndroid Build Coastguard Worker // tracing get automatically flushed at a regular interval, so sleep for an
223*cc02d7e2SAndroid Build Coastguard Worker // interval to make sure that those are flushed too.
224*cc02d7e2SAndroid Build Coastguard Worker absl::SleepFor(absl::Seconds(25));
225*cc02d7e2SAndroid Build Coastguard Worker }
226*cc02d7e2SAndroid Build Coastguard Worker
227*cc02d7e2SAndroid Build Coastguard Worker } // namespace internal
228*cc02d7e2SAndroid Build Coastguard Worker
229*cc02d7e2SAndroid Build Coastguard Worker namespace experimental {
230*cc02d7e2SAndroid Build Coastguard Worker
GcpObservabilityInit()231*cc02d7e2SAndroid Build Coastguard Worker absl::Status GcpObservabilityInit() {
232*cc02d7e2SAndroid Build Coastguard Worker return grpc::internal::GcpObservabilityInit();
233*cc02d7e2SAndroid Build Coastguard Worker }
234*cc02d7e2SAndroid Build Coastguard Worker
GcpObservabilityClose()235*cc02d7e2SAndroid Build Coastguard Worker void GcpObservabilityClose() { return grpc::internal::GcpObservabilityClose(); }
236*cc02d7e2SAndroid Build Coastguard Worker
237*cc02d7e2SAndroid Build Coastguard Worker } // namespace experimental
238*cc02d7e2SAndroid Build Coastguard Worker
239*cc02d7e2SAndroid Build Coastguard Worker //
240*cc02d7e2SAndroid Build Coastguard Worker // GcpObservability
241*cc02d7e2SAndroid Build Coastguard Worker //
242*cc02d7e2SAndroid Build Coastguard Worker
Init()243*cc02d7e2SAndroid Build Coastguard Worker absl::StatusOr<GcpObservability> GcpObservability::Init() {
244*cc02d7e2SAndroid Build Coastguard Worker absl::Status status = grpc::internal::GcpObservabilityInit();
245*cc02d7e2SAndroid Build Coastguard Worker if (!status.ok()) {
246*cc02d7e2SAndroid Build Coastguard Worker return status;
247*cc02d7e2SAndroid Build Coastguard Worker }
248*cc02d7e2SAndroid Build Coastguard Worker GcpObservability obj;
249*cc02d7e2SAndroid Build Coastguard Worker obj.impl_ = std::make_unique<GcpObservabilityImpl>();
250*cc02d7e2SAndroid Build Coastguard Worker return obj;
251*cc02d7e2SAndroid Build Coastguard Worker }
252*cc02d7e2SAndroid Build Coastguard Worker
GcpObservability(GcpObservability && other)253*cc02d7e2SAndroid Build Coastguard Worker GcpObservability::GcpObservability(GcpObservability&& other) noexcept
254*cc02d7e2SAndroid Build Coastguard Worker : impl_(std::move(other.impl_)) {}
255*cc02d7e2SAndroid Build Coastguard Worker
operator =(GcpObservability && other)256*cc02d7e2SAndroid Build Coastguard Worker GcpObservability& GcpObservability::operator=(
257*cc02d7e2SAndroid Build Coastguard Worker GcpObservability&& other) noexcept {
258*cc02d7e2SAndroid Build Coastguard Worker if (this != &other) {
259*cc02d7e2SAndroid Build Coastguard Worker impl_ = std::move(other.impl_);
260*cc02d7e2SAndroid Build Coastguard Worker }
261*cc02d7e2SAndroid Build Coastguard Worker return *this;
262*cc02d7e2SAndroid Build Coastguard Worker }
263*cc02d7e2SAndroid Build Coastguard Worker
264*cc02d7e2SAndroid Build Coastguard Worker //
265*cc02d7e2SAndroid Build Coastguard Worker // GcpObservability::GcpObservabilityImpl
266*cc02d7e2SAndroid Build Coastguard Worker //
267*cc02d7e2SAndroid Build Coastguard Worker
~GcpObservabilityImpl()268*cc02d7e2SAndroid Build Coastguard Worker GcpObservability::GcpObservabilityImpl::~GcpObservabilityImpl() {
269*cc02d7e2SAndroid Build Coastguard Worker grpc::internal::GcpObservabilityClose();
270*cc02d7e2SAndroid Build Coastguard Worker }
271*cc02d7e2SAndroid Build Coastguard Worker
272*cc02d7e2SAndroid Build Coastguard Worker } // namespace grpc
273