1 // Copyright 2023 The gRPC Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "test/core/test_util/fake_stats_plugin.h"
16
17 #include "absl/log/check.h"
18 #include "src/core/config/core_configuration.h"
19
20 namespace grpc_core {
21
22 class FakeStatsClientFilter : public ChannelFilter {
23 public:
24 static const grpc_channel_filter kFilter;
25
TypeName()26 static absl::string_view TypeName() { return "fake_stats_client"; }
27
28 explicit FakeStatsClientFilter(
29 FakeClientCallTracerFactory* fake_client_call_tracer_factory);
30
31 static absl::StatusOr<std::unique_ptr<FakeStatsClientFilter>> Create(
32 const ChannelArgs& /*args*/, ChannelFilter::Args /*filter_args*/);
33
34 ArenaPromise<ServerMetadataHandle> MakeCallPromise(
35 CallArgs call_args, NextPromiseFactory next_promise_factory) override;
36
37 private:
38 FakeClientCallTracerFactory* const fake_client_call_tracer_factory_;
39 };
40
41 const grpc_channel_filter FakeStatsClientFilter::kFilter =
42 MakePromiseBasedFilter<FakeStatsClientFilter, FilterEndpoint::kClient>();
43
44 absl::StatusOr<std::unique_ptr<FakeStatsClientFilter>>
Create(const ChannelArgs & args,ChannelFilter::Args)45 FakeStatsClientFilter::Create(const ChannelArgs& args,
46 ChannelFilter::Args /*filter_args*/) {
47 auto* fake_client_call_tracer_factory =
48 args.GetPointer<FakeClientCallTracerFactory>(
49 GRPC_ARG_INJECT_FAKE_CLIENT_CALL_TRACER_FACTORY);
50 CHECK_NE(fake_client_call_tracer_factory, nullptr);
51 return std::make_unique<FakeStatsClientFilter>(
52 fake_client_call_tracer_factory);
53 }
54
MakeCallPromise(CallArgs call_args,NextPromiseFactory next_promise_factory)55 ArenaPromise<ServerMetadataHandle> FakeStatsClientFilter::MakeCallPromise(
56 CallArgs call_args, NextPromiseFactory next_promise_factory) {
57 FakeClientCallTracer* client_call_tracer =
58 fake_client_call_tracer_factory_->CreateFakeClientCallTracer();
59 if (client_call_tracer != nullptr) {
60 SetContext<CallTracerAnnotationInterface>(client_call_tracer);
61 }
62 return next_promise_factory(std::move(call_args));
63 }
64
FakeStatsClientFilter(FakeClientCallTracerFactory * fake_client_call_tracer_factory)65 FakeStatsClientFilter::FakeStatsClientFilter(
66 FakeClientCallTracerFactory* fake_client_call_tracer_factory)
67 : fake_client_call_tracer_factory_(fake_client_call_tracer_factory) {}
68
RegisterFakeStatsPlugin()69 void RegisterFakeStatsPlugin() {
70 CoreConfiguration::RegisterBuilder(
71 [](CoreConfiguration::Builder* builder) mutable {
72 builder->channel_init()
73 ->RegisterFilter(GRPC_CLIENT_CHANNEL,
74 &FakeStatsClientFilter::kFilter)
75 .If([](const ChannelArgs& args) {
76 return args.GetPointer<FakeClientCallTracerFactory>(
77 GRPC_ARG_INJECT_FAKE_CLIENT_CALL_TRACER_FACTORY) !=
78 nullptr;
79 });
80 });
81 }
82
83 namespace {
84
AddKeyValuePairs(absl::Span<const absl::string_view> keys,absl::Span<const absl::string_view> values,std::vector<std::string> * key_value_pairs)85 void AddKeyValuePairs(absl::Span<const absl::string_view> keys,
86 absl::Span<const absl::string_view> values,
87 std::vector<std::string>* key_value_pairs) {
88 CHECK(keys.size() == values.size());
89 for (size_t i = 0; i < keys.size(); ++i) {
90 key_value_pairs->push_back(absl::StrCat(keys[i], "=", values[i]));
91 }
92 }
93
94 } // namespace
95
MakeLabelString(absl::Span<const absl::string_view> label_keys,absl::Span<const absl::string_view> label_values,absl::Span<const absl::string_view> optional_label_keys,absl::Span<const absl::string_view> optional_values)96 std::string MakeLabelString(
97 absl::Span<const absl::string_view> label_keys,
98 absl::Span<const absl::string_view> label_values,
99 absl::Span<const absl::string_view> optional_label_keys,
100 absl::Span<const absl::string_view> optional_values) {
101 std::vector<std::string> key_value_pairs;
102 AddKeyValuePairs(label_keys, label_values, &key_value_pairs);
103 AddKeyValuePairs(optional_label_keys, optional_values, &key_value_pairs);
104 return absl::StrJoin(key_value_pairs, ",");
105 }
106
MakeStatsPluginForTarget(absl::string_view target_suffix)107 std::shared_ptr<FakeStatsPlugin> MakeStatsPluginForTarget(
108 absl::string_view target_suffix) {
109 return FakeStatsPluginBuilder()
110 .SetChannelFilter(
111 [target_suffix](const experimental::StatsPluginChannelScope& scope) {
112 return absl::EndsWith(scope.target(), target_suffix);
113 })
114 .BuildAndRegister();
115 }
116
ResetGlobalInstrumentsRegistry()117 void GlobalInstrumentsRegistryTestPeer::ResetGlobalInstrumentsRegistry() {
118 auto& instruments = GlobalInstrumentsRegistry::GetInstrumentList();
119 instruments.clear();
120 }
121
122 namespace {
123
124 absl::optional<GlobalInstrumentsRegistry::GlobalInstrumentHandle>
FindInstrument(const std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor> & instruments,absl::string_view name,GlobalInstrumentsRegistry::ValueType value_type,GlobalInstrumentsRegistry::InstrumentType instrument_type)125 FindInstrument(
126 const std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
127 instruments,
128 absl::string_view name, GlobalInstrumentsRegistry::ValueType value_type,
129 GlobalInstrumentsRegistry::InstrumentType instrument_type) {
130 for (const auto& descriptor : instruments) {
131 if (descriptor.name == name && descriptor.value_type == value_type &&
132 descriptor.instrument_type == instrument_type) {
133 GlobalInstrumentsRegistry::GlobalInstrumentHandle handle;
134 handle.index = descriptor.index;
135 return handle;
136 }
137 }
138 return absl::nullopt;
139 }
140
141 } // namespace
142
143 absl::optional<GlobalInstrumentsRegistry::GlobalInstrumentHandle>
FindUInt64CounterHandleByName(absl::string_view name)144 GlobalInstrumentsRegistryTestPeer::FindUInt64CounterHandleByName(
145 absl::string_view name) {
146 return FindInstrument(GlobalInstrumentsRegistry::GetInstrumentList(), name,
147 GlobalInstrumentsRegistry::ValueType::kUInt64,
148 GlobalInstrumentsRegistry::InstrumentType::kCounter);
149 }
150
151 absl::optional<GlobalInstrumentsRegistry::GlobalInstrumentHandle>
FindDoubleCounterHandleByName(absl::string_view name)152 GlobalInstrumentsRegistryTestPeer::FindDoubleCounterHandleByName(
153 absl::string_view name) {
154 return FindInstrument(GlobalInstrumentsRegistry::GetInstrumentList(), name,
155 GlobalInstrumentsRegistry::ValueType::kDouble,
156 GlobalInstrumentsRegistry::InstrumentType::kCounter);
157 }
158
159 absl::optional<GlobalInstrumentsRegistry::GlobalInstrumentHandle>
FindUInt64HistogramHandleByName(absl::string_view name)160 GlobalInstrumentsRegistryTestPeer::FindUInt64HistogramHandleByName(
161 absl::string_view name) {
162 return FindInstrument(GlobalInstrumentsRegistry::GetInstrumentList(), name,
163 GlobalInstrumentsRegistry::ValueType::kUInt64,
164 GlobalInstrumentsRegistry::InstrumentType::kHistogram);
165 }
166
167 absl::optional<GlobalInstrumentsRegistry::GlobalInstrumentHandle>
FindDoubleHistogramHandleByName(absl::string_view name)168 GlobalInstrumentsRegistryTestPeer::FindDoubleHistogramHandleByName(
169 absl::string_view name) {
170 return FindInstrument(GlobalInstrumentsRegistry::GetInstrumentList(), name,
171 GlobalInstrumentsRegistry::ValueType::kDouble,
172 GlobalInstrumentsRegistry::InstrumentType::kHistogram);
173 }
174
175 absl::optional<GlobalInstrumentsRegistry::GlobalInstrumentHandle>
FindCallbackInt64GaugeHandleByName(absl::string_view name)176 GlobalInstrumentsRegistryTestPeer::FindCallbackInt64GaugeHandleByName(
177 absl::string_view name) {
178 return FindInstrument(
179 GlobalInstrumentsRegistry::GetInstrumentList(), name,
180 GlobalInstrumentsRegistry::ValueType::kInt64,
181 GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge);
182 }
183
184 absl::optional<GlobalInstrumentsRegistry::GlobalInstrumentHandle>
FindCallbackDoubleGaugeHandleByName(absl::string_view name)185 GlobalInstrumentsRegistryTestPeer::FindCallbackDoubleGaugeHandleByName(
186 absl::string_view name) {
187 return FindInstrument(
188 GlobalInstrumentsRegistry::GetInstrumentList(), name,
189 GlobalInstrumentsRegistry::ValueType::kDouble,
190 GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge);
191 }
192
193 GlobalInstrumentsRegistry::GlobalInstrumentDescriptor*
FindMetricDescriptorByName(absl::string_view name)194 GlobalInstrumentsRegistryTestPeer::FindMetricDescriptorByName(
195 absl::string_view name) {
196 for (auto& descriptor : GlobalInstrumentsRegistry::GetInstrumentList()) {
197 if (descriptor.name == name) {
198 return &descriptor;
199 }
200 }
201 return nullptr;
202 }
203
204 } // namespace grpc_core
205