util/log.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-License-Identifier: BSD-3-Clause | ||
| 2 | #include "chrono_batch_render/util/log.h" | ||
| 3 | |||
| 4 | #include <atomic> | ||
| 5 | #include <cstdio> | ||
| 6 | #include <mutex> | ||
| 7 | |||
| 8 | #include "chrono_batch_render/util/environment.h" | ||
| 9 | #include "chrono_batch_render/util/error.h" | ||
| 10 | |||
| 11 | namespace chrono::batch_render { | ||
| 12 | namespace { | ||
| 13 | |||
| 14 | constexpr Choice<LogLevel> kLevels[] = {{"debug", LogLevel::Debug}, | ||
| 15 | {"info", LogLevel::Info}, | ||
| 16 | {"warning", LogLevel::Warning}, | ||
| 17 | {"error", LogLevel::Error}, | ||
| 18 | {"off", LogLevel::Off}}; | ||
| 19 | |||
| 20 | 16 | LogLevel ReadLevel() { | |
| 21 | 16 | try { | |
| 22 | 17 | return EnvironmentChoice("CHRONO_BATCH_RENDER_LOG", kLevels).value_or(LogLevel::Info); | |
| 23 | 1 | } catch (const Error& error) { | |
| 24 | 1 | std::fprintf(stderr, "chrono-batch-render: warning: %s\n", error.what()); | |
| 25 | 1 | return LogLevel::Info; | |
| 26 | 1 | } | |
| 27 | } | ||
| 28 | |||
| 29 | 151 | const char* Prefix(LogLevel level) { | |
| 30 | 151 | switch (level) { | |
| 31 | case LogLevel::Debug: | ||
| 32 | return "chrono-batch-render: debug: "; | ||
| 33 | 25 | case LogLevel::Warning: | |
| 34 | 25 | return "chrono-batch-render: warning: "; | |
| 35 | 3 | case LogLevel::Error: | |
| 36 | 3 | return "chrono-batch-render: error: "; | |
| 37 | 122 | default: | |
| 38 | 122 | return "chrono-batch-render: "; | |
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | struct LogState { | ||
| 43 | std::atomic<LogLevel> level{ReadLevel()}; | ||
| 44 | std::mutex mutex; | ||
| 45 | LogSink sink; | ||
| 46 | }; | ||
| 47 | |||
| 48 | 7924 | LogState& State() { | |
| 49 | 7924 | static LogState state; | |
| 50 | 7924 | return state; | |
| 51 | } | ||
| 52 | |||
| 53 | } | ||
| 54 | |||
| 55 | 7662 | LogLevel GetLogLevel() { | |
| 56 | 7662 | return State().level.load(std::memory_order_relaxed); | |
| 57 | } | ||
| 58 | |||
| 59 | 32 | void SetLogLevel(LogLevel level) { | |
| 60 | 32 | State().level.store(level, std::memory_order_relaxed); | |
| 61 | 32 | } | |
| 62 | |||
| 63 | 26 | void SetLogSink(LogSink sink) { | |
| 64 | 26 | LogState& state = State(); | |
| 65 | 26 | std::lock_guard lock(state.mutex); | |
| 66 | 26 | state.sink = std::move(sink); | |
| 67 | 26 | } | |
| 68 | |||
| 69 | 206 | void LogMessage(LogLevel level, std::string_view message) { | |
| 70 | 206 | if (level == LogLevel::Off || level < GetLogLevel()) { | |
| 71 | 55 | return; | |
| 72 | } | ||
| 73 | |||
| 74 | 204 | LogState& state = State(); | |
| 75 | 204 | std::lock_guard lock(state.mutex); | |
| 76 | 204 | if (state.sink) { | |
| 77 | 53 | state.sink(level, message); | |
| 78 | 53 | return; | |
| 79 | } | ||
| 80 | 302 | std::fprintf(stderr, "%s%.*s\n", Prefix(level), int(message.size()), message.data()); | |
| 81 | 204 | } | |
| 82 | |||
| 83 | } | ||
| 84 |