diff --git a/clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp b/clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp
--- a/clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp
+++ b/clang-tools-extra/clangd/benchmarks/IndexBenchmark.cpp
@@ -9,6 +9,7 @@
 #include "../index/Serialization.h"
 #include "../index/dex/Dex.h"
 #include "benchmark/benchmark.h"
+#include "support/Logger.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Path.h"
@@ -43,13 +44,11 @@
 
   // Panic if the provided file couldn't be parsed.
   if (!JSONArray) {
-    llvm::errs() << "Error when parsing JSON requests file: "
-                 << llvm::toString(JSONArray.takeError());
+    elog("Error when parsing JSON requests file: {0}", JSONArray.takeError());
     exit(1);
   }
   if (!JSONArray->getAsArray()) {
-    llvm::errs() << "Error: top-level value is not a JSON array: " << Log
-                 << '\n';
+    elog("Error: top-level value is not a JSON array: {0}", Log);
     exit(1);
   }
 
@@ -57,7 +56,7 @@
     FuzzyFindRequest Request;
     // Panic if the provided file couldn't be parsed.
     if (!fromJSON(Item, Request)) {
-      llvm::errs() << "Error when deserializing request: " << Item << '\n';
+      elog("Error when deserializing request: {0}", Item);
       exit(1);
     }
     Requests.push_back(Request);
@@ -99,9 +98,9 @@
 // FIXME(kbobyrev): Create a logger wrapper to suppress debugging info printer.
 int main(int argc, char *argv[]) {
   if (argc < 3) {
-    llvm::errs() << "Usage: " << argv[0]
-                 << " global-symbol-index.yaml requests.json "
-                    "BENCHMARK_OPTIONS...\n";
+    clang::clangd::elog("Usage: {0} global-symbol-index.yaml requests.json "
+                        "BENCHMARK_OPTIONS...",
+                        argv[0]);
     return -1;
   }
   IndexFilename = argv[1];
diff --git a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
--- a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
+++ b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
@@ -14,6 +14,7 @@
 #include "index/Serialization.h"
 #include "index/dex/Dex.h"
 #include "index/remote/Client.h"
+#include "support/Logger.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -181,15 +182,14 @@
 
   void run() override {
     if (ID.getNumOccurrences() == 0 && Name.getNumOccurrences() == 0) {
-      llvm::errs()
-          << "Missing required argument: please provide id or -name.\n";
+      elog("Missing required argument: please provide id or -name.");
       return;
     }
     std::vector<SymbolID> IDs;
     if (ID.getNumOccurrences()) {
       auto SID = SymbolID::fromStr(ID);
       if (!SID) {
-        llvm::errs() << llvm::toString(SID.takeError()) << "\n";
+        elog("{0}", SID.takeError());
         return;
       }
       IDs.push_back(*SID);
@@ -205,7 +205,7 @@
       llvm::outs() << toYAML(Sym);
     });
     if (!FoundSymbol)
-      llvm::errs() << "not found\n";
+      elog("not found");
   }
 };
 
@@ -228,25 +228,23 @@
 
   void run() override {
     if (ID.getNumOccurrences() == 0 && Name.getNumOccurrences() == 0) {
-      llvm::errs()
-          << "Missing required argument: please provide id or -name.\n";
+      elog("Missing required argument: please provide id or -name.");
       return;
     }
     std::vector<SymbolID> IDs;
     if (ID.getNumOccurrences()) {
       auto SID = SymbolID::fromStr(ID);
       if (!SID) {
-        llvm::errs() << llvm::toString(SID.takeError()) << "\n";
+        elog("{0}", SID.takeError());
         return;
       }
       IDs.push_back(*SID);
     } else {
       IDs = getSymbolIDsFromIndex(Name, Index);
       if (IDs.size() > 1) {
-        llvm::errs() << llvm::formatv(
-            "The name {0} is ambiguous, found {1} different "
-            "symbols. Please use id flag to disambiguate.\n",
-            Name, IDs.size());
+        elog("The name {0} is ambiguous, found {1} different symbols. Please "
+             "use id flag to disambiguate.",
+             Name, IDs.size());
         return;
       }
     }
@@ -256,7 +254,7 @@
     Index->refs(RefRequest, [&RegexFilter](const Ref &R) {
       auto U = URI::parse(R.Location.FileURI);
       if (!U) {
-        llvm::errs() << U.takeError();
+        elog("{0}", U.takeError());
         return;
       }
       if (RegexFilter.match(U->body()))
@@ -288,14 +286,14 @@
     // Read input file (as specified in global option)
     auto Buffer = llvm::MemoryBuffer::getFile(IndexLocation);
     if (!Buffer) {
-      llvm::errs() << llvm::formatv("Can't open {0}", IndexLocation) << "\n";
+      elog("Can't open {0}", IndexLocation);
       return;
     }
 
     // Auto-detects input format when parsing
     auto IndexIn = clang::clangd::readIndexFile(Buffer->get()->getBuffer());
     if (!IndexIn) {
-      llvm::errs() << llvm::toString(IndexIn.takeError()) << "\n";
+      elog("{0}", IndexIn.takeError());
       return;
     }
 
@@ -303,8 +301,7 @@
     std::error_code EC;
     llvm::raw_fd_ostream OutputStream(OutputFile, EC);
     if (EC) {
-      llvm::errs() << llvm::formatv("Can't open {0} for writing", OutputFile)
-                   << "\n";
+      elog("Can't open {0} for writing", OutputFile);
       return;
     }
 
@@ -358,7 +355,7 @@
       return Cmd.Implementation()->parseAndRun(FakeArgv, Cmd.Description,
                                                Index);
   }
-  llvm::errs() << "Unknown command. Try 'help'.\n";
+  elog("Unknown command. Try 'help'");
   return false;
 }
 
@@ -380,7 +377,7 @@
              [&]() { Index = openIndex(IndexLocation); });
 
   if (!Index) {
-    llvm::errs() << "Failed to open the index.\n";
+    elog("Failed to open the index.");
     return -1;
   }
 
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
@@ -173,7 +173,7 @@
   Builder.AddListeningPort(ServerAddress, grpc::InsecureServerCredentials());
   Builder.RegisterService(&Service);
   std::unique_ptr<grpc::Server> Server(Builder.BuildAndStart());
-  llvm::outs() << "Server listening on " << ServerAddress << '\n';
+  vlog("Server listening on {0}", ServerAddress);
 
   Server->Wait();
 }
diff --git a/clang-tools-extra/clangd/indexer/IndexerMain.cpp b/clang-tools-extra/clangd/indexer/IndexerMain.cpp
--- a/clang-tools-extra/clangd/indexer/IndexerMain.cpp
+++ b/clang-tools-extra/clangd/indexer/IndexerMain.cpp
@@ -16,6 +16,7 @@
 #include "index/Serialization.h"
 #include "index/Symbol.h"
 #include "index/SymbolCollector.h"
+#include "support/Logger.h"
 #include "clang/Tooling/ArgumentsAdjusters.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Execution.h"
@@ -112,7 +113,7 @@
       argc, argv, llvm::cl::GeneralCategory, Overview);
 
   if (!Executor) {
-    llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
+    clang::clangd::elog("{0}", llvm::toString(Executor.takeError()));
     return 1;
   }
 
@@ -122,7 +123,7 @@
       std::make_unique<clang::clangd::IndexActionFactory>(Data),
       clang::tooling::getStripPluginsAdjuster());
   if (Err) {
-    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+    clang::clangd::elog("{0}", llvm::toString(std::move(Err)));
   }
 
   // Emit collected data.
diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -564,14 +564,14 @@
   }
 
   if (!Sync && WorkerThreadsCount == 0) {
-    llvm::errs() << "A number of worker threads cannot be 0. Did you mean to "
-                    "specify -sync?";
+    elog("A number of worker threads cannot be 0. Did you mean to "
+         "specify -sync?");
     return 1;
   }
 
   if (Sync) {
     if (WorkerThreadsCount.getNumOccurrences())
-      llvm::errs() << "Ignoring -j because -sync is set.\n";
+      elog("Ignoring -j because -sync is set.");
     WorkerThreadsCount = 0;
   }
   if (FallbackStyle.getNumOccurrences())
@@ -585,8 +585,7 @@
                               llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
     if (EC) {
       InputMirrorStream.reset();
-      llvm::errs() << "Error while opening an input mirror file: "
-                   << EC.message();
+      elog("Error while opening an input mirror file: {0}", EC.message());
     } else {
       InputMirrorStream->SetUnbuffered();
     }
@@ -606,8 +605,7 @@
                          llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
     if (EC) {
       TracerStream.reset();
-      llvm::errs() << "Error while opening trace file " << TracerFile << ": "
-                   << EC.message();
+      elog("Error while opening trace file {0}: {1}", TracerFile, EC.message());
     } else {
       Tracer = (TracerFile == JSONTraceFile)
                    ? trace::createJSONTracer(*TracerStream, PrettyPrint)
@@ -623,7 +621,7 @@
   // it's somewhat likely they're confused about how to use clangd.
   // Show them the help overview, which explains.
   if (llvm::outs().is_displayed() && llvm::errs().is_displayed())
-    llvm::errs() << Overview << "\n";
+    elog(Overview);
   // Use buffered stream to stderr (we still flush each log message). Unbuffered
   // stream can cause significant (non-deterministic) latency for the logger.
   llvm::errs().SetBuffered();
@@ -657,16 +655,16 @@
       // continuing.
       llvm::SmallString<128> Path(CompileCommandsDir);
       if (std::error_code EC = llvm::sys::fs::make_absolute(Path)) {
-        llvm::errs() << "Error while converting the relative path specified by "
-                        "--compile-commands-dir to an absolute path: "
-                     << EC.message() << ". The argument will be ignored.\n";
+        elog("Error while converting the relative path specified by "
+             "--compile-commands-dir to an absolute path: {0}. The argument "
+             "will be ignored.",
+             EC.message());
       } else {
         CompileCommandsDirPath = std::string(Path.str());
       }
     } else {
-      llvm::errs()
-          << "Path specified by --compile-commands-dir does not exist. The "
-             "argument will be ignored.\n";
+      elog("Path specified by --compile-commands-dir does not exist. The "
+           "argument will be ignored.");
     }
   }
 
@@ -698,8 +696,8 @@
   }
 #if CLANGD_ENABLE_REMOTE
   if (RemoteIndexAddress.empty() != ProjectRoot.empty()) {
-    llvm::errs() << "remote-index-address and project-path have to be "
-                    "specified at the same time.";
+    elog("remote-index-address and project-path have to be specified at the "
+         "same time.");
     return 1;
   }
   if (!RemoteIndexAddress.empty()) {
@@ -750,7 +748,7 @@
       elog("Couldn't determine user config file, not loading");
     }
     std::vector<const config::Provider *> ProviderPointers;
-    for (const auto& P : ProviderStack)
+    for (const auto &P : ProviderStack)
       ProviderPointers.push_back(P.get());
     Config = config::Provider::combine(std::move(ProviderPointers));
     Opts.ConfigProvider = Config.get();
@@ -766,7 +764,7 @@
     log("Starting LSP over XPC service");
     TransportLayer = newXPCTransport();
 #else
-    llvm::errs() << "This clangd binary wasn't built with XPC support.\n";
+    elog("This clangd binary wasn't built with XPC support.");
     return (int)ErrorResultCode::CantRunAsXPCService;
 #endif
   } else {