[CSM O11Y] CSM Service Label Plumbing from LB Policies to CallAttemptTracer (#35210)
<!--
If you know who should review your pull request, please assign it to that
person, otherwise the pull request would get assigned randomly.
If your pull request is for a specific language, please add the appropriate
lang label.
-->
Closes #35210
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35210 from yijiem:csm-service-label 6a6a7d1774
PiperOrigin-RevId: 597641393
pull/35529/head
parent
22682a78f6
commit
77ad5a786e
34 changed files with 827 additions and 121 deletions
@ -0,0 +1,82 @@ |
|||||||
|
// Copyright 2023 The gRPC Authors.
|
||||||
|
//
|
||||||
|
// 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 "test/core/util/fake_stats_plugin.h" |
||||||
|
|
||||||
|
#include "src/core/lib/config/core_configuration.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
class FakeStatsClientFilter : public ChannelFilter { |
||||||
|
public: |
||||||
|
static const grpc_channel_filter kFilter; |
||||||
|
|
||||||
|
static absl::StatusOr<FakeStatsClientFilter> Create( |
||||||
|
const ChannelArgs& /*args*/, ChannelFilter::Args /*filter_args*/); |
||||||
|
|
||||||
|
ArenaPromise<ServerMetadataHandle> MakeCallPromise( |
||||||
|
CallArgs call_args, NextPromiseFactory next_promise_factory) override; |
||||||
|
|
||||||
|
private: |
||||||
|
explicit FakeStatsClientFilter( |
||||||
|
FakeClientCallTracerFactory* fake_client_call_tracer_factory); |
||||||
|
FakeClientCallTracerFactory* const fake_client_call_tracer_factory_; |
||||||
|
}; |
||||||
|
|
||||||
|
const grpc_channel_filter FakeStatsClientFilter::kFilter = |
||||||
|
MakePromiseBasedFilter<FakeStatsClientFilter, FilterEndpoint::kClient>( |
||||||
|
"fake_stats_client"); |
||||||
|
|
||||||
|
absl::StatusOr<FakeStatsClientFilter> FakeStatsClientFilter::Create( |
||||||
|
const ChannelArgs& args, ChannelFilter::Args /*filter_args*/) { |
||||||
|
auto* fake_client_call_tracer_factory = |
||||||
|
args.GetPointer<FakeClientCallTracerFactory>( |
||||||
|
GRPC_ARG_INJECT_FAKE_CLIENT_CALL_TRACER_FACTORY); |
||||||
|
GPR_ASSERT(fake_client_call_tracer_factory != nullptr); |
||||||
|
return FakeStatsClientFilter(fake_client_call_tracer_factory); |
||||||
|
} |
||||||
|
|
||||||
|
ArenaPromise<ServerMetadataHandle> FakeStatsClientFilter::MakeCallPromise( |
||||||
|
CallArgs call_args, NextPromiseFactory next_promise_factory) { |
||||||
|
FakeClientCallTracer* client_call_tracer = |
||||||
|
fake_client_call_tracer_factory_->CreateFakeClientCallTracer(); |
||||||
|
if (client_call_tracer != nullptr) { |
||||||
|
auto* call_context = GetContext<grpc_call_context_element>(); |
||||||
|
call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value = |
||||||
|
client_call_tracer; |
||||||
|
call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].destroy = |
||||||
|
nullptr; |
||||||
|
} |
||||||
|
return next_promise_factory(std::move(call_args)); |
||||||
|
} |
||||||
|
|
||||||
|
FakeStatsClientFilter::FakeStatsClientFilter( |
||||||
|
FakeClientCallTracerFactory* fake_client_call_tracer_factory) |
||||||
|
: fake_client_call_tracer_factory_(fake_client_call_tracer_factory) {} |
||||||
|
|
||||||
|
void RegisterFakeStatsPlugin() { |
||||||
|
CoreConfiguration::RegisterBuilder( |
||||||
|
[](CoreConfiguration::Builder* builder) mutable { |
||||||
|
builder->channel_init() |
||||||
|
->RegisterFilter(GRPC_CLIENT_CHANNEL, |
||||||
|
&FakeStatsClientFilter::kFilter) |
||||||
|
.If([](const ChannelArgs& args) { |
||||||
|
return args.GetPointer<FakeClientCallTracerFactory>( |
||||||
|
GRPC_ARG_INJECT_FAKE_CLIENT_CALL_TRACER_FACTORY) != |
||||||
|
nullptr; |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace grpc_core
|
@ -0,0 +1,192 @@ |
|||||||
|
// Copyright 2023 The gRPC Authors.
|
||||||
|
//
|
||||||
|
// 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 GRPC_TEST_CORE_UTIL_FAKE_STATS_PLUGIN_H |
||||||
|
#define GRPC_TEST_CORE_UTIL_FAKE_STATS_PLUGIN_H |
||||||
|
|
||||||
|
#include <memory> |
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include "src/core/lib/channel/call_tracer.h" |
||||||
|
#include "src/core/lib/channel/promise_based_filter.h" |
||||||
|
#include "src/core/lib/channel/tcp_tracer.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
// Registers a FakeStatsClientFilter as a client channel filter if there is a
|
||||||
|
// FakeClientCallTracerFactory in the channel args. This filter will use the
|
||||||
|
// FakeClientCallTracerFactory to create and inject a FakeClientCallTracer into
|
||||||
|
// the call context.
|
||||||
|
// Example usage:
|
||||||
|
// RegisterFakeStatsPlugin(); // before grpc_init()
|
||||||
|
//
|
||||||
|
// // Creates a FakeClientCallTracerFactory and adds it into the channel args.
|
||||||
|
// FakeClientCallTracerFactory fake_client_call_tracer_factory;
|
||||||
|
// ChannelArguments channel_args;
|
||||||
|
// channel_args.SetPointer(GRPC_ARG_INJECT_FAKE_CLIENT_CALL_TRACER_FACTORY,
|
||||||
|
// &fake_client_call_tracer_factory);
|
||||||
|
//
|
||||||
|
// // After the system under test has been executed (e.g. an RPC has been
|
||||||
|
// // sent), use the FakeClientCallTracerFactory to verify certain
|
||||||
|
// // expectations.
|
||||||
|
// EXPECT_THAT(fake_client_call_tracer_factory.GetLastFakeClientCallTracer()
|
||||||
|
// ->GetLastCallAttemptTracer()
|
||||||
|
// ->GetOptionalLabels(),
|
||||||
|
// VerifyCsmServiceLabels());
|
||||||
|
void RegisterFakeStatsPlugin(); |
||||||
|
|
||||||
|
class FakeClientCallTracer : public ClientCallTracer { |
||||||
|
public: |
||||||
|
class FakeClientCallAttemptTracer |
||||||
|
: public ClientCallTracer::CallAttemptTracer { |
||||||
|
public: |
||||||
|
explicit FakeClientCallAttemptTracer( |
||||||
|
std::vector<std::string>* annotation_logger) |
||||||
|
: annotation_logger_(annotation_logger) {} |
||||||
|
~FakeClientCallAttemptTracer() override {} |
||||||
|
void RecordSendInitialMetadata( |
||||||
|
grpc_metadata_batch* /*send_initial_metadata*/) override {} |
||||||
|
void RecordSendTrailingMetadata( |
||||||
|
grpc_metadata_batch* /*send_trailing_metadata*/) override {} |
||||||
|
void RecordSendMessage(const SliceBuffer& /*send_message*/) override {} |
||||||
|
void RecordSendCompressedMessage( |
||||||
|
const SliceBuffer& /*send_compressed_message*/) override {} |
||||||
|
void RecordReceivedInitialMetadata( |
||||||
|
grpc_metadata_batch* /*recv_initial_metadata*/) override {} |
||||||
|
void RecordReceivedMessage(const SliceBuffer& /*recv_message*/) override {} |
||||||
|
void RecordReceivedDecompressedMessage( |
||||||
|
const SliceBuffer& /*recv_decompressed_message*/) override {} |
||||||
|
void RecordCancel(grpc_error_handle /*cancel_error*/) override {} |
||||||
|
void RecordReceivedTrailingMetadata( |
||||||
|
absl::Status /*status*/, |
||||||
|
grpc_metadata_batch* /*recv_trailing_metadata*/, |
||||||
|
const grpc_transport_stream_stats* /*transport_stream_stats*/) |
||||||
|
override {} |
||||||
|
void RecordEnd(const gpr_timespec& /*latency*/) override {} |
||||||
|
void RecordAnnotation(absl::string_view annotation) override { |
||||||
|
annotation_logger_->push_back(std::string(annotation)); |
||||||
|
} |
||||||
|
void RecordAnnotation(const Annotation& /*annotation*/) override {} |
||||||
|
std::shared_ptr<TcpTracerInterface> StartNewTcpTrace() override { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
void AddOptionalLabels( |
||||||
|
OptionalLabelComponent component, |
||||||
|
std::shared_ptr<std::map<std::string, std::string>> labels) override { |
||||||
|
optional_labels_.emplace(component, std::move(labels)); |
||||||
|
} |
||||||
|
std::string TraceId() override { return ""; } |
||||||
|
std::string SpanId() override { return ""; } |
||||||
|
bool IsSampled() override { return false; } |
||||||
|
|
||||||
|
const std::map<OptionalLabelComponent, |
||||||
|
std::shared_ptr<std::map<std::string, std::string>>>& |
||||||
|
GetOptionalLabels() const { |
||||||
|
return optional_labels_; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
std::vector<std::string>* annotation_logger_; |
||||||
|
std::map<OptionalLabelComponent, |
||||||
|
std::shared_ptr<std::map<std::string, std::string>>> |
||||||
|
optional_labels_; |
||||||
|
}; |
||||||
|
|
||||||
|
explicit FakeClientCallTracer(std::vector<std::string>* annotation_logger) |
||||||
|
: annotation_logger_(annotation_logger) {} |
||||||
|
~FakeClientCallTracer() override {} |
||||||
|
CallAttemptTracer* StartNewAttempt(bool /*is_transparent_retry*/) override { |
||||||
|
call_attempt_tracers_.emplace_back( |
||||||
|
new FakeClientCallAttemptTracer(annotation_logger_)); |
||||||
|
return call_attempt_tracers_.back().get(); |
||||||
|
} |
||||||
|
|
||||||
|
void RecordAnnotation(absl::string_view annotation) override { |
||||||
|
annotation_logger_->push_back(std::string(annotation)); |
||||||
|
} |
||||||
|
void RecordAnnotation(const Annotation& /*annotation*/) override {} |
||||||
|
std::string TraceId() override { return ""; } |
||||||
|
std::string SpanId() override { return ""; } |
||||||
|
bool IsSampled() override { return false; } |
||||||
|
|
||||||
|
FakeClientCallAttemptTracer* GetLastCallAttemptTracer() const { |
||||||
|
return call_attempt_tracers_.back().get(); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
std::vector<std::string>* annotation_logger_; |
||||||
|
std::vector<std::unique_ptr<FakeClientCallAttemptTracer>> |
||||||
|
call_attempt_tracers_; |
||||||
|
}; |
||||||
|
|
||||||
|
#define GRPC_ARG_INJECT_FAKE_CLIENT_CALL_TRACER_FACTORY \ |
||||||
|
"grpc.testing.inject_fake_client_call_tracer_factory" |
||||||
|
|
||||||
|
class FakeClientCallTracerFactory { |
||||||
|
public: |
||||||
|
FakeClientCallTracer* CreateFakeClientCallTracer() { |
||||||
|
fake_client_call_tracers_.emplace_back( |
||||||
|
new FakeClientCallTracer(&annotation_logger_)); |
||||||
|
return fake_client_call_tracers_.back().get(); |
||||||
|
} |
||||||
|
|
||||||
|
FakeClientCallTracer* GetLastFakeClientCallTracer() { |
||||||
|
return fake_client_call_tracers_.back().get(); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
std::vector<std::string> annotation_logger_; |
||||||
|
std::vector<std::unique_ptr<FakeClientCallTracer>> fake_client_call_tracers_; |
||||||
|
}; |
||||||
|
|
||||||
|
class FakeServerCallTracer : public ServerCallTracer { |
||||||
|
public: |
||||||
|
explicit FakeServerCallTracer(std::vector<std::string>* annotation_logger) |
||||||
|
: annotation_logger_(annotation_logger) {} |
||||||
|
~FakeServerCallTracer() override {} |
||||||
|
void RecordSendInitialMetadata( |
||||||
|
grpc_metadata_batch* /*send_initial_metadata*/) override {} |
||||||
|
void RecordSendTrailingMetadata( |
||||||
|
grpc_metadata_batch* /*send_trailing_metadata*/) override {} |
||||||
|
void RecordSendMessage(const SliceBuffer& /*send_message*/) override {} |
||||||
|
void RecordSendCompressedMessage( |
||||||
|
const SliceBuffer& /*send_compressed_message*/) override {} |
||||||
|
void RecordReceivedInitialMetadata( |
||||||
|
grpc_metadata_batch* /*recv_initial_metadata*/) override {} |
||||||
|
void RecordReceivedMessage(const SliceBuffer& /*recv_message*/) override {} |
||||||
|
void RecordReceivedDecompressedMessage( |
||||||
|
const SliceBuffer& /*recv_decompressed_message*/) override {} |
||||||
|
void RecordCancel(grpc_error_handle /*cancel_error*/) override {} |
||||||
|
void RecordReceivedTrailingMetadata( |
||||||
|
grpc_metadata_batch* /*recv_trailing_metadata*/) override {} |
||||||
|
void RecordEnd(const grpc_call_final_info* /*final_info*/) override {} |
||||||
|
void RecordAnnotation(absl::string_view annotation) override { |
||||||
|
annotation_logger_->push_back(std::string(annotation)); |
||||||
|
} |
||||||
|
void RecordAnnotation(const Annotation& /*annotation*/) override {} |
||||||
|
std::shared_ptr<TcpTracerInterface> StartNewTcpTrace() override { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
std::string TraceId() override { return ""; } |
||||||
|
std::string SpanId() override { return ""; } |
||||||
|
bool IsSampled() override { return false; } |
||||||
|
|
||||||
|
private: |
||||||
|
std::vector<std::string>* annotation_logger_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
#endif // GRPC_TEST_CORE_UTIL_FAKE_STATS_PLUGIN_H
|
Loading…
Reference in new issue