15#include "llvm/ADT/StringRef.h"
16#include "llvm/Support/Errno.h"
17#include "llvm/Support/ErrorHandling.h"
18#include "llvm/Support/FileSystem.h"
19#include "llvm/Support/Format.h"
20#include "llvm/Support/Process.h"
21#include "llvm/Support/Threading.h"
36 return T.tv_sec * 1000 +
T.tv_usec / 1000;
38 auto Time = std::chrono::system_clock::now();
39 auto Millis = std::chrono::duration_cast<std::chrono::milliseconds>(
40 Time.time_since_epoch());
41 return Millis.count();
56 std::error_code EC = llvm::sys::fs::openFileForWrite(
57 Path, FD, llvm::sys::fs::CD_OpenAlways, llvm::sys::fs::OF_Append);
59 llvm::errs() <<
"warning: unable to open log file '" << Path
60 <<
"': " << EC.message() <<
"\n";
72 (void)FD, (
void)
Data, (void)Size;
73 llvm_unreachable(
"dependency scanning logging is unsupported on Windows");
75 ssize_t Written = llvm::sys::RetryAfterSignal(-1, write, FD,
Data, Size);
76 return Written >= 0 && (
static_cast<size_t>(Written) == Size);
81 : FormattingOS(Buffer), FD(FD), DroppedLines(DroppedLines) {
83 *FormattingOS << llvm::format(
"[%lld.%0.3lld]", Millis / 1000, Millis % 1000);
84 *FormattingOS <<
' ' << llvm::sys::Process::getProcessId() <<
' '
85 << llvm::get_threadid() <<
": ";
90 DroppedLines(
Other.DroppedLines) {
91 if (
Other.FormattingOS)
92 FormattingOS.emplace(Buffer);
95 Other.FormattingOS.reset();
97 Other.DroppedLines =
nullptr;
103 *FormattingOS <<
"\n";
105 DroppedLines->fetch_add(1, std::memory_order_relaxed);
108void AtomicLineLogger::initialize(StringRef LogFilePath) {
109 LogPath = LogFilePath.str();
113 FD.store(NewFD, std::memory_order_relaxed);
114 log() <<
"logging_start";
118 if (LogFilePath.empty())
120 initialize(LogFilePath);
121 PathSource = LogPathSource::Constructor;
125 std::lock_guard<std::mutex> Lock(EnableMtx);
126 switch (PathSource) {
127 case LogPathSource::None:
128 PathSource = LogPathSource::EnableMethod;
129 if (!RequestedLogPath.empty())
130 initialize(RequestedLogPath);
132 case LogPathSource::Constructor:
133 return RequestedLogPath.empty() || RequestedLogPath == LogPath;
134 case LogPathSource::EnableMethod:
135 return RequestedLogPath == LogPath;
138 llvm_unreachable(
"unhandled LogPathSource");
142 int CurFD = FD.load(std::memory_order_relaxed);
144 return LogLine(CurFD, &DroppedLines);
149 int CurFD = FD.load(std::memory_order_relaxed);
152 log() <<
"logging_end";
153 if (uint64_t Dropped = DroppedLines.load(std::memory_order_relaxed))
154 llvm::errs() <<
"warning: log '" << LogPath
155 <<
"' is incomplete: " << Dropped
156 <<
" line(s) dropped due to write errors\n";
157 llvm::sys::Process::SafelyCloseFileDescriptor(FD);
static int openLogFile(StringRef Path)
static bool writeLineToFD(int FD, const char *Data, size_t Size)
static uint64_t getTimestampMillis()
Defines a logger where each line is written atomically to the file.
bool enable(StringRef RequestedLogPath)
Enables the logger if it is not already enabled.
Top level wrappers for InstallAPI frontend operations.
const FunctionProtoType * T
@ Other
Other implicit parameter.