| 98 | } |
| 99 | |
| 100 | message::~message() try { |
| 101 | if (!buffer_.is_active()) { |
| 102 | return; |
| 103 | } |
| 104 | |
| 105 | auto* its_logger = logger_impl::get(); |
| 106 | if (!its_logger) { |
| 107 | // Trying to log at static deinit time, after logger has already been destroyed. |
| 108 | // As this should never happen, log to std::cerr so it becomes visible if it does. |
| 109 | // We do not expect any threads running at this time, so do not bother to avoid |
| 110 | // interleaving. |
| 111 | std::cerr << timestamp() << app_name() << " [VSIP] Trying to log after program termination: " << buffer_as_view() << std::endl; |
| 112 | return; |
| 113 | } |
| 114 | |
| 115 | if (console_enabled_) { |
| 116 | #ifndef ANDROID |
| 117 | // std::cout is threadsafe, but output may be interleaved if multiple things are |
| 118 | // streamed. To avoid a lock, build the full logline first and stream as a |
| 119 | // single argument. In C++20, could use std::osyncstream and/or std::format to simplify |
| 120 | // this. |
| 121 | // Unfortunately, building the string is a bit awkward - freely concatenating |
| 122 | // string_views and strings is a C++26 feature. |
| 123 | const std::string_view ts = timestamp(); |
| 124 | const std::string_view app = app_name(); |
| 125 | const std::string_view lvl = level_as_view(); |
| 126 | const std::string_view msg = buffer_as_view(); |
| 127 | std::string output; |
| 128 | output.reserve(ts.size() + app.size() + lvl.size() + msg.size() + 1); |
| 129 | output += ts; |
| 130 | output += app; |
| 131 | output += lvl; |
| 132 | output += msg; |
| 133 | output += '\n'; |
| 134 | std::cout << output; |
| 135 | std::cout.flush(); |
| 136 | |
| 137 | #else |
| 138 | static std::string app = runtime::get_property("LogApplication"); |
| 139 | |
| 140 | // Note: Adding this prefix is not really optimal in terms of memory allocation/copying. |
| 141 | // Could we set the prefix as separate arg instead? This would change the current |
| 142 | // message structure through, so leave it for now. |
| 143 | const static std::string prefix = "VSIP: "; |
| 144 | const std::string_view view = buffer_as_view(); |
| 145 | std::string output; |
| 146 | output.reserve(prefix.size() + view.size()); |
| 147 | output += prefix; |
| 148 | output += view; |
| 149 | |
| 150 | switch (level_) { |
| 151 | case level_e::LL_FATAL: |
| 152 | ALOGE(app.c_str(), output.c_str()); |
| 153 | break; |
| 154 | case level_e::LL_ERROR: |
| 155 | ALOGE(app.c_str(), output.c_str()); |
| 156 | break; |
| 157 | case level_e::LL_WARNING: |
nothing calls this directly
no test coverage detected