@@ -141,6 +141,90 @@ TEST(Async, CollectWithThrow) {
141
141
ARCTICDB_DEBUG (log ::version (), " Collect returned" );
142
142
}
143
143
144
+ TEST (Async, StatsQueryDemo) {
145
+ using namespace arcticdb ::util::query_stats;
146
+ class EnableQueryStatsRAII {
147
+ public:
148
+ EnableQueryStatsRAII () {
149
+ QueryStats::instance ().is_enabled_ = true ;
150
+ }
151
+ ~EnableQueryStatsRAII () {
152
+ QueryStats::instance ().is_enabled_ = false ;
153
+ }
154
+ };
155
+ EnableQueryStatsRAII enable_query_stats;
156
+ async::TaskScheduler sched{20 , 20 };
157
+ auto & instance = QueryStats::instance ();
158
+ auto work = [&]() {
159
+ std::vector<folly::Future<folly::Unit>> stuff;
160
+ {
161
+ /*
162
+ "AddFuture": {
163
+ "count": 2,
164
+ }
165
+ */
166
+ QUERY_STATS_ADD_GROUP (storage_ops, " AddFuture" ) // Always add group at the bottom of the C++ call stack
167
+ QUERY_STATS_ADD (count, 1 )
168
+ QUERY_STATS_ADD (count, 1 )
169
+ stuff.push_back (sched.submit_cpu_task (MaybeThrowTask (false ))
170
+ .thenValue ([](auto )
171
+ {
172
+ /*
173
+ "key_type": {
174
+ "l": {
175
+ "storage_ops": {
176
+ "ListObjectsV2": {
177
+ "result_count": 123,
178
+ }
179
+ }
180
+ }
181
+ }
182
+ */
183
+ QUERY_STATS_ADD_GROUP (key_type, " l" )
184
+ QUERY_STATS_ADD_GROUP (storage_ops, " ListObjectsV2" )
185
+ QUERY_STATS_ADD (result_count, 123 )
186
+ return folly::Unit{};
187
+ })
188
+ .via (&async::io_executor ()) // switching executor in the chain won't create a new child layer
189
+ );
190
+ stuff.push_back (sched.submit_io_task (MaybeThrowTask (false ))
191
+ .thenValue ([](auto )
192
+ {
193
+ /*
194
+ "key_type": {
195
+ "l": {
196
+ "storage_ops": {
197
+ "ListObjectsV2": {
198
+ "result_count": 456,
199
+ }
200
+ }
201
+ }
202
+ }
203
+ */
204
+ QUERY_STATS_ADD_GROUP (key_type, " l" )
205
+ QUERY_STATS_ADD_GROUP (storage_ops, " ListObjectsV2" )
206
+ QUERY_STATS_ADD (result_count, 456 )
207
+ return folly::Unit{};
208
+ })
209
+ );
210
+ folly::collect (stuff).get ();
211
+ ASSERT_EQ (instance.thread_local_var_ .child_layers_ .size (), 2 ); // One child_layers_ for each chain of tasks
212
+ const auto & add_future_layer = instance.root_layer ()->next_layer_maps_ [static_cast <size_t >(StatsGroupName::storage_ops)][" AddFuture" ];
213
+ ASSERT_EQ (add_future_layer->stats_ [static_cast <size_t >(StatsName::count)], 2 );
214
+ }
215
+ ASSERT_EQ (instance.thread_local_var_ .child_layers_ .size (), 0 ); // child maps should be folded into root map when the root add group stat deconstructs
216
+ const auto & list_objects_layer = instance.root_layer ()->next_layer_maps_ [static_cast <size_t >(StatsGroupName::storage_ops)][" AddFuture" ]
217
+ ->next_layer_maps_ [static_cast <size_t >(StatsGroupName::key_type)][" l" ]
218
+ ->next_layer_maps_ [static_cast <size_t >(StatsGroupName::storage_ops)][" ListObjectsV2" ];
219
+ ASSERT_EQ (list_objects_layer->stats_ [static_cast <size_t >(StatsName::result_count)], 579 ); // child map stats should be summed
220
+ };
221
+ std::thread t1 (work), t2 (work); // mimic multithreading at python level
222
+ t1.join ();
223
+ t2.join ();
224
+ auto root_layers = instance.root_layers ();
225
+ ASSERT_EQ (root_layers.size (), 2 ); // Each pseudo-python thread will create one root layer
226
+ }
227
+
144
228
using IndexSegmentReader = int ;
145
229
146
230
int get_index_segment_reader_impl (arcticdb::StreamId id) {
0 commit comments