|
15 | 15 | #include "google/cloud/log.h" |
16 | 16 | #include "google/cloud/internal/getenv.h" |
17 | 17 | #include <array> |
| 18 | +#include <cstdint> |
| 19 | +#include <ctime> |
| 20 | +#include <iomanip> |
18 | 21 |
|
19 | 22 | namespace google { |
20 | 23 | namespace cloud { |
21 | 24 | inline namespace GOOGLE_CLOUD_CPP_NS { |
| 25 | + |
22 | 26 | static_assert(sizeof(Severity) <= sizeof(int), |
23 | 27 | "Expected Severity to fit in an integer"); |
24 | 28 |
|
25 | 29 | static_assert(static_cast<int>(Severity::GCP_LS_LOWEST) < |
26 | 30 | static_cast<int>(Severity::GCP_LS_HIGHEST), |
27 | 31 | "Expect LOWEST severity to be smaller than HIGHEST severity"); |
28 | 32 |
|
| 33 | +namespace { |
| 34 | +struct Timestamp { |
| 35 | + explicit Timestamp(std::chrono::system_clock::time_point const& tp) { |
| 36 | + auto const tt = std::chrono::system_clock::to_time_t(tp); |
| 37 | +#if defined(_WIN32) |
| 38 | + gmtime_s(&tm, &tt); |
| 39 | +#else |
| 40 | + gmtime_r(&tt, &tm); |
| 41 | +#endif |
| 42 | + auto const ss = tp - std::chrono::system_clock::from_time_t(tt); |
| 43 | + nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(ss).count(); |
| 44 | + } |
| 45 | + std::tm tm; |
| 46 | + std::int32_t nanos; |
| 47 | +}; |
| 48 | + |
| 49 | +std::ostream& operator<<(std::ostream& os, Timestamp const& ts) { |
| 50 | + auto const prev = os.fill(' '); |
| 51 | + auto constexpr kTmYearOffset = 1900; |
| 52 | + os << std::setw(4) << ts.tm.tm_year + kTmYearOffset; |
| 53 | + os.fill('0'); |
| 54 | + os << '-' << std::setw(2) << ts.tm.tm_mon + 1; |
| 55 | + os << '-' << std::setw(2) << ts.tm.tm_mday; |
| 56 | + os << 'T' << std::setw(2) << ts.tm.tm_hour; |
| 57 | + os << ':' << std::setw(2) << ts.tm.tm_min; |
| 58 | + os << ':' << std::setw(2) << ts.tm.tm_sec; |
| 59 | + // NOLINTNEXTLINE(readability-magic-numbers) |
| 60 | + os << '.' << std::setw(9) << ts.nanos << 'Z'; |
| 61 | + os.fill(prev); |
| 62 | + return os; |
| 63 | +} |
| 64 | + |
| 65 | +auto constexpr kSeverityCount = static_cast<int>(Severity::GCP_LS_HIGHEST) + 1; |
| 66 | + |
| 67 | +// Double braces needed to workaround a clang-3.8 bug. |
| 68 | +std::array<char const*, kSeverityCount> constexpr kSeverityNames{{ |
| 69 | + "TRACE", |
| 70 | + "DEBUG", |
| 71 | + "INFO", |
| 72 | + "NOTICE", |
| 73 | + "WARNING", |
| 74 | + "ERROR", |
| 75 | + "CRITICAL", |
| 76 | + "ALERT", |
| 77 | + "FATAL", |
| 78 | +}}; |
| 79 | +} // namespace |
| 80 | + |
29 | 81 | std::ostream& operator<<(std::ostream& os, Severity x) { |
30 | | - auto constexpr kSeverityCount = |
31 | | - static_cast<int>(Severity::GCP_LS_HIGHEST) + 1; |
32 | | - // Double braces needed to workaround a clang-3.8 bug. |
33 | | - std::array<char const*, kSeverityCount> names{{ |
34 | | - "TRACE", |
35 | | - "DEBUG", |
36 | | - "INFO", |
37 | | - "NOTICE", |
38 | | - "WARNING", |
39 | | - "ERROR", |
40 | | - "CRITICAL", |
41 | | - "ALERT", |
42 | | - "FATAL", |
43 | | - }}; |
44 | 82 | auto index = static_cast<int>(x); |
45 | | - return os << names[index]; |
| 83 | + return os << kSeverityNames[index]; |
46 | 84 | } |
47 | 85 |
|
48 | 86 | std::ostream& operator<<(std::ostream& os, LogRecord const& rhs) { |
49 | | - return os << '[' << rhs.severity << "] " << rhs.message << " (" |
50 | | - << rhs.filename << ':' << rhs.lineno << ')'; |
| 87 | + return os << Timestamp{rhs.timestamp} << " [" << rhs.severity << "] " |
| 88 | + << rhs.message << " (" << rhs.filename << ':' << rhs.lineno << ')'; |
51 | 89 | } |
52 | 90 |
|
53 | 91 | LogSink::LogSink() |
|
0 commit comments