|
1 | | -// Copyright 2023 David Allison |
| 1 | +// Copyright 2023,2025 David Allison |
2 | 2 | // All Rights Reserved |
3 | 3 | // See LICENSE file for licensing information. |
4 | 4 |
|
@@ -132,11 +132,26 @@ void Logger::Log(LogLevel level, const char *fmt, ...) { |
132 | 132 | va_end(ap); |
133 | 133 | } |
134 | 134 |
|
| 135 | +absl::Status Logger::SetTeeFile(const std::string &filename, bool truncate) { |
| 136 | + if (tee_stream_ != nullptr) { |
| 137 | + fclose(tee_stream_); |
| 138 | + } |
| 139 | + tee_stream_ = fopen(filename.c_str(), truncate ? "w" : "a"); |
| 140 | + if (tee_stream_ == nullptr) { |
| 141 | + return absl::InternalError(absl::StrFormat("Failed to open tee file %s: %s", |
| 142 | + filename, strerror(errno))); |
| 143 | + } |
| 144 | + return absl::OkStatus(); |
| 145 | +} |
| 146 | + |
135 | 147 | void Logger::VLog(LogLevel level, const char *fmt, va_list ap) { |
136 | 148 | if (level < min_level_) { |
137 | 149 | return; |
138 | 150 | } |
| 151 | +#pragma clang diagnostic push |
| 152 | +#pragma clang diagnostic ignored "-Wformat-nonliteral" |
139 | 153 | size_t n = vsnprintf(buffer_, sizeof(buffer_), fmt, ap); |
| 154 | +#pragma clang diagnostic pop |
140 | 155 |
|
141 | 156 | // Strip final \n if present. Refactoring from printf can leave |
142 | 157 | // this in place. |
@@ -196,6 +211,11 @@ void Logger::Log(LogLevel level, uint64_t timestamp, const std::string &source, |
196 | 211 | break; |
197 | 212 | } |
198 | 213 |
|
| 214 | + if (tee_stream_ != nullptr) { |
| 215 | + fprintf(tee_stream_, "%s %s: %s: %s: %s\n", timebuf, subsystem_.c_str(), |
| 216 | + LogLevelAsString(level), source.c_str(), text.c_str()); |
| 217 | + fflush(tee_stream_); |
| 218 | + } |
199 | 219 | if (level == LogLevel::kFatal) { |
200 | 220 | abort(); |
201 | 221 | } |
@@ -311,7 +331,9 @@ void Logger::LogColumnar(const char *timebuf, LogLevel level, |
311 | 331 | // clang-format off. |
312 | 332 | fprintf(output_stream_, "%-*s%s%-*s%s\n", prefix_length, |
313 | 333 | first_line ? prefix.c_str() : "", |
314 | | - color::SetColor(ColorForLogLevel(level)).c_str(), int(column_widths_[4]), segment.c_str(), color::ResetColor().c_str()); |
| 334 | + color::SetColor(ColorForLogLevel(level)).c_str(), |
| 335 | + int(column_widths_[4]), segment.c_str(), |
| 336 | + color::ResetColor().c_str()); |
315 | 337 | // clang-format on |
316 | 338 | start += segment.size(); |
317 | 339 | if (start >= text.size()) { |
|
0 commit comments