12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/ADT/iterator.h"
16 #include "llvm/Support/Chrono.h"
17 #include "llvm/Support/ManagedStatic.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/Signals.h"
20 #include "llvm/Support/Threading.h"
21 #include "llvm/Support/raw_ostream.h"
40 const Log::ChannelMap::value_type &entry,
41 llvm::function_ref<
void(llvm::StringRef, llvm::StringRef)> lambda) {
42 lambda(
"all",
"all available logging categories");
43 lambda(
"default",
"default set of logging categories");
44 for (
const auto &category : entry.second.m_channel.categories)
45 lambda(category.name, category.description);
49 const ChannelMap::value_type &entry) {
50 stream << llvm::formatv(
"Logging categories for '{0}':\n", entry.first());
52 [&stream](llvm::StringRef name, llvm::StringRef description) {
53 stream << llvm::formatv(
" {0} - {1}\n", name, description);
58 llvm::ArrayRef<const char *> categories) {
59 bool list_categories =
false;
61 for (
const char *category : categories) {
62 if (llvm::StringRef(
"all").equals_insensitive(category)) {
66 if (llvm::StringRef(
"default").equals_insensitive(category)) {
67 flags |= entry.second.m_channel.default_flags;
70 auto cat = llvm::find_if(entry.second.m_channel.categories,
72 return c.name.equals_insensitive(category);
74 if (cat != entry.second.m_channel.categories.end()) {
78 stream << llvm::formatv(
"error: unrecognized log category '{0}'\n",
80 list_categories =
true;
87 void Log::Enable(
const std::shared_ptr<llvm::raw_ostream> &stream_sp,
89 llvm::sys::ScopedWriter lock(
m_mutex);
93 m_options.store(options, std::memory_order_relaxed);
100 llvm::sys::ScopedWriter lock(
m_mutex);
102 MaskType mask =
m_mask.fetch_and(~flags, std::memory_order_relaxed);
103 if (!(mask & ~flags)) {
110 return m_options.load(std::memory_order_relaxed);
114 return m_mask.load(std::memory_order_relaxed);
123 va_start(args, format);
132 llvm::SmallString<64> FinalMessage;
133 llvm::raw_svector_ostream
Stream(FinalMessage);
136 llvm::SmallString<64> Content;
139 Stream << Content <<
"\n";
147 va_start(args, format);
153 llvm::SmallString<64> Content;
156 Printf(
"error: %s", Content.c_str());
165 va_start(args, format);
172 llvm::SmallString<64> Content;
174 va_start(args, format);
178 Printf(
"warning: %s", Content.c_str());
183 assert(iter.second ==
true);
195 const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
196 uint32_t log_options, llvm::StringRef channel,
197 llvm::ArrayRef<const char *> categories, llvm::raw_ostream &error_stream) {
200 error_stream << llvm::formatv(
"Invalid log channel '{0}'.\n", channel);
204 ? iter->second.m_channel.default_flags
205 :
GetFlags(error_stream, *iter, categories);
206 iter->second.Enable(log_stream_sp, log_options, flags);
211 llvm::ArrayRef<const char *> categories,
212 llvm::raw_ostream &error_stream) {
215 error_stream << llvm::formatv(
"Invalid log channel '{0}'.\n", channel);
220 :
GetFlags(error_stream, *iter, categories);
221 iter->second.Disable(flags);
226 llvm::raw_ostream &stream) {
229 stream << llvm::formatv(
"Invalid log channel '{0}'.\n", channel);
242 llvm::StringRef channel,
243 llvm::function_ref<
void(llvm::StringRef, llvm::StringRef)> lambda) {
252 std::vector<llvm::StringRef> result;
254 result.push_back(channel.first());
260 stream <<
"No logging channels are currently registered.\n";
273 llvm::StringRef
function) {
278 OS << ++g_sequence_id <<
" ";
282 auto now = std::chrono::duration<double>(
283 std::chrono::system_clock::now().time_since_epoch());
284 OS << llvm::formatv(
"{0:f9} ", now.count());
289 OS << llvm::formatv(
"[{0,0+4}/{1,0+4}] ", getpid(),
290 llvm::get_threadid());
294 llvm::SmallString<32> thread_name;
295 llvm::get_thread_name(thread_name);
297 llvm::SmallString<12> format_str;
298 llvm::raw_svector_ostream format_os(format_str);
299 format_os <<
"{0,-" << llvm::alignTo<16>(thread_name.size()) <<
"} ";
300 OS << llvm::formatv(format_str.c_str(), thread_name);
304 llvm::sys::PrintStackTrace(
OS);
307 (!file.empty() || !
function.empty())) {
308 file = llvm::sys::path::filename(file).take_front(40);
309 function =
function.take_front(40);
310 OS << llvm::formatv(
"{0,-60:60} ", (file +
":" +
function).str());
323 static std::recursive_mutex g_LogThreadedMutex;
324 std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
334 const llvm::formatv_object_base &payload) {
336 llvm::raw_string_ostream
message(message_string);