clang-tools  8.0.0
Logger.h
Go to the documentation of this file.
1 //===--- Logger.h - Logger interface for clangd ------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H
11 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H
12 
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Error.h"
16 #include "llvm/Support/FormatAdapters.h"
17 #include "llvm/Support/FormatVariadic.h"
18 #include <mutex>
19 
20 namespace clang {
21 namespace clangd {
22 
23 /// Interface to allow custom logging in clangd.
24 class Logger {
25 public:
26  virtual ~Logger() = default;
27 
28  enum Level { Debug, Verbose, Info, Error };
29  static char indicator(Level L) { return "DVIE"[L]; }
30 
31  /// Implementations of this method must be thread-safe.
32  virtual void log(Level, const llvm::formatv_object_base &Message) = 0;
33 };
34 
35 namespace detail {
36 const char *debugType(const char *Filename);
37 void log(Logger::Level, const llvm::formatv_object_base &);
38 
39 // We often want to consume llvm::Errors by value when passing them to log().
40 // We automatically wrap them in llvm::fmt_consume() as formatv requires.
41 template <typename T> T &&wrap(T &&V) { return std::forward<T>(V); }
42 inline decltype(fmt_consume(llvm::Error::success())) wrap(llvm::Error &&V) {
43  return fmt_consume(std::move(V));
44 }
45 template <typename... Ts>
46 void log(Logger::Level L, const char *Fmt, Ts &&... Vals) {
47  detail::log(L, llvm::formatv(Fmt, detail::wrap(std::forward<Ts>(Vals))...));
48 }
49 } // namespace detail
50 
51 // Clangd logging functions write to a global logger set by LoggingSession.
52 // If no logger is registered, writes to llvm::errs().
53 // All accept llvm::formatv()-style arguments, e.g. log("Text={0}", Text).
54 
55 // elog() is used for "loud" errors and warnings.
56 // This level is often visible to users.
57 template <typename... Ts> void elog(const char *Fmt, Ts &&... Vals) {
58  detail::log(Logger::Error, Fmt, std::forward<Ts>(Vals)...);
59 }
60 // log() is used for information important to understand a clangd session.
61 // e.g. the names of LSP messages sent are logged at this level.
62 // This level could be enabled in production builds to allow later inspection.
63 template <typename... Ts> void log(const char *Fmt, Ts &&... Vals) {
64  detail::log(Logger::Info, Fmt, std::forward<Ts>(Vals)...);
65 }
66 // vlog() is used for details often needed for debugging clangd sessions.
67 // This level would typically be enabled for clangd developers.
68 template <typename... Ts> void vlog(const char *Fmt, Ts &&... Vals) {
69  detail::log(Logger::Verbose, Fmt, std::forward<Ts>(Vals)...);
70 }
71 // dlog only logs if --debug was passed, or --debug_only=Basename.
72 // This level would be enabled in a targeted way when debugging.
73 #define dlog(...) \
74  DEBUG_WITH_TYPE(::clang::clangd::detail::debugType(__FILE__), \
75  ::clang::clangd::detail::log(Logger::Debug, __VA_ARGS__))
76 
77 /// Only one LoggingSession can be active at a time.
79 public:
80  LoggingSession(clangd::Logger &Instance);
81  ~LoggingSession();
82 
83  LoggingSession(LoggingSession &&) = delete;
84  LoggingSession &operator=(LoggingSession &&) = delete;
85 
86  LoggingSession(LoggingSession const &) = delete;
87  LoggingSession &operator=(LoggingSession const &) = delete;
88 };
89 
90 // Logs to an output stream, such as stderr.
91 class StreamLogger : public Logger {
92 public:
93  StreamLogger(llvm::raw_ostream &Logs, Logger::Level MinLevel)
94  : MinLevel(MinLevel), Logs(Logs) {}
95 
96  /// Write a line to the logging stream.
97  void log(Level, const llvm::formatv_object_base &Message) override;
98 
99 private:
100  Logger::Level MinLevel;
101  llvm::raw_ostream &Logs;
102 
103  std::mutex StreamMutex;
104 };
105 
106 } // namespace clangd
107 } // namespace clang
108 
109 #endif
Some operations such as code completion produce a set of candidates.
void log(Logger::Level, const llvm::formatv_object_base &)
Definition: Logger.cpp:31
static char indicator(Level L)
Definition: Logger.h:29
decltype(fmt_consume(llvm::Error::success())) wrap(llvm::Error &&V)
Definition: Logger.h:42
void vlog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:68
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:57
const char * debugType(const char *Filename)
Definition: Logger.cpp:42
virtual void log(Level, const llvm::formatv_object_base &Message)=0
Implementations of this method must be thread-safe.
std::string Filename
Filename as a string.
Interface to allow custom logging in clangd.
Definition: Logger.h:24
Only one LoggingSession can be active at a time.
Definition: Logger.h:78
virtual ~Logger()=default
T && wrap(T &&V)
Definition: Logger.h:41
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
StreamLogger(llvm::raw_ostream &Logs, Logger::Level MinLevel)
Definition: Logger.h:93