diff --git a/clang-tools-extra/clangd/index/remote/server/Server.cpp b/clang-tools-extra/clangd/index/remote/server/Server.cpp --- a/clang-tools-extra/clangd/index/remote/server/Server.cpp +++ b/clang-tools-extra/clangd/index/remote/server/Server.cpp @@ -37,7 +37,9 @@ #include #include #include +#include #include +#include #if ENABLE_GRPC_REFLECTION #include @@ -78,6 +80,12 @@ llvm::cl::init(false), }; +llvm::cl::opt LogPrefix{ + "log-prefix", + llvm::cl::desc("A string that'll be prepended to all log statements. " + "Useful when running multiple instances on same host."), +}; + llvm::cl::opt TraceFile( "trace-file", llvm::cl::desc("Path to the file where tracer logs will be stored")); @@ -427,27 +435,48 @@ ServerShutdownWatcher.join(); } -std::unique_ptr makeLogger(llvm::raw_ostream &OS) { - if (!LogPublic) - return std::make_unique(OS, LogLevel); - // Redacted mode: - // - messages outside the scope of a request: log fully - // - messages tagged [public]: log fully - // - errors: log the format string - // - others: drop - class RedactedLogger : public StreamLogger { +std::unique_ptr makeLogger(llvm::StringRef LogPrefix, + llvm::raw_ostream &OS) { + std::unique_ptr Base; + if (LogPublic) { + // Redacted mode: + // - messages outside the scope of a request: log fully + // - messages tagged [public]: log fully + // - errors: log the format string + // - others: drop + class RedactedLogger : public StreamLogger { + public: + using StreamLogger::StreamLogger; + void log(Level L, const char *Fmt, + const llvm::formatv_object_base &Message) override { + if (Context::current().get(CurrentRequest) == nullptr || + llvm::StringRef(Fmt).startswith("[public]")) + return StreamLogger::log(L, Fmt, Message); + if (L >= Error) + return StreamLogger::log(L, Fmt, + llvm::formatv("[redacted] {0}", Fmt)); + } + }; + Base = std::make_unique(OS, LogLevel); + } else { + Base = std::make_unique(OS, LogLevel); + } + + if (LogPrefix.empty()) + return Base; + class PrefixedLogger : public Logger { + std::string LogPrefix; + std::unique_ptr Base; + public: - using StreamLogger::StreamLogger; + PrefixedLogger(llvm::StringRef LogPrefix, std::unique_ptr Base) + : LogPrefix(LogPrefix.str()), Base(std::move(Base)) {} void log(Level L, const char *Fmt, const llvm::formatv_object_base &Message) override { - if (Context::current().get(CurrentRequest) == nullptr || - llvm::StringRef(Fmt).startswith("[public]")) - return StreamLogger::log(L, Fmt, Message); - if (L >= Error) - return StreamLogger::log(L, Fmt, llvm::formatv("[redacted] {0}", Fmt)); + Base->log(L, Fmt, llvm::formatv("[{0}] {1}", LogPrefix, Message)); } }; - return std::make_unique(OS, LogLevel); + return std::make_unique(LogPrefix, std::move(Base)); } } // namespace @@ -471,7 +500,7 @@ llvm::errs().SetBuffered(); // Don't flush stdout when logging for thread safety. llvm::errs().tie(nullptr); - auto Logger = makeLogger(llvm::errs()); + auto Logger = makeLogger(LogPrefix.getValue(), llvm::errs()); clang::clangd::LoggingSession LoggingSession(*Logger); llvm::Optional TracerStream; diff --git a/clang-tools-extra/clangd/test/remote-index/log-prefix.test b/clang-tools-extra/clangd/test/remote-index/log-prefix.test new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clangd/test/remote-index/log-prefix.test @@ -0,0 +1,18 @@ +# RUN: rm -rf %t +# RUN: clangd-indexer %S/Inputs/Source.cpp > %t.idx +# RUN: %python %S/pipeline_helper.py --input-file-name=%s --server-arg=--log=verbose --server-arg=-log-prefix=test-prefix --server-log=%t.log --project-root=%S --index-file=%t.idx > /dev/null +# RUN: FileCheck %s < %t.log +# REQUIRES: clangd-remote-index + +# CHECK: [test-prefix] Server listening on +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +--- +{"jsonrpc":"2.0","id":1,"method":"workspace/symbol","params":{"query":"gFoo"}} +# CHECK: [test-prefix] <<< FuzzyFindRequest +# CHECK: [test-prefix] >>> FuzzyFindReply +# CHECK: [test-prefix] [public] request v1/FuzzyFind +--- +{"jsonrpc":"2.0","id":4,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"} +