• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/libs/full/performance_counters/src/counter_creators.cpp
1
//  Copyright (c) 2007-2022 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
#include <hpx/config.hpp>
8
#include <hpx/actions/transfer_action.hpp>
9
#include <hpx/actions_base/plain_action.hpp>
10
#include <hpx/agas/agas_fwd.hpp>
11
#include <hpx/assert.hpp>
12
#include <hpx/async_distributed/async.hpp>
13
#include <hpx/async_distributed/transfer_continuation_action.hpp>
14
#include <hpx/components_base/agas_interface.hpp>
15
#include <hpx/modules/errors.hpp>
16
#include <hpx/modules/functional.hpp>
17
#include <hpx/modules/type_support.hpp>
18
#include <hpx/naming_base/id_type.hpp>
19
#include <hpx/performance_counters/agas_namespace_action_code.hpp>
20
#include <hpx/performance_counters/counter_creators.hpp>
21
#include <hpx/performance_counters/counters.hpp>
22
#include <hpx/performance_counters/server/component_namespace_counters.hpp>
23
#include <hpx/performance_counters/server/locality_namespace_counters.hpp>
24
#include <hpx/performance_counters/server/primary_namespace_counters.hpp>
25
#include <hpx/performance_counters/server/symbol_namespace_counters.hpp>
26

27
#include <cstdint>
28
#include <string>
29
#include <vector>
30

31
#include <hpx/config/warnings_prefix.hpp>
32

33
///////////////////////////////////////////////////////////////////////////////
34
namespace hpx { namespace performance_counters {
35

36
    ///////////////////////////////////////////////////////////////////////////
37
    // Creation functions to be registered with counter types
38

39
    /// Default discovery function for performance counters; to be registered
40
    /// with the counter types. It will pass the \a counter_info and the
×
41
    /// \a error_code to the supplied function.
42
    bool default_counter_discoverer(counter_info const& info,
43
        discover_counter_func const& f, discover_counters_mode /* mode */,
44
        error_code& ec)
×
45
    {
46
        return f(info, ec);
47
    }
48

49
    /// Default discoverer function for performance counters; to be registered
50
    /// with the counter types. It is suitable to be used for all counters
51
    /// following the naming scheme:
52
    ///
53
    ///   /<objectname>{locality#<locality_id>/total}/<instancename>
×
54
    ///
55
    bool locality_counter_discoverer(counter_info const& info,
56
        discover_counter_func const& f, discover_counters_mode mode,
57
        error_code& ec)
×
58
    {
59
        performance_counters::counter_info i = info;
60

61
        // compose the counter name templates
62
        performance_counters::counter_path_elements p;
×
63
        performance_counters::counter_status status =
×
64
            get_counter_path_elements(info.fullname_, p, ec);
65
        if (!status_is_valid(status))
66
            return false;
×
67

×
68
        if (mode == discover_counters_mode::minimal ||
69
            p.parentinstancename_.empty() || p.instancename_.empty())
×
70
        {
71
            if (p.parentinstancename_.empty())
72
            {
×
73
                p.parentinstancename_ = "locality#*";
74
                p.parentinstanceindex_ = -1;
75
            }
×
76

77
            if (p.instancename_.empty())
78
            {
×
79
                p.instancename_ = "total";
80
                p.instanceindex_ = -1;
81
            }
×
82

×
83
            status = get_counter_name(p, i.fullname_, ec);
×
84
            if (!status_is_valid(status) || !f(i, ec) || ec)
85
                return false;
×
86
        }
87
        else if (!f(i, ec) || ec)
88
        {
89
            return false;
90
        }
×
91

×
92
        if (&ec != &throws)
93
            ec = make_success_code();
94

×
95
        return true;
96
    }
97

98
    /// Default discoverer function for performance counters; to be registered
99
    /// with the counter types. It is suitable to be used for all counters
100
    /// following the naming scheme:
101
    ///
102
    ///   /<objectname>(locality#<locality_id>/pool#<pool_name>/total)/<instancename>
×
103
    ///
104
    bool locality_pool_counter_discoverer(counter_info const& info,
105
        discover_counter_func const& f, discover_counters_mode mode,
106
        error_code& ec)
×
107
    {
108
        performance_counters::counter_info i = info;
109

110
        // compose the counter name templates
111
        performance_counters::counter_path_elements p;
×
112
        performance_counters::counter_status status =
×
113
            get_counter_path_elements(info.fullname_, p, ec);
114
        if (!status_is_valid(status))
115
            return false;
×
116

×
117
        if (mode == discover_counters_mode::minimal ||
118
            p.parentinstancename_.empty() || p.instancename_.empty())
×
119
        {
120
            if (p.parentinstancename_.empty())
121
            {
×
122
                p.parentinstancename_ = "locality#*";
123
                p.parentinstanceindex_ = -1;
124
            }
×
125

126
            if (p.instancename_.empty())
127
            {
×
128
                p.instancename_ = "total";
129
                p.instanceindex_ = -1;
×
130
            }
131
            else if (p.subinstancename_.empty())
132
            {
×
133
                p.subinstancename_ = "total";
134
                p.instanceindex_ = -1;
135
            }
×
136

×
137
            status = get_counter_name(p, i.fullname_, ec);
×
138
            if (!status_is_valid(status) || !f(i, ec) || ec)
139
                return false;
140

×
141
            p.instancename_ = "pool#*";
142
            p.instanceindex_ = -1;
143

×
144
            p.subinstancename_ = "total";
145
            p.subinstanceindex_ = -1;
×
146

×
147
            status = get_counter_name(p, i.fullname_, ec);
×
148
            if (!status_is_valid(status) || !f(i, ec) || ec)
149
                return false;
×
150
        }
151
        else if (!f(i, ec) || ec)
152
        {
153
            return false;
154
        }
×
155

×
156
        if (&ec != &throws)
157
            ec = make_success_code();
158

×
159
        return true;
160
    }
161

162
    /// Default discoverer function for AGAS performance counters; to be
163
    /// registered with the counter types. It is suitable to be used for all
164
    /// counters following the naming scheme:
165
    ///
166
    ///   /<objectname>{locality#0/total}/<instancename>
×
167
    ///
168
    bool locality0_counter_discoverer(counter_info const& info,
169
        discover_counter_func const& f, discover_counters_mode mode,
170
        error_code& ec)
×
171
    {
172
        performance_counters::counter_info i = info;
173

174
        // compose the counter name templates
175
        performance_counters::counter_path_elements p;
×
176
        performance_counters::counter_status status =
×
177
            get_counter_path_elements(info.fullname_, p, ec);
178
        if (!status_is_valid(status))
179
            return false;
180

×
181
        // restrict to locality zero
182
        if (p.parentinstancename_ == "locality#*")
183
        {
×
184
            p.parentinstancename_ = "locality";
185
            p.parentinstanceindex_ = 0;
186
        }
×
187

×
188
        if (mode == discover_counters_mode::minimal ||
189
            p.parentinstancename_.empty() || p.instancename_.empty())
×
190
        {
191
            if (p.parentinstancename_.empty())
192
            {
×
193
                p.parentinstancename_ = "locality";
194
                p.parentinstanceindex_ = 0;
195
            }
×
196

197
            if (p.instancename_.empty())
198
            {
×
199
                p.instancename_ = "total";
200
                p.instanceindex_ = -1;
201
            }
202
        }
×
203

×
204
        status = get_counter_name(p, i.fullname_, ec);
×
205
        if (!status_is_valid(status) || !f(i, ec) || ec)
206
            return false;
×
207

×
208
        if (&ec != &throws)
209
            ec = make_success_code();
210

×
211
        return true;
212
    }
213

214
    /// Default discoverer function for performance counters; to be registered
215
    /// with the counter types. It is suitable to be used for all counters
216
    /// following the naming scheme:
217
    ///
218
    ///   /<objectname>{locality#<locality_id>/thread#<threadnum>}/<instancename>
×
219
    ///
220
    bool locality_thread_counter_discoverer(counter_info const& info,
221
        discover_counter_func const& f, discover_counters_mode mode,
222
        error_code& ec)
×
223
    {
224
        performance_counters::counter_info i = info;
225

226
        // compose the counter name templates
227
        performance_counters::counter_path_elements p;
×
228
        performance_counters::counter_status status =
×
229
            get_counter_path_elements(info.fullname_, p, ec);
230
        if (!status_is_valid(status))
231
            return false;
×
232

×
233
        if (mode == discover_counters_mode::minimal ||
234
            p.parentinstancename_.empty() || p.instancename_.empty())
×
235
        {
236
            if (p.parentinstancename_.empty())
237
            {
×
238
                p.parentinstancename_ = "locality#*";
239
                p.parentinstanceindex_ = -1;
240
            }
×
241

242
            if (p.instancename_.empty())
243
            {
×
244
                p.instancename_ = "total";
245
                p.instanceindex_ = -1;
246
            }
×
247

×
248
            status = get_counter_name(p, i.fullname_, ec);
×
249
            if (!status_is_valid(status) || !f(i, ec) || ec)
250
                return false;
251

×
252
            p.instancename_ = "worker-thread#*";
253
            p.instanceindex_ = -1;
×
254

×
255
            status = get_counter_name(p, i.fullname_, ec);
×
256
            if (!status_is_valid(status) || !f(i, ec) || ec)
257
                return false;
×
258
        }
259
        else if (!f(i, ec) || ec)
260
        {
261
            return false;
262
        }
×
263

×
264
        if (&ec != &throws)
265
            ec = make_success_code();
266

×
267
        return true;
268
    }
269

270
    /// Default discoverer function for performance counters; to be registered
271
    /// with the counter types. It is suitable to be used for all counters
272
    /// following the naming scheme:
273
    ///
274
    ///   /<objectname>{locality#<locality_id>/pool#<pool_name>/thread#<threadnum>}/<instancename>
×
275
    ///
276
    bool locality_pool_thread_counter_discoverer(counter_info const& info,
277
        discover_counter_func const& f, discover_counters_mode mode,
278
        error_code& ec)
×
279
    {
280
        performance_counters::counter_info i = info;
281

282
        // compose the counter name templates
283
        performance_counters::counter_path_elements p;
×
284
        performance_counters::counter_status status =
×
285
            get_counter_path_elements(info.fullname_, p, ec);
286
        if (!status_is_valid(status))
287
            return false;
×
288

×
289
        if (mode == discover_counters_mode::minimal ||
290
            p.parentinstancename_.empty() || p.instancename_.empty() ||
291
            p.subinstancename_.empty())
×
292
        {
293
            if (p.parentinstancename_.empty())
294
            {
×
295
                p.parentinstancename_ = "locality#*";
296
                p.parentinstanceindex_ = -1;
297
            }
×
298

299
            if (p.instancename_.empty())
300
            {
×
301
                p.instancename_ = "total";
302
                p.instanceindex_ = -1;
×
303
            }
304
            else if (p.subinstancename_.empty())
305
            {
×
306
                p.subinstancename_ = "total";
307
                p.instanceindex_ = -1;
308
            }
×
309

×
310
            status = get_counter_name(p, i.fullname_, ec);
×
311
            if (!status_is_valid(status) || !f(i, ec) || ec)
312
                return false;
313

×
314
            p.instancename_ = "pool#*";
315
            p.instanceindex_ = -1;
316

×
317
            p.subinstancename_ = "worker-thread#*";
318
            p.subinstanceindex_ = -1;
×
319

×
320
            status = get_counter_name(p, i.fullname_, ec);
×
321
            if (!status_is_valid(status) || !f(i, ec) || ec)
322
                return false;
×
323
        }
324
        else if (!f(i, ec) || ec)
325
        {
326
            return false;
327
        }
×
328

×
329
        if (&ec != &throws)
330
            ec = make_success_code();
331

×
332
        return true;
333
    }
334

335
    /// Default discoverer function for performance counters; to be registered
336
    /// with the counter types. It is suitable to be used for all counters
337
    /// following the naming scheme:
338
    ///
339
    ///   /<objectname>{locality#<locality_id>/pool#<poolname>/thread#<threadnum>}/<instancename>
340
    ///
341
    /// This is essentially the same as above just that locality#*/total is not
×
342
    /// supported.
343
    bool locality_pool_thread_no_total_counter_discoverer(
344
        counter_info const& info, discover_counter_func const& f,
345
        discover_counters_mode mode, error_code& ec)
×
346
    {
347
        performance_counters::counter_info i = info;
348

349
        // compose the counter name templates
350
        performance_counters::counter_path_elements p;
×
351
        performance_counters::counter_status status =
×
352
            get_counter_path_elements(info.fullname_, p, ec);
353
        if (!status_is_valid(status))
354
            return false;
×
355

×
356
        if (mode == discover_counters_mode::minimal ||
357
            p.parentinstancename_.empty() || p.instancename_.empty() ||
358
            p.subinstancename_.empty())
×
359
        {
360
            if (p.parentinstancename_.empty())
361
            {
×
362
                p.parentinstancename_ = "locality#*";
363
                p.parentinstanceindex_ = -1;
364
            }
365

×
366
            p.instancename_ = "pool#*";
367
            p.instanceindex_ = -1;
368

×
369
            p.subinstancename_ = "worker-thread#*";
370
            p.subinstanceindex_ = -1;
×
371

×
372
            status = get_counter_name(p, i.fullname_, ec);
×
373
            if (!status_is_valid(status) || !f(i, ec) || ec)
374
                return false;
×
375
        }
376
        else if (!f(i, ec) || ec)
377
        {
378
            return false;
379
        }
×
380

×
381
        if (&ec != &throws)
382
            ec = make_success_code();
383

×
384
        return true;
385
    }
386

387
    /// Default discoverer function for performance counters; to be registered
388
    /// with the counter types. It is suitable to be used for all counters
389
    /// following the naming scheme:
390
    ///
391
    ///   /<objectname>(locality#<locality_id>/numa#<threadnum>)/<instancename>
×
392
    ///
393
    bool locality_numa_counter_discoverer(counter_info const& info,
394
        discover_counter_func const& f, discover_counters_mode mode,
395
        error_code& ec)
×
396
    {
397
        performance_counters::counter_info i = info;
398

399
        // compose the counter name templates
400
        performance_counters::counter_path_elements p;
×
401
        performance_counters::counter_status status =
×
402
            get_counter_path_elements(info.fullname_, p, ec);
403
        if (!status_is_valid(status))
404
            return false;
×
405

×
406
        if (mode == discover_counters_mode::minimal ||
407
            p.parentinstancename_.empty() || p.instancename_.empty())
×
408
        {
409
            if (p.parentinstancename_.empty())
410
            {
×
411
                p.parentinstancename_ = "locality#*";
412
                p.parentinstanceindex_ = -1;
413
            }
×
414

415
            if (p.instancename_.empty())
416
            {
×
417
                p.instancename_ = "total";
418
                p.instanceindex_ = -1;
419
            }
×
420

×
421
            status = get_counter_name(p, i.fullname_, ec);
×
422
            if (!status_is_valid(status) || !f(i, ec) || ec)
423
                return false;
424

×
425
            p.instancename_ = "numa-node#*";
426
            p.instanceindex_ = -1;
×
427

×
428
            status = get_counter_name(p, i.fullname_, ec);
×
429
            if (!status_is_valid(status) || !f(i, ec) || ec)
430
                return false;
×
431
        }
432
        else if (!f(i, ec) || ec)
433
        {
434
            return false;
435
        }
×
436

×
437
        if (&ec != &throws)
438
            ec = make_success_code();
439

×
440
        return true;
441
    }
442

443
    ///////////////////////////////////////////////////////////////////////////
444
    /// Creation function for raw counters. The passed function is encapsulating
445
    /// the actual value to monitor. This function checks the validity of the
446
    /// supplied counter name, it has to follow the scheme:
447
    ///
448
    ///   /<objectname>{locality#<locality_id>/total}/<instancename>
×
449
    ///
450
    naming::gid_type locality_raw_counter_creator(counter_info const& info,
451
        hpx::function<std::int64_t(bool)> const& f, error_code& ec)
452
    {
453
        // verify the validity of the counter instance name
×
454
        counter_path_elements paths;
×
455
        get_counter_path_elements(info.fullname_, paths, ec);
456
        if (ec)
457
            return naming::invalid_gid;
×
458

459
        if (paths.parentinstance_is_basename_)
×
460
        {
461
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
462
                "locality_raw_counter_creator",
463
                "invalid counter instance parent name: " +
464
                    paths.parentinstancename_);
465
            return naming::invalid_gid;
466
        }
×
467

468
        if (paths.instancename_ == "total" && paths.instanceindex_ == -1)
×
469
            return detail::create_raw_counter(
470
                info, f, ec);    // overall counter
×
471

472
        HPX_THROWS_IF(ec, hpx::error::bad_parameter,
473
            "locality_raw_counter_creator",
474
            "invalid counter instance name: " + paths.instancename_);
×
475
        return naming::invalid_gid;
476
    }
×
477

478
    naming::gid_type locality_raw_values_counter_creator(
479
        counter_info const& info,
480
        hpx::function<std::vector<std::int64_t>(bool)> const& f, error_code& ec)
481
    {
482
        // verify the validity of the counter instance name
×
483
        counter_path_elements paths;
×
484
        get_counter_path_elements(info.fullname_, paths, ec);
485
        if (ec)
486
            return naming::invalid_gid;
×
487

488
        if (paths.parentinstance_is_basename_)
×
489
        {
490
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
491
                "locality_raw_values_counter_creator",
492
                "invalid counter instance parent name: " +
493
                    paths.parentinstancename_);
494
            return naming::invalid_gid;
495
        }
×
496

497
        if (paths.instancename_ == "total" && paths.instanceindex_ == -1)
498
        {
×
499
            return detail::create_raw_counter(
500
                info, f, ec);    // overall counter
501
        }
×
502

503
        HPX_THROWS_IF(ec, hpx::error::bad_parameter,
504
            "locality_raw_values_counter_creator",
505
            "invalid counter instance name: " + paths.instancename_);
×
506
        return naming::invalid_gid;
507
    }
508

509
    namespace detail {
×
510

511
        naming::gid_type retrieve_agas_counter(std::string const& name,
512
            hpx::id_type const& agas_id, error_code& ec)
513
        {
514
            naming::gid_type id;
515

516
#if !defined(HPX_COMPUTE_DEVICE_CODE)
517
            //  get action code from counter type
×
518
            agas::namespace_action_code service_code =
×
519
                agas::detail::retrieve_action_service_code(name, ec);
520
            if (agas::invalid_request == service_code)
521
                return id;
×
522

523
            switch (service_code)
×
524
            {
525
            case agas::component_ns_statistics_counter:
526
            {
×
527
                agas::component_namespace_statistics_counter_action action;
528
                return action(agas_id, name).get_gid();
×
529
            }
530
            case agas::locality_ns_statistics_counter:
531
            {
×
532
                agas::locality_namespace_statistics_counter_action action;
533
                return action(agas_id, name).get_gid();
×
534
            }
535
            case agas::symbol_ns_statistics_counter:
536
            {
×
537
                agas::symbol_namespace_statistics_counter_action action;
538
                return action(agas_id, name).get_gid();
×
539
            }
540
            case agas::primary_ns_statistics_counter:
541
            {
×
542
                agas::primary_namespace_statistics_counter_action action;
543
                return action(agas_id, name).get_gid();
544
            }
×
545
            default:
546
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
547
                    "retrieve_statistics_counter",
548
                    "unknown counter agas counter name: " + name);
549
                break;
550
            }
551
            return id;
552
#else
553
            HPX_ASSERT(false);
554
            HPX_UNUSED(name);
555
            HPX_UNUSED(agas_id);
556
            HPX_UNUSED(ec);
557
            return id;
558
#endif
559
        }
560
    }    // namespace detail
561

562
    ///////////////////////////////////////////////////////////////////////////
563
    /// Creation function for raw AGAS counters. This function checks the
564
    /// validity of the supplied counter name, it has to follow the scheme:
565
    ///
566
    ///   /agas(<objectinstance>/total)/<instancename>
×
567
    ///
568
    naming::gid_type agas_raw_counter_creator(counter_info const& info,
569
        error_code& ec, char const* const service_name)
570
    {
571
        // verify the validity of the counter instance name
×
572
        counter_path_elements paths;
×
573
        get_counter_path_elements(info.fullname_, paths, ec);
574
        if (ec)
575
            return naming::invalid_gid;
×
576

577
        if (paths.objectname_ != "agas")
×
578
        {
579
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
580
                "agas_raw_counter_creator",
581
                "unknown performance counter (unrelated to AGAS)");
582
            return naming::invalid_gid;
×
583
        }
584
        if (paths.parentinstance_is_basename_)
×
585
        {
586
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
587
                "agas_raw_counter_creator",
588
                "invalid counter instance parent name: " +
589
                    paths.parentinstancename_);
590
            return naming::invalid_gid;
591
        }
592

593
        // counter instance name: <agas_instance_name>/total
×
594
        // for instance: locality#0/total
595
        if (paths.instancename_ == "total" && paths.instanceindex_ == -1)
596
        {
×
597
            // find the referenced AGAS instance and dispatch the request there
598
            std::string service(agas::service_name);
599
            service += paths.parentinstancename_;
×
600

601
            if (-1 == paths.parentinstanceindex_)
×
602
            {
603
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
604
                    "agas_raw_counter_creator",
605
                    "invalid parent instance index: -1");
606
                return naming::invalid_gid;
607
            }
×
608
            service += "#";
609
            service += std::to_string(paths.parentinstanceindex_);
610

611
            service += "/";
612
            service += service_name;
×
613

×
614
            hpx::id_type id = agas::resolve_name(launch::sync, service, ec);
615
            if (id == hpx::invalid_id)
×
616
            {
617
                HPX_THROWS_IF(ec, hpx::error::not_implemented,
618
                    "agas_raw_counter_creator",
619
                    "invalid counter name: " +
620
                        remove_counter_prefix(info.fullname_));
621
                return naming::invalid_gid;
622
            }
×
623

624
            return detail::retrieve_agas_counter(info.fullname_, id, ec);
625
        }
×
626

627
        HPX_THROWS_IF(ec, hpx::error::not_implemented,
628
            "agas_raw_counter_creator",
629
            "invalid counter type name: " + paths.instancename_);
×
630
        return naming::invalid_gid;
631
    }
632
}}    // namespace hpx::performance_counters
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc