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/util/fake_stats_plugin.h"
16
17 #include "src/core/lib/config/core_configuration.h"
18
19 namespace grpc_core {
20
21 class FakeStatsClientFilter : public ChannelFilter {
22 public:
23 static const grpc_channel_filter kFilter;
24
25 static absl::StatusOr<FakeStatsClientFilter> Create(
26 const ChannelArgs& /*args*/, ChannelFilter::Args /*filter_args*/);
27
28 ArenaPromise<ServerMetadataHandle> MakeCallPromise(
29 CallArgs call_args, NextPromiseFactory next_promise_factory) override;
30
31 private:
32 explicit FakeStatsClientFilter(
33 FakeClientCallTracerFactory* fake_client_call_tracer_factory);
34 FakeClientCallTracerFactory* const fake_client_call_tracer_factory_;
35 };
36
37 const grpc_channel_filter FakeStatsClientFilter::kFilter =
38 MakePromiseBasedFilter<FakeStatsClientFilter, FilterEndpoint::kClient>(
39 "fake_stats_client");
40
Create(const ChannelArgs & args,ChannelFilter::Args)41 absl::StatusOr<FakeStatsClientFilter> FakeStatsClientFilter::Create(
42 const ChannelArgs& args, ChannelFilter::Args /*filter_args*/) {
43 auto* fake_client_call_tracer_factory =
44 args.GetPointer<FakeClientCallTracerFactory>(
45 GRPC_ARG_INJECT_FAKE_CLIENT_CALL_TRACER_FACTORY);
46 GPR_ASSERT(fake_client_call_tracer_factory != nullptr);
47 return FakeStatsClientFilter(fake_client_call_tracer_factory);
48 }
49
MakeCallPromise(CallArgs call_args,NextPromiseFactory next_promise_factory)50 ArenaPromise<ServerMetadataHandle> FakeStatsClientFilter::MakeCallPromise(
51 CallArgs call_args, NextPromiseFactory next_promise_factory) {
52 FakeClientCallTracer* client_call_tracer =
53 fake_client_call_tracer_factory_->CreateFakeClientCallTracer();
54 if (client_call_tracer != nullptr) {
55 auto* call_context = GetContext<grpc_call_context_element>();
56 call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value =
57 client_call_tracer;
58 call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].destroy =
59 nullptr;
60 }
61 return next_promise_factory(std::move(call_args));
62 }
63
FakeStatsClientFilter(FakeClientCallTracerFactory * fake_client_call_tracer_factory)64 FakeStatsClientFilter::FakeStatsClientFilter(
65 FakeClientCallTracerFactory* fake_client_call_tracer_factory)
66 : fake_client_call_tracer_factory_(fake_client_call_tracer_factory) {}
67
RegisterFakeStatsPlugin()68 void RegisterFakeStatsPlugin() {
69 CoreConfiguration::RegisterBuilder(
70 [](CoreConfiguration::Builder* builder) mutable {
71 builder->channel_init()
72 ->RegisterFilter(GRPC_CLIENT_CHANNEL,
73 &FakeStatsClientFilter::kFilter)
74 .If([](const ChannelArgs& args) {
75 return args.GetPointer<FakeClientCallTracerFactory>(
76 GRPC_ARG_INJECT_FAKE_CLIENT_CALL_TRACER_FACTORY) !=
77 nullptr;
78 });
79 });
80 }
81
82 namespace {
83
AddKeyValuePairs(absl::Span<const absl::string_view> keys,absl::Span<const absl::string_view> values,std::vector<std::string> * key_value_pairs)84 void AddKeyValuePairs(absl::Span<const absl::string_view> keys,
85 absl::Span<const absl::string_view> values,
86 std::vector<std::string>* key_value_pairs) {
87 GPR_ASSERT(keys.size() == values.size());
88 for (size_t i = 0; i < keys.size(); ++i) {
89 key_value_pairs->push_back(absl::StrCat(keys[i], "=", values[i]));
90 }
91 }
92
93 } // namespace
94
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)95 std::string MakeLabelString(
96 absl::Span<const absl::string_view> label_keys,
97 absl::Span<const absl::string_view> label_values,
98 absl::Span<const absl::string_view> optional_label_keys,
99 absl::Span<const absl::string_view> optional_values) {
100 std::vector<std::string> key_value_pairs;
101 AddKeyValuePairs(label_keys, label_values, &key_value_pairs);
102 AddKeyValuePairs(optional_label_keys, optional_values, &key_value_pairs);
103 return absl::StrJoin(key_value_pairs, ",");
104 }
105
MakeStatsPluginForTarget(absl::string_view target_suffix)106 std::shared_ptr<FakeStatsPlugin> MakeStatsPluginForTarget(
107 absl::string_view target_suffix) {
108 return FakeStatsPluginBuilder()
109 .SetChannelFilter(
110 [target_suffix](const experimental::StatsPluginChannelScope& scope) {
111 return absl::EndsWith(scope.target(), target_suffix);
112 })
113 .BuildAndRegister();
114 }
115
ResetGlobalInstrumentsRegistry()116 void GlobalInstrumentsRegistryTestPeer::ResetGlobalInstrumentsRegistry() {
117 auto& instruments = GlobalInstrumentsRegistry::GetInstrumentList();
118 instruments.clear();
119 }
120
121 namespace {
122
123 template <typename HandleType>
FindInstrument(const std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor> & instruments,absl::string_view name,GlobalInstrumentsRegistry::ValueType value_type,GlobalInstrumentsRegistry::InstrumentType instrument_type)124 absl::optional<HandleType> FindInstrument(
125 const std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
126 instruments,
127 absl::string_view name, GlobalInstrumentsRegistry::ValueType value_type,
128 GlobalInstrumentsRegistry::InstrumentType instrument_type) {
129 for (const auto& descriptor : instruments) {
130 if (descriptor.name == name && descriptor.value_type == value_type &&
131 descriptor.instrument_type == instrument_type) {
132 HandleType handle;
133 handle.index = descriptor.index;
134 return handle;
135 }
136 }
137 return absl::nullopt;
138 }
139
140 } // namespace
141
142 absl::optional<GlobalInstrumentsRegistry::GlobalUInt64CounterHandle>
FindUInt64CounterHandleByName(absl::string_view name)143 GlobalInstrumentsRegistryTestPeer::FindUInt64CounterHandleByName(
144 absl::string_view name) {
145 return FindInstrument<GlobalInstrumentsRegistry::GlobalUInt64CounterHandle>(
146 GlobalInstrumentsRegistry::GetInstrumentList(), name,
147 GlobalInstrumentsRegistry::ValueType::kUInt64,
148 GlobalInstrumentsRegistry::InstrumentType::kCounter);
149 }
150
151 absl::optional<GlobalInstrumentsRegistry::GlobalDoubleCounterHandle>
FindDoubleCounterHandleByName(absl::string_view name)152 GlobalInstrumentsRegistryTestPeer::FindDoubleCounterHandleByName(
153 absl::string_view name) {
154 return FindInstrument<GlobalInstrumentsRegistry::GlobalDoubleCounterHandle>(
155 GlobalInstrumentsRegistry::GetInstrumentList(), name,
156 GlobalInstrumentsRegistry::ValueType::kDouble,
157 GlobalInstrumentsRegistry::InstrumentType::kCounter);
158 }
159
160 absl::optional<GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle>
FindUInt64HistogramHandleByName(absl::string_view name)161 GlobalInstrumentsRegistryTestPeer::FindUInt64HistogramHandleByName(
162 absl::string_view name) {
163 return FindInstrument<GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle>(
164 GlobalInstrumentsRegistry::GetInstrumentList(), name,
165 GlobalInstrumentsRegistry::ValueType::kUInt64,
166 GlobalInstrumentsRegistry::InstrumentType::kHistogram);
167 }
168
169 absl::optional<GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle>
FindDoubleHistogramHandleByName(absl::string_view name)170 GlobalInstrumentsRegistryTestPeer::FindDoubleHistogramHandleByName(
171 absl::string_view name) {
172 return FindInstrument<GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle>(
173 GlobalInstrumentsRegistry::GetInstrumentList(), name,
174 GlobalInstrumentsRegistry::ValueType::kDouble,
175 GlobalInstrumentsRegistry::InstrumentType::kHistogram);
176 }
177
178 absl::optional<GlobalInstrumentsRegistry::GlobalInt64GaugeHandle>
FindInt64GaugeHandleByName(absl::string_view name)179 GlobalInstrumentsRegistryTestPeer::FindInt64GaugeHandleByName(
180 absl::string_view name) {
181 return FindInstrument<GlobalInstrumentsRegistry::GlobalInt64GaugeHandle>(
182 GlobalInstrumentsRegistry::GetInstrumentList(), name,
183 GlobalInstrumentsRegistry::ValueType::kInt64,
184 GlobalInstrumentsRegistry::InstrumentType::kGauge);
185 }
186
187 absl::optional<GlobalInstrumentsRegistry::GlobalDoubleGaugeHandle>
FindDoubleGaugeHandleByName(absl::string_view name)188 GlobalInstrumentsRegistryTestPeer::FindDoubleGaugeHandleByName(
189 absl::string_view name) {
190 return FindInstrument<GlobalInstrumentsRegistry::GlobalDoubleGaugeHandle>(
191 GlobalInstrumentsRegistry::GetInstrumentList(), name,
192 GlobalInstrumentsRegistry::ValueType::kDouble,
193 GlobalInstrumentsRegistry::InstrumentType::kGauge);
194 }
195
196 absl::optional<GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle>
FindCallbackInt64GaugeHandleByName(absl::string_view name)197 GlobalInstrumentsRegistryTestPeer::FindCallbackInt64GaugeHandleByName(
198 absl::string_view name) {
199 return FindInstrument<
200 GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle>(
201 GlobalInstrumentsRegistry::GetInstrumentList(), name,
202 GlobalInstrumentsRegistry::ValueType::kInt64,
203 GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge);
204 }
205
206 absl::optional<GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle>
FindCallbackDoubleGaugeHandleByName(absl::string_view name)207 GlobalInstrumentsRegistryTestPeer::FindCallbackDoubleGaugeHandleByName(
208 absl::string_view name) {
209 return FindInstrument<
210 GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle>(
211 GlobalInstrumentsRegistry::GetInstrumentList(), name,
212 GlobalInstrumentsRegistry::ValueType::kDouble,
213 GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge);
214 }
215
216 GlobalInstrumentsRegistry::GlobalInstrumentDescriptor*
FindMetricDescriptorByName(absl::string_view name)217 GlobalInstrumentsRegistryTestPeer::FindMetricDescriptorByName(
218 absl::string_view name) {
219 for (auto& descriptor : GlobalInstrumentsRegistry::GetInstrumentList()) {
220 if (descriptor.name == name) {
221 return &descriptor;
222 }
223 }
224 return nullptr;
225 }
226
227 } // namespace grpc_core
228