1 //===--- Logger.cpp - Logger interface for clangd -------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "support/Logger.h" 10 #include "support/Trace.h" 11 #include "llvm/Support/Chrono.h" 12 #include "llvm/Support/Error.h" 13 #include "llvm/Support/FormatVariadic.h" 14 #include "llvm/Support/raw_ostream.h" 15 #include <mutex> 16 17 namespace clang { 18 namespace clangd { 19 20 namespace { 21 Logger *L = nullptr; 22 } // namespace 23 24 LoggingSession::LoggingSession(clangd::Logger &Instance) { 25 assert(!L); 26 L = &Instance; 27 } 28 29 LoggingSession::~LoggingSession() { L = nullptr; } 30 31 void detail::logImpl(Logger::Level Level, const char *Fmt, 32 const llvm::formatv_object_base &Message) { 33 if (L) 34 L->log(Level, Fmt, Message); 35 else { 36 static std::mutex Mu; 37 std::lock_guard<std::mutex> Guard(Mu); 38 llvm::errs() << Message << "\n"; 39 } 40 } 41 42 const char *detail::debugType(const char *Filename) { 43 if (const char *Slash = strrchr(Filename, '/')) 44 return Slash + 1; 45 if (const char *Backslash = strrchr(Filename, '\\')) 46 return Backslash + 1; 47 return Filename; 48 } 49 50 void StreamLogger::log(Logger::Level Level, const char *Fmt, 51 const llvm::formatv_object_base &Message) { 52 if (Level < MinLevel) 53 return; 54 llvm::sys::TimePoint<> Timestamp = std::chrono::system_clock::now(); 55 trace::log(Message); 56 std::lock_guard<std::mutex> Guard(StreamMutex); 57 Logs << llvm::formatv("{0}[{1:%H:%M:%S.%L}] {2}\n", indicator(Level), 58 Timestamp, Message); 59 Logs.flush(); 60 } 61 62 namespace { 63 // Like llvm::StringError but with fewer options and no gratuitous copies. 64 class SimpleStringError : public llvm::ErrorInfo<SimpleStringError> { 65 std::error_code EC; 66 std::string Message; 67 68 public: 69 SimpleStringError(std::error_code EC, std::string &&Message) 70 : EC(EC), Message(std::move(Message)) {} 71 void log(llvm::raw_ostream &OS) const override { OS << Message; } 72 std::string message() const override { return Message; } 73 std::error_code convertToErrorCode() const override { return EC; } 74 static char ID; 75 }; 76 char SimpleStringError::ID; 77 78 } // namespace 79 80 llvm::Error detail::error(std::error_code EC, std::string &&Msg) { 81 return llvm::make_error<SimpleStringError>(EC, std::move(Msg)); 82 } 83 84 } // namespace clangd 85 } // namespace clang 86