• 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

51.13
/libs/core/init_runtime_local/src/init_logging.cpp
1
//  Copyright (c) 2007-2024 Hartmut Kaiser
2
//  Copyright (c)      2011 Bryce Lelbach
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/config.hpp>
9

10
#if defined(HPX_HAVE_LOGGING)
11
#include <hpx/init_runtime_local/detail/init_logging.hpp>
12
#include <hpx/modules/logging.hpp>
13
#include <hpx/modules/runtime_configuration.hpp>
14
#include <hpx/modules/runtime_local.hpp>
15
#include <hpx/modules/threading_base.hpp>
16

17
#include <cstddef>
18
#include <cstdint>
19
#include <cstdlib>
20
#include <string>
21

22
#if defined(ANDROID) || defined(__ANDROID__)
23
#include <android/log.h>
24
#endif
25

26
///////////////////////////////////////////////////////////////////////////////
27
namespace hpx::util {
28

29
    using logger_writer_type = logging::writer::named_write;
30

31
    ///////////////////////////////////////////////////////////////////////////
32
    // custom formatter: shepherd
33
    struct shepherd_thread_id final : logging::formatter::manipulator
34
    {
35
        void operator()(std::ostream& to) const override
128✔
36
        {
37
            error_code ec(throwmode::lightweight);
×
38
            std::size_t const thread_num = hpx::get_worker_thread_num(ec);
39

40
            if (static_cast<std::size_t>(-1) != thread_num)
×
41
            {
42
                util::format_to(to, "{:016x}", thread_num);
×
43
            }
44
            else
×
45
            {
46
                to << std::string(16, '-');
47
            }
48
        }
×
49
    };
50

×
51
    ///////////////////////////////////////////////////////////////////////////
52
    // custom formatter: locality prefix
53
    struct locality_prefix final : logging::formatter::manipulator
54
    {
55
        void operator()(std::ostream& to) const override
128✔
56
        {
57
            std::uint32_t const locality_id = hpx::get_locality_id();
×
58

59
            if (~static_cast<std::uint32_t>(0) != locality_id)
×
60
            {
61
                util::format_to(to, "{:08x}", locality_id);
×
62
            }
63
            else
×
64
            {
65
                // called from outside a HPX thread
66
                to << std::string(8, '-');
67
            }
68
        }
×
69
    };
70

×
71
    ///////////////////////////////////////////////////////////////////////////
72
    // custom formatter: HPX thread id
73
    struct thread_id final : logging::formatter::manipulator
74
    {
75
        void operator()(std::ostream& to) const override
128✔
76
        {
77
            threads::thread_self const* self = threads::get_self_ptr();
×
78
            if (nullptr != self)
79
            {
×
80
                // called from inside a HPX thread
×
81
                threads::thread_id_type const id = threads::get_self_id();
82
                if (id != threads::invalid_thread_id)
83
                {
×
84
                    auto const value =
×
85
                        reinterpret_cast<std::ptrdiff_t>(id.get());
86
                    util::format_to(to, "{:016x}", value);
87
                    return;
×
88
                }
×
89
            }
90

91
            // called from outside a HPX thread or invalid thread id
92
            to << std::string(16, '-');
93
        }
94
    };
×
95

96
    ///////////////////////////////////////////////////////////////////////////
97
    // custom formatter: HPX thread phase
98
    struct thread_phase final : logging::formatter::manipulator
99
    {
100
        void operator()(std::ostream& to) const override
128✔
101
        {
102
            threads::thread_self const* self = threads::get_self_ptr();
×
103
            if (nullptr != self)
104
            {
×
105
                // called from inside a HPX thread
×
106
                std::size_t const phase = self->get_thread_phase();
107
                if (0 != phase)
108
                {
×
109
                    util::format_to(to, "{:04x}", self->get_thread_phase());
×
110
                    return;
111
                }
×
112
            }
×
113

114
            // called from outside a HPX thread or no phase given
115
            to << std::string(4, '-');    //-V112
116
        }
117
    };
×
118

119
    ///////////////////////////////////////////////////////////////////////////
120
    // custom formatter: locality prefix of parent thread
121
    struct parent_thread_locality final : logging::formatter::manipulator
122
    {
123
        void operator()(std::ostream& to) const override
128✔
124
        {
125
            std::uint32_t const parent_locality_id =
×
126
                threads::get_parent_locality_id();
127
            if (~static_cast<std::uint32_t>(0) != parent_locality_id)
128
            {
×
129
                // called from inside a HPX thread
×
130
                util::format_to(to, "{:08x}", parent_locality_id);
131
            }
132
            else
×
133
            {
134
                // called from outside a HPX thread
135
                to << std::string(8, '-');
136
            }
137
        }
×
138
    };
139

×
140
    ///////////////////////////////////////////////////////////////////////////
141
    // custom formatter: HPX parent thread id
142
    struct parent_thread_id final : logging::formatter::manipulator
143
    {
144
        void operator()(std::ostream& to) const override
128✔
145
        {
146
            threads::thread_id_type const parent_id = threads::get_parent_id();
×
147
            if (nullptr != parent_id)
148
            {
×
149
                // called from inside a HPX thread
×
150
                auto const value =
151
                    reinterpret_cast<std::ptrdiff_t>(parent_id.get());
152
                util::format_to(to, "{:016x}", value);
153
            }
×
154
            else
×
155
            {
156
                // called from outside a HPX thread
157
                to << std::string(16, '-');
158
            }
159
        }
×
160
    };
161

×
162
    ///////////////////////////////////////////////////////////////////////////
163
    // custom formatter: HPX parent thread phase
164
    struct parent_thread_phase final : logging::formatter::manipulator
165
    {
166
        void operator()(std::ostream& to) const override
128✔
167
        {
168
            std::size_t const parent_phase = threads::get_parent_phase();
×
169
            if (0 != parent_phase)
170
            {
×
171
                // called from inside a HPX thread
×
172
                util::format_to(to, "{:04x}", parent_phase);
173
            }
174
            else
×
175
            {
176
                // called from outside a HPX thread
177
                to << std::string(4, '-');    //-V112
178
            }
179
        }
×
180
    };
181

×
182
#if defined(ANDROID) || defined(__ANDROID__)
183
    // default log destination for Android
184
    struct android_log final : logging::destination::manipulator
185
    {
186
        android_log(char const* tag_)
187
          : tag(tag_)
188
        {
189
        }
190

191
        void operator()(logging::message const& msg) override
192
        {
193
            __android_log_write(
194
                ANDROID_LOG_DEBUG, tag.c_str(), msg.full_string().c_str());
195
        }
196

197
        friend bool operator==(android_log const& lhs, android_log const& rhs)
198
        {
199
            return lhs.tag == rhs.tag;
200
        }
201
        friend bool operator!=(android_log const& lhs, android_log const& rhs)
202
        {
203
            return !(lhs == rhs);
204
        }
205

206
        std::string tag;
207
    };
208
#endif
209

64✔
210
    ///////////////////////////////////////////////////////////////////////////
211
    struct dummy_thread_component_id final : logging::formatter::manipulator
×
212
    {
213
        void operator()(std::ostream& to) const override
×
214
        {
×
215
            to << std::string(16, '-');
216
        }
217
    };
218

219
    ///////////////////////////////////////////////////////////////////////////
×
220
    // custom log destination: send generated strings to console
221
    void console_local::operator()(logging::message const& msg)
×
222
    {
223
        switch (dest_)
224
        {
×
225
        // NOLINTNEXTLINE(bugprone-branch-clone)
×
226
        case logging_destination::hpx:
227
            LHPX_CONSOLE_(level_) << msg;
228
            break;
×
229

×
230
        case logging_destination::timing:
231
            LTIM_CONSOLE_(level_) << msg;
232
            break;
×
233

×
234
        case logging_destination::agas:
235
            LAGAS_CONSOLE_(level_) << msg;
236
            break;
×
237

×
238
        case logging_destination::parcel:
239
            LPT_CONSOLE_(level_) << msg;
240
            break;
×
241

×
242
        case logging_destination::app:
243
            LAPP_CONSOLE_(level_) << msg;
244
            break;
×
245

×
246
        case logging_destination::debuglog:
247
            LDEB_CONSOLE_ << msg;
248
            break;
×
249
        }
250
    }
251

252
    namespace detail {
253

768✔
254
        // unescape config entry
255
        std::string unescape(std::string const& value)
256
        {
768✔
257
            std::string result;
258
            if (std::string::size_type pos1 = value.find_first_of('\\', 0);
259
                std::string::npos != pos1)
260
            {
261
                std::string::size_type pos = 0;
262
                do
384✔
263
                {
264
                    switch (value[pos1 + 1])
×
265
                    {
266
                    case '\\':
267
                    case '\"':
×
268
                    case '?':
×
269
                        result = result + value.substr(pos, pos1 - pos);
×
270
                        pos1 = value.find_first_of('\\', (pos = pos1 + 1) + 1);
271
                        break;
384✔
272

1,152✔
273
                    case 'n':
274
                        result = result + value.substr(pos, pos1 - pos) + "\n";
384✔
275
                        pos1 = value.find_first_of('\\', pos = pos1 + 1);
384✔
276
                        ++pos;
277
                        break;
×
278

×
279
                    default:
280
                        result = result + value.substr(pos, pos1 - pos + 1);
281
                        pos1 = value.find_first_of('\\', pos = pos1 + 1);
282
                    }
384✔
283

768✔
284
                } while (pos1 != std::string::npos);
285
                result = result + value.substr(pos);
286
            }
287
            else
288
            {
289
                // the string doesn't contain any escaped character sequences
290
                result = value;
768✔
291
            }
292
            return result;
293
        }
128✔
294

295
        void define_common_formatters(logger_writer_type& writer)
256✔
296
        {
256✔
297
            writer.set_formatter("osthread", shepherd_thread_id());
256✔
298
            writer.set_formatter("locality", locality_prefix());
256✔
299
            writer.set_formatter("hpxthread", thread_id());
256✔
300
            writer.set_formatter("hpxphase", thread_phase());
256✔
301
            writer.set_formatter("hpxparent", parent_thread_id());
256✔
302
            writer.set_formatter("hpxparentphase", parent_thread_phase());
128✔
303
            writer.set_formatter("parentloc", parent_thread_locality());
304
        }
64✔
305

306
        void define_formatters_local(logger_writer_type& writer)
64✔
307
        {
128✔
308
            define_common_formatters(writer);
64✔
309
            writer.set_formatter("hpxcomponent", dummy_thread_component_id());
310
        }
311

312
        ///////////////////////////////////////////////////////////////////////
313
        namespace {
768✔
314

315
            std::string empty_string;
316
        }
1,536✔
317

318
        log_settings get_log_settings(util::section const& ini, char const* sec)
768✔
319
        {
320
            log_settings result;
321
            if (ini.has_section(sec))
2,304✔
322
            {
768✔
323
                util::section const* logini = ini.get_section(sec);
768✔
324
                HPX_ASSERT(nullptr != logini);
768✔
325

326
                result.level_ = logini ?
327
                    logini->get_entry("level", empty_string) :
768✔
328
                    empty_string;
768✔
329
                if (logini && !result.level_.empty())
2,304✔
330
                {
331
                    result.dest_ =
332
                        logini->get_entry("destination", empty_string);
768✔
333
                    result.format_ = detail::unescape(
×
334
                        logini->get_entry("format", empty_string));
335
                }
336
            }
64✔
337
            return result;
338
        }
339

128✔
340
        ///////////////////////////////////////////////////////////////////////
64✔
341
        void get_console_local(logger_writer_type& writer, char const* name,
342
            logging::level lvl, logging_destination dest)
343
        {
344
            writer.set_destination(name, console_local(lvl, dest));
345
        }
64✔
346

347
#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS)
348
        ///////////////////////////////////////////////////////////////////////
349
        // initialize logging for AGAS
350
        void init_agas_log(logging::level lvl, std::string logdest,
351
            std::string logformat, bool isconsole,
64✔
352
            void (*set_console_dest)(logger_writer_type&, char const*,
353
                logging::level, logging_destination),
×
354
            void (*define_formatters)(logging::writer::named_write&))
355
        {
356
            if (hpx::util::logging::level::disable_all != lvl)
357
            {
358
                logger_writer_type& writer = agas_logger()->writer();
359

360
#if defined(ANDROID) || defined(__ANDROID__)
361
                if (logdest.empty())    // ensure minimal defaults
×
362
                    logdest = isconsole ? "android_log" : "console";
×
363
                agas_logger()->writer().set_destination(
364
                    "android_log", android_log("hpx.agas"));
×
365
#else
366
                if (logdest.empty())    // ensure minimal defaults
367
                    logdest = isconsole ? "cerr" : "console";
×
368
#endif
369
                if (logformat.empty())
×
370
                    logformat = "|\\n";
×
371

372
                set_console_dest(writer, "console", lvl,
×
373
                    logging_destination::agas);    //-V106
374
                writer.write(logformat, logdest);
64✔
375
                define_formatters(writer);
64✔
376

377
                agas_logger()->mark_as_initialized();
64✔
378
            }
379
            agas_logger()->set_enabled(lvl);
380
        }
381

382
        void init_agas_log(runtime_configuration const& ini, bool isconsole,
64✔
383
            void (*set_console_dest)(logger_writer_type&, char const*,
384
                logging::level, logging_destination),
385
            void (*define_formatters)(logging::writer::named_write&))
64✔
386
        {
64✔
387
            auto settings = detail::get_log_settings(ini, "hpx.logging.agas");
388

128✔
389
            auto lvl = hpx::util::logging::level::disable_all;
390
            if (!settings.level_.empty())
391
                lvl = detail::get_log_level(settings.level_, true);
64✔
392

393
            init_agas_log(lvl, HPX_MOVE(settings.dest_),
394
                HPX_MOVE(settings.format_), isconsole, set_console_dest,
395
                define_formatters);
64✔
396
        }
397

398
        ///////////////////////////////////////////////////////////////////////
399
        // initialize logging for the parcel transport
400
        void init_parcel_log(logging::level lvl, std::string logdest,
401
            std::string logformat, bool isconsole,
64✔
402
            void (*set_console_dest)(logger_writer_type&, char const*,
403
                logging::level, logging_destination),
×
404
            void (*define_formatters)(logging::writer::named_write&))
405
        {
406
            if (hpx::util::logging::level::disable_all != lvl)
407
            {
408
                logger_writer_type& writer = parcel_logger()->writer();
409

410
#if defined(ANDROID) || defined(__ANDROID__)
411
                if (logdest.empty())    // ensure minimal defaults
×
412
                    logdest = isconsole ? "android_log" : "console";
×
413
                parcel_logger()->writer().set_destination(
414
                    "android_log", android_log("hpx.parcel"));
×
415
#else
416
                if (logdest.empty())    // ensure minimal defaults
417
                    logdest = isconsole ? "cerr" : "console";
×
418
#endif
419
                if (logformat.empty())
×
420
                    logformat = "|\\n";
×
421

422
                set_console_dest(writer, "console", lvl,
×
423
                    logging_destination::parcel);    //-V106
424
                writer.write(logformat, logdest);
64✔
425
                define_formatters(writer);
64✔
426

427
                parcel_logger()->mark_as_initialized();
64✔
428
            }
429
            parcel_logger()->set_enabled(lvl);
430
        }
431

432
        void init_parcel_log(runtime_configuration const& ini, bool isconsole,
64✔
433
            void (*set_console_dest)(logger_writer_type&, char const*,
434
                logging::level, logging_destination),
435
            void (*define_formatters)(logging::writer::named_write&))
64✔
436
        {
64✔
437
            auto settings = detail::get_log_settings(ini, "hpx.logging.parcel");
438

128✔
439
            auto lvl = hpx::util::logging::level::disable_all;
440
            if (!settings.level_.empty())
441
                lvl = detail::get_log_level(settings.level_, true);
64✔
442

443
            init_parcel_log(lvl, HPX_MOVE(settings.dest_),
444
                HPX_MOVE(settings.format_), isconsole, set_console_dest,
445
                define_formatters);
64✔
446
        }
447

448
        ///////////////////////////////////////////////////////////////////////
449
        // initialize logging for performance measurements
450
        void init_timing_log(logging::level lvl, std::string logdest,
451
            std::string logformat, bool isconsole,
64✔
452
            void (*set_console_dest)(logger_writer_type&, char const*,
453
                logging::level, logging_destination),
×
454
            void (*define_formatters)(logging::writer::named_write&))
455
        {
456
            if (hpx::util::logging::level::disable_all != lvl)
457
            {
458
                logger_writer_type& writer = timing_logger()->writer();
459

460
#if defined(ANDROID) || defined(__ANDROID__)
461
                if (logdest.empty())    // ensure minimal defaults
462
                    logdest = isconsole ? "android_log" : "console";
×
463

×
464
                writer.set_destination(
465
                    "android_log", android_log("hpx.timing"));
×
466
#else
467
                if (logdest.empty())    // ensure minimal defaults
468
                    logdest = isconsole ? "cerr" : "console";
×
469
#endif
470
                if (logformat.empty())
×
471
                    logformat = "|\\n";
×
472

473
                set_console_dest(writer, "console", lvl,
×
474
                    logging_destination::timing);    //-V106
475
                writer.write(logformat, logdest);
64✔
476
                define_formatters(writer);
64✔
477

478
                timing_logger()->mark_as_initialized();
64✔
479
            }
480
            timing_logger()->set_enabled(lvl);
481
        }
482

483
        void init_timing_log(runtime_configuration const& ini, bool isconsole,
64✔
484
            void (*set_console_dest)(logger_writer_type&, char const*,
485
                logging::level, logging_destination),
486
            void (*define_formatters)(logging::writer::named_write&))
64✔
487
        {
64✔
488
            auto settings = detail::get_log_settings(ini, "hpx.logging.timing");
489

128✔
490
            auto lvl = hpx::util::logging::level::disable_all;
491
            if (!settings.level_.empty())
492
                lvl = detail::get_log_level(settings.level_, true);
64✔
493

494
            init_timing_log(lvl, HPX_MOVE(settings.dest_),
495
                HPX_MOVE(settings.format_), isconsole, set_console_dest,
496
                define_formatters);
64✔
497
        }
498
#endif
499

500
        ///////////////////////////////////////////////////////////////////////
501
        void init_hpx_log(logging::level lvl, std::string logdest,
502
            std::string logformat, bool isconsole,
64✔
503
            void (*set_console_dest)(logger_writer_type&, char const*,
64✔
504
                logging::level, logging_destination),
505
            void (*define_formatters)(logging::writer::named_write&))
506
        {
507
            logger_writer_type& writer = hpx_logger()->writer();
508
            logger_writer_type& error_writer = hpx_error_logger()->writer();
509

510
#if defined(ANDROID) || defined(__ANDROID__)
511
            if (logdest.empty())    // ensure minimal defaults
512
                logdest = isconsole ? "android_log" : "console";
64✔
513

×
514
            writer.set_destination("android_log", android_log("hpx"));
515
            error_writer.set_destination("android_log", android_log("hpx"));
64✔
516
#else
517
            if (logdest.empty())    // ensure minimal defaults
518
                logdest = isconsole ? "cerr" : "console";
64✔
519
#endif
520
            if (logformat.empty())
64✔
521
                logformat = "|\\n";
522

64✔
523
            if (hpx::util::logging::level::disable_all != lvl)
64✔
524
            {
525
                set_console_dest(writer, "console", lvl,
64✔
526
                    logging_destination::hpx);    //-V106
64✔
527
                writer.write(logformat, logdest);
528
                define_formatters(writer);
529

64✔
530
                hpx_logger()->mark_as_initialized();
531
                hpx_logger()->set_enabled(lvl);
532

64✔
533
                // errors are logged to the given destination and to cerr
128✔
534
                set_console_dest(error_writer, "console", lvl,
535
                    logging_destination::hpx);    //-V106
64✔
536
#if !defined(ANDROID) && !defined(__ANDROID__)
537
                if (logdest != "cerr")
64✔
538
                    error_writer.write(logformat, logdest + " cerr");
64✔
539
#endif
540
                define_formatters(error_writer);
541

542
                hpx_error_logger()->mark_as_initialized();
543
                hpx_error_logger()->set_enabled(lvl);
×
544
            }
545
            else
×
546
            {
547
                // errors are always logged to cerr
×
548
                if (!isconsole)
549
                {
550
                    set_console_dest(writer, "console", lvl,
551
                        logging_destination::hpx);    //-V106
552
                    error_writer.write(logformat, "console");
553
                }
554
                else
×
555
                {
556
#if defined(ANDROID) || defined(__ANDROID__)
557
                    error_writer.write(logformat, "android_log");
×
558
#else
559
                    error_writer.write(logformat, "cerr");
×
560
#endif
×
561
                }
562
                define_formatters(error_writer);
563

64✔
564
                hpx_error_logger()->mark_as_initialized();
565
                hpx_error_logger()->set_enabled(
64✔
566
                    hpx::util::logging::level::fatal);
567
            }
568
        }
569

570
        void init_hpx_log(runtime_configuration const& ini, bool isconsole,
64✔
571
            void (*set_console_dest)(logger_writer_type&, char const*,
572
                logging::level, logging_destination),
573
            void (*define_formatters)(logging::writer::named_write&))
64✔
574
        {
64✔
575
            auto settings = detail::get_log_settings(ini, "hpx.logging");
576

128✔
577
            auto lvl = hpx::util::logging::level::disable_all;
578
            if (!settings.level_.empty())
579
                lvl = detail::get_log_level(settings.level_, true);
64✔
580

581
            init_hpx_log(lvl, HPX_MOVE(settings.dest_),
582
                HPX_MOVE(settings.format_), isconsole, set_console_dest,
583
                define_formatters);
64✔
584
        }
585

586
        ///////////////////////////////////////////////////////////////////////
587
        // initialize logging for application
588
        void init_app_log(logging::level lvl, std::string logdest,
589
            std::string logformat, bool isconsole,
64✔
590
            void (*set_console_dest)(logger_writer_type&, char const*,
591
                logging::level, logging_destination),
×
592
            void (*define_formatters)(logging::writer::named_write&))
593
        {
594
            if (hpx::util::logging::level::disable_all != lvl)
595
            {
596
                logger_writer_type& writer = app_logger()->writer();
597

598
#if defined(ANDROID) || defined(__ANDROID__)
599
                if (logdest.empty())    // ensure minimal defaults
×
600
                    logdest = isconsole ? "android_log" : "console";
×
601
                writer.set_destination(
602
                    "android_log", android_log("hpx.application"));
×
603
#else
604
                if (logdest.empty())    // ensure minimal defaults
605
                    logdest = isconsole ? "cerr" : "console";
×
606
#endif
607
                if (logformat.empty())
×
608
                    logformat = "|\\n";
×
609

610
                set_console_dest(writer, "console", lvl,
×
611
                    logging_destination::app);    //-V106
612
                writer.write(logformat, logdest);
64✔
613
                define_formatters(writer);
64✔
614

615
                app_logger()->mark_as_initialized();
64✔
616
            }
617
            app_logger()->set_enabled(lvl);
618
        }
619

620
        void init_app_log(runtime_configuration const& ini, bool isconsole,
621
            void (*set_console_dest)(logger_writer_type&, char const*,
64✔
622
                logging::level, logging_destination),
623
            void (*define_formatters)(logging::writer::named_write&))
624
        {
64✔
625
            auto settings =
64✔
626
                detail::get_log_settings(ini, "hpx.logging.application");
627

128✔
628
            auto lvl = hpx::util::logging::level::disable_all;
629
            if (!settings.level_.empty())
630
                lvl = detail::get_log_level(settings.level_, true);
64✔
631

632
            init_app_log(lvl, HPX_MOVE(settings.dest_),
633
                HPX_MOVE(settings.format_), isconsole, set_console_dest,
634
                define_formatters);
64✔
635
        }
636

637
        ///////////////////////////////////////////////////////////////////////
638
        // initialize logging for application
639
        void init_debuglog_log(logging::level lvl, std::string logdest,
640
            std::string logformat, bool isconsole,
64✔
641
            void (*set_console_dest)(logger_writer_type&, char const*,
642
                logging::level, logging_destination),
×
643
            void (*define_formatters)(logging::writer::named_write&))
644
        {
645
            if (hpx::util::logging::level::disable_all != lvl)
646
            {
647
                logger_writer_type& writer = debuglog_logger()->writer();
648

649
#if defined(ANDROID) || defined(__ANDROID__)
650
                if (logdest.empty())    // ensure minimal defaults
×
651
                    logdest = isconsole ? "android_log" : "console";
×
652
                writer.set_destination(
653
                    "android_log", android_log("hpx.debuglog"));
×
654
#else
655
                if (logdest.empty())    // ensure minimal defaults
656
                    logdest = isconsole ? "cerr" : "console";
×
657
#endif
658
                if (logformat.empty())
×
659
                    logformat = "|\\n";
×
660

661
                set_console_dest(writer, "console", lvl,
×
662
                    logging_destination::debuglog);    //-V106
663
                writer.write(logformat, logdest);
64✔
664
                define_formatters(writer);
64✔
665

666
                debuglog_logger()->mark_as_initialized();
64✔
667
            }
668
            debuglog_logger()->set_enabled(lvl);
669
        }
670

671
        void init_debuglog_log(runtime_configuration const& ini, bool isconsole,
672
            void (*set_console_dest)(logger_writer_type&, char const*,
64✔
673
                logging::level, logging_destination),
674
            void (*define_formatters)(logging::writer::named_write&))
675
        {
64✔
676
            auto settings =
64✔
677
                detail::get_log_settings(ini, "hpx.logging.debuglog");
678

128✔
679
            auto lvl = hpx::util::logging::level::disable_all;
680
            if (!settings.level_.empty())
681
                lvl = detail::get_log_level(settings.level_, true);
64✔
682

683
            init_debuglog_log(lvl, HPX_MOVE(settings.dest_),
684
                HPX_MOVE(settings.format_), isconsole, set_console_dest,
685
                define_formatters);
64✔
686
        }
687

688
#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS)
64✔
689
        ///////////////////////////////////////////////////////////////////////
690
        void init_agas_console_log(
×
691
            logging::level lvl, std::string logdest, std::string logformat)
692
        {
693
            if (hpx::util::logging::level::disable_all != lvl)
694
            {
695
                logger_writer_type& writer = agas_console_logger()->writer();
696

697
#if defined(ANDROID) || defined(__ANDROID__)
×
698
                if (logdest.empty())    // ensure minimal defaults
699
                    logdest = "android_log";
700
                writer.set_destination("android_log", android_log("hpx.agas"));
×
701
#else
702
                if (logdest.empty())    // ensure minimal defaults
703
                    logdest = "cerr";
×
704
#endif
705
                if (logformat.empty())
×
706
                    logformat = "|\\n";
707

64✔
708
                writer.write(logformat, logdest);
64✔
709

710
                agas_console_logger()->mark_as_initialized();
64✔
711
            }
712
            agas_console_logger()->set_enabled(lvl);
713
        }
64✔
714

715
        void init_agas_console_log(util::section const& ini)
716
        {
64✔
717
            auto settings =
64✔
718
                detail::get_log_settings(ini, "hpx.logging.console.agas");
719

128✔
720
            auto lvl = hpx::util::logging::level::disable_all;
721
            if (!settings.level_.empty())
64✔
722
                lvl = detail::get_log_level(settings.level_, true);
723

724
            init_agas_console_log(
64✔
725
                lvl, HPX_MOVE(settings.dest_), HPX_MOVE(settings.format_));
726
        }
727

64✔
728
        ///////////////////////////////////////////////////////////////////////
729
        void init_parcel_console_log(
×
730
            logging::level lvl, std::string logdest, std::string logformat)
731
        {
732
            if (hpx::util::logging::level::disable_all != lvl)
733
            {
734
                logger_writer_type& writer = parcel_console_logger()->writer();
735

736
#if defined(ANDROID) || defined(__ANDROID__)
737
                if (logdest.empty())    // ensure minimal defaults
×
738
                    logdest = "android_log";
739
                writer.set_destination(
740
                    "android_log", android_log("hpx.parcel"));
×
741
#else
742
                if (logdest.empty())    // ensure minimal defaults
743
                    logdest = "cerr";
×
744
#endif
745
                if (logformat.empty())
×
746
                    logformat = "|\\n";
747

64✔
748
                writer.write(logformat, logdest);
64✔
749

750
                parcel_console_logger()->mark_as_initialized();
64✔
751
            }
752
            parcel_console_logger()->set_enabled(lvl);
753
        }
64✔
754

755
        void init_parcel_console_log(util::section const& ini)
756
        {
64✔
757
            auto settings =
64✔
758
                detail::get_log_settings(ini, "hpx.logging.console.parcel");
759

128✔
760
            auto lvl = hpx::util::logging::level::disable_all;
761
            if (!settings.level_.empty())
64✔
762
                lvl = detail::get_log_level(settings.level_, true);
763

764
            init_parcel_console_log(
64✔
765
                lvl, HPX_MOVE(settings.dest_), HPX_MOVE(settings.format_));
766
        }
767

64✔
768
        ///////////////////////////////////////////////////////////////////////
769
        void init_timing_console_log(
×
770
            logging::level lvl, std::string logdest, std::string logformat)
771
        {
772
            if (hpx::util::logging::level::disable_all != lvl)
773
            {
774
                logger_writer_type& writer = timing_console_logger()->writer();
775

776
#if defined(ANDROID) || defined(__ANDROID__)
777
                if (logdest.empty())    // ensure minimal defaults
×
778
                    logdest = "android_log";
779
                writer.set_destination(
780
                    "android_log", android_log("hpx.timing"));
×
781
#else
782
                if (logdest.empty())    // ensure minimal defaults
783
                    logdest = "cerr";
×
784
#endif
785
                if (logformat.empty())
×
786
                    logformat = "|\\n";
787

64✔
788
                writer.write(logformat, logdest);
64✔
789

790
                timing_console_logger()->mark_as_initialized();
64✔
791
            }
792
            timing_console_logger()->set_enabled(lvl);
793
        }
64✔
794

795
        void init_timing_console_log(util::section const& ini)
796
        {
64✔
797
            auto settings =
64✔
798
                detail::get_log_settings(ini, "hpx.logging.console.timing");
799

128✔
800
            auto lvl = hpx::util::logging::level::disable_all;
801
            if (!settings.level_.empty())
64✔
802
                lvl = detail::get_log_level(settings.level_, true);
803

804
            init_timing_console_log(
805
                lvl, HPX_MOVE(settings.dest_), HPX_MOVE(settings.format_));
64✔
806
        }
807
#endif
808

64✔
809
        ///////////////////////////////////////////////////////////////////////
810
        void init_hpx_console_log(
64✔
811
            logging::level lvl, std::string logdest, std::string logformat)
812
        {
813
            if (hpx::util::logging::level::disable_all != lvl)
814
            {
815
                logger_writer_type& writer = hpx_console_logger()->writer();
816

817
#if defined(ANDROID) || defined(__ANDROID__)
64✔
818
                if (logdest.empty())    // ensure minimal defaults
819
                    logdest = "android_log";
820
                writer.set_destination("android_log", android_log("hpx"));
64✔
821
#else
822
                if (logdest.empty())    // ensure minimal defaults
823
                    logdest = "cerr";
64✔
824
#endif
825
                if (logformat.empty())
64✔
826
                    logformat = "|\\n";
827

64✔
828
                writer.write(logformat, logdest);
64✔
829

830
                hpx_console_logger()->mark_as_initialized();
64✔
831
            }
832
            hpx_console_logger()->set_enabled(lvl);
833
        }
64✔
834

835
        void init_hpx_console_log(util::section const& ini)
836
        {
64✔
837
            auto settings =
64✔
838
                detail::get_log_settings(ini, "hpx.logging.console");
839

128✔
840
            auto lvl = hpx::util::logging::level::disable_all;
841
            if (!settings.level_.empty())
64✔
842
                lvl = detail::get_log_level(settings.level_, true);
843

844
            init_hpx_console_log(
64✔
845
                lvl, HPX_MOVE(settings.dest_), HPX_MOVE(settings.format_));
846
        }
847

64✔
848
        ///////////////////////////////////////////////////////////////////////
849
        void init_app_console_log(
×
850
            logging::level lvl, std::string logdest, std::string logformat)
851
        {
852
            if (hpx::util::logging::level::disable_all != lvl)
853
            {
854
                logger_writer_type& writer = app_console_logger()->writer();
855

856
#if defined(ANDROID) || defined(__ANDROID__)
857
                if (logdest.empty())    // ensure minimal defaults
×
858
                    logdest = "android_log";
859
                writer.set_destination(
860
                    "android_log", android_log("hpx.application"));
×
861
#else
862
                if (logdest.empty())    // ensure minimal defaults
863
                    logdest = "cerr";
×
864
#endif
865
                if (logformat.empty())
×
866
                    logformat = "|\\n";
867

64✔
868
                writer.write(logformat, logdest);
64✔
869

870
                app_console_logger()->mark_as_initialized();
64✔
871
            }
872
            app_console_logger()->set_enabled(lvl);
873
        }
64✔
874

875
        void init_app_console_log(util::section const& ini)
876
        {
64✔
877
            auto settings = detail::get_log_settings(
64✔
878
                ini, "hpx.logging.console.application");
879

128✔
880
            auto lvl = hpx::util::logging::level::disable_all;
881
            if (!settings.level_.empty())
64✔
882
                lvl = detail::get_log_level(settings.level_, true);
883

884
            init_app_console_log(
64✔
885
                lvl, HPX_MOVE(settings.dest_), HPX_MOVE(settings.format_));
886
        }
887

64✔
888
        ///////////////////////////////////////////////////////////////////////
889
        void init_debuglog_console_log(
890
            logging::level lvl, std::string logdest, std::string logformat)
×
891
        {
892
            if (hpx::util::logging::level::disable_all != lvl)
893
            {
894
                logger_writer_type& writer =
895
                    debuglog_console_logger()->writer();
896

897
#if defined(ANDROID) || defined(__ANDROID__)
898
                if (logdest.empty())    // ensure minimal defaults
×
899
                    logdest = "android_log";
900
                writer.set_destination(
901
                    "android_log", android_log("hpx.debuglog"));
×
902
#else
903
                if (logdest.empty())    // ensure minimal defaults
904
                    logdest = "cerr";
×
905
#endif
906
                if (logformat.empty())
×
907
                    logformat = "|\\n";
908

64✔
909
                writer.write(logformat, logdest);
64✔
910

911
                debuglog_console_logger()->mark_as_initialized();
64✔
912
            }
913
            debuglog_console_logger()->set_enabled(lvl);
914
        }
64✔
915

916
        void init_debuglog_console_log(util::section const& ini)
917
        {
64✔
918
            auto settings =
64✔
919
                detail::get_log_settings(ini, "hpx.logging.console.debuglog");
920

128✔
921
            auto lvl = hpx::util::logging::level::disable_all;
922
            if (!settings.level_.empty())
64✔
923
                lvl = detail::get_log_level(settings.level_, true);
924

925
            init_debuglog_console_log(
926
                lvl, HPX_MOVE(settings.dest_), HPX_MOVE(settings.format_));
927
        }
928

929
        ///////////////////////////////////////////////////////////////////////
930
        namespace {
931

932
            void (*default_set_console_dest)(logger_writer_type&, char const*,
933
                logging::level, logging_destination) = get_console_local;
934

64✔
935
            void (*default_define_formatters)(
936
                logging::writer::named_write&) = define_formatters_local;
937

938
            bool default_isconsole = true;
939
        }    // namespace
64✔
940

64✔
941
        void init_logging(runtime_configuration& ini, bool isconsole,
64✔
942
            void (*set_console_dest)(logger_writer_type&, char const*,
943
                logging::level, logging_destination),
944
            void (*define_formatters)(logging::writer::named_write&))
945
        {
64✔
946
            default_isconsole = isconsole;
64✔
947
            default_set_console_dest = set_console_dest;
948
            default_define_formatters = define_formatters;
64✔
949

950
#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS)
951
            // initialize normal logs
64✔
952
            init_agas_log(ini, isconsole, set_console_dest, define_formatters);
64✔
953
            init_parcel_log(
64✔
954
                ini, isconsole, set_console_dest, define_formatters);
955
            init_timing_log(
956
                ini, isconsole, set_console_dest, define_formatters);
957
#endif
958
            init_hpx_log(ini, isconsole, set_console_dest, define_formatters);
64✔
959
            init_app_log(ini, isconsole, set_console_dest, define_formatters);
64✔
960
            init_debuglog_log(
64✔
961
                ini, isconsole, set_console_dest, define_formatters);
962

64✔
963
            // initialize console logs
64✔
964
#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS)
64✔
965
            init_agas_console_log(ini);
64✔
966
            init_parcel_console_log(ini);
967
            init_timing_console_log(ini);
32✔
968
#endif
969
            init_hpx_console_log(ini);
32✔
970
            init_app_console_log(ini);
971
            init_debuglog_console_log(ini);
32✔
972
        }
973

974
        void init_logging_local(runtime_configuration& ini)
975
        {
×
976
            init_logging(ini, true, util::detail::get_console_local,
977
                util::detail::define_formatters_local);
×
978
        }
979
    }    // namespace detail
980

×
981
    ///////////////////////////////////////////////////////////////////////////
×
982
    void disable_logging(logging_destination dest) noexcept
×
983
    {
984
        switch (dest)
985
        {
×
986
#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS)
×
987
        case logging_destination::timing:
×
988
            timing_logger()->set_enabled(logging::level::disable_all);
989
            timing_console_logger()->set_enabled(logging::level::disable_all);
990
            break;
×
991

×
992
        case logging_destination::agas:
×
993
            agas_logger()->set_enabled(logging::level::disable_all);
994
            agas_console_logger()->set_enabled(logging::level::disable_all);
995
            break;
996

997
        case logging_destination::parcel:
998
            parcel_logger()->set_enabled(logging::level::disable_all);
999
            parcel_console_logger()->set_enabled(logging::level::disable_all);
1000
            break;
1001
#else
×
1002
        case logging_destination::agas:
×
1003
        case logging_destination::timing:
×
1004
        case logging_destination::parcel:
1005
            [[fallthrough]];
1006
#endif
×
1007

×
1008
        case logging_destination::hpx:
×
1009
            hpx_logger()->set_enabled(logging::level::disable_all);
1010
            hpx_console_logger()->set_enabled(logging::level::disable_all);
1011
            break;
×
1012

×
1013
        case logging_destination::app:
×
1014
            app_logger()->set_enabled(logging::level::disable_all);
1015
            app_console_logger()->set_enabled(logging::level::disable_all);
1016
            break;
×
1017

1018
        case logging_destination::debuglog:
×
1019
            debuglog_logger()->set_enabled(logging::level::disable_all);
1020
            debuglog_console_logger()->set_enabled(logging::level::disable_all);
1021
            break;
1022
        }
×
1023
    }
1024

×
1025
    void enable_logging(logging_destination dest, std::string const& level,
1026
        std::string logdest, std::string logformat)
1027
    {
×
1028
        auto lvl = hpx::util::logging::level::enable_all;
1029
        if (!level.empty())
1030
        {
×
1031
            lvl = detail::get_log_level(level, true);
×
1032
        }
1033

1034
        switch (dest)
×
1035
        {
1036
#if defined(HPX_LOGGING_HAVE_SEPARATE_DESTINATIONS)
×
1037
        case logging_destination::timing:
1038
            detail::init_timing_log(lvl, logdest, logformat,
×
1039
                detail::default_isconsole, detail::default_set_console_dest,
×
1040
                detail::default_define_formatters);
1041
            detail::init_debuglog_console_log(
1042
                lvl, HPX_MOVE(logdest), HPX_MOVE(logformat));
×
1043
            break;
1044

×
1045
        case logging_destination::agas:
1046
            detail::init_agas_log(lvl, logdest, logformat,
×
1047
                detail::default_isconsole, detail::default_set_console_dest,
×
1048
                detail::default_define_formatters);
1049
            detail::init_agas_console_log(
1050
                lvl, HPX_MOVE(logdest), HPX_MOVE(logformat));
×
1051
            break;
1052

×
1053
        case logging_destination::parcel:
1054
            detail::init_parcel_log(lvl, logdest, logformat,
1055
                detail::default_isconsole, detail::default_set_console_dest,
1056
                detail::default_define_formatters);
1057
            detail::init_parcel_console_log(
1058
                lvl, HPX_MOVE(logdest), HPX_MOVE(logformat));
1059
            break;
1060
#else
×
1061
        case logging_destination::agas:
×
1062
        case logging_destination::timing:
1063
        case logging_destination::parcel:
1064
            [[fallthrough]];
×
1065
#endif
1066

×
1067
        case logging_destination::hpx:
1068
            detail::init_hpx_log(lvl, logdest, logformat,
×
1069
                detail::default_isconsole, detail::default_set_console_dest,
×
1070
                detail::default_define_formatters);
1071
            detail::init_hpx_console_log(
1072
                lvl, HPX_MOVE(logdest), HPX_MOVE(logformat));
×
1073
            break;
1074

×
1075
        case logging_destination::app:
1076
            detail::init_app_log(lvl, logdest, logformat,
×
1077
                detail::default_isconsole, detail::default_set_console_dest,
×
1078
                detail::default_define_formatters);
1079
            detail::init_app_console_log(
1080
                lvl, HPX_MOVE(logdest), HPX_MOVE(logformat));
×
1081
            break;
1082

×
1083
        case logging_destination::debuglog:
1084
            detail::init_debuglog_log(lvl, logdest, logformat,
×
1085
                detail::default_isconsole, detail::default_set_console_dest,
1086
                detail::default_define_formatters);
1087
            detail::init_debuglog_console_log(
1088
                lvl, HPX_MOVE(logdest), HPX_MOVE(logformat));
1089
            break;
1090
        }
1091
    }
1092
}    // namespace hpx::util
1093

1094
#else
1095

1096
#include <hpx/init_runtime_local/detail/init_logging.hpp>
1097
#include <hpx/modules/logging.hpp>
1098
#include <hpx/modules/util.hpp>
1099

1100
#include <iostream>
1101
#include <string>
1102

1103
namespace hpx::util {
1104

1105
    //////////////////////////////////////////////////////////////////////////
1106
    void enable_logging(logging_destination, std::string const&,
1107
        std::string const&, std::string const&)
1108
    {
1109
    }
1110

1111
    void disable_logging(logging_destination) noexcept {}
1112

1113
    //////////////////////////////////////////////////////////////////////////
1114
    namespace detail {
1115

1116
        void warn_if_logging_requested(runtime_configuration& ini)
1117
        {
1118
            using util::get_entry_as;
1119

1120
            // warn if logging is requested
1121
            if (get_entry_as<int>(ini, "hpx.logging.level", -1) > 0 ||
1122
                get_entry_as<int>(ini, "hpx.logging.timing.level", -1) > 0 ||
1123
                get_entry_as<int>(ini, "hpx.logging.agas.level", -1) > 0 ||
1124
                get_entry_as<int>(ini, "hpx.logging.debuglog.level", -1) > 0 ||
1125
                get_entry_as<int>(ini, "hpx.logging.application.level", -1) > 0)
1126
            {
1127
                std::cerr
1128
                    << "hpx::init_logging: warning: logging is requested even "
1129
                       "while it was disabled at compile time. If you "
1130
                       "need logging to be functional, please reconfigure and "
1131
                       "rebuild HPX with HPX_WITH_LOGGING set to ON."
1132
                    << std::endl;
1133
            }
1134
        }
1135
    }    // namespace detail
1136
}    // namespace hpx::util
1137

1138
#endif    // HPX_HAVE_LOGGING
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