1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Define _GNU_SOURCE to ensure that <errno.h> defines
6 // program_invocation_short_name which is used in GetProgramName(). Keep this at
7 // the top of the file since some system headers might include <errno.h> and the
8 // header could be skipped on subsequent includes.
9 #if !defined(_GNU_SOURCE)
10 #define _GNU_SOURCE
11 #endif
12
13 #include "base/logging.h"
14
15 #include <errno.h>
16
17 #include <iomanip>
18
19 #include "base/process/process_handle.h"
20 #include "base/strings/string_piece.h"
21 #include "base/threading/platform_thread.h"
22
23 namespace logging {
24
25 namespace {
GetProgramName()26 const char* GetProgramName() {
27 return program_invocation_short_name ? program_invocation_short_name : "";
28 }
29 } // namespace
30
31 // InitWithSyslogPrefix generates log header for Chrome OS in syslog compatible
32 // format. The timezone will always be UTC regardless of devices' timezone.
33 // `<rfc3339_timestamp> <tickcount> <log_level>`
34 // `<program_name>[<pid>:<thread_id>]: `
35 // `[<filename>(<line_number>)] <message>`
36 //
37 // e.g.
38 // 2020-06-27T23:55:25.094701Z 1234 VERBOSE1 chrome[3816:3877]:
39 // [drm_device_handle.cc(90)] Succeeded authenticating /dev/dri/card0 in 0 ms
40 // with 1 attempt(s)
InitWithSyslogPrefix(base::StringPiece filename,int line,uint64_t tick_count,const char * log_severity_name_c_str,const char * log_prefix,bool enable_process_id,bool enable_thread_id,bool enable_timestamp,bool enable_tickcount)41 void LogMessage::InitWithSyslogPrefix(base::StringPiece filename,
42 int line,
43 uint64_t tick_count,
44 const char* log_severity_name_c_str,
45 const char* log_prefix,
46 bool enable_process_id,
47 bool enable_thread_id,
48 bool enable_timestamp,
49 bool enable_tickcount) {
50 if (log_prefix)
51 stream_ << log_prefix << ':';
52 if (enable_timestamp) {
53 timeval tv{};
54 gettimeofday(&tv, nullptr);
55 time_t t = tv.tv_sec;
56 struct tm utc_time {};
57 gmtime_r(&t, &utc_time);
58 stream_ << std::setfill('0') // Set fill to 0
59 << std::setw(4) << 1900 + utc_time.tm_year << "-" // year
60 << std::setw(2) << 1 + utc_time.tm_mon << "-" // month
61 << std::setw(2) << utc_time.tm_mday // date
62 << 'T' << std::setw(2) << utc_time.tm_hour << ":" // hour
63 << std::setw(2) << utc_time.tm_min << ":" // minute
64 << std::setw(2) << utc_time.tm_sec << "." // second
65 << std::setw(6) << tv.tv_usec // millisecond
66 << "Z "; // timezone UTC
67 }
68 if (enable_tickcount)
69 stream_ << tick_count << ' ';
70 if (severity_ >= 0) {
71 stream_ << log_severity_name_c_str;
72 } else {
73 stream_ << "VERBOSE" << -severity_;
74 }
75 stream_ << ' ' << GetProgramName();
76 if (enable_process_id || enable_thread_id) {
77 stream_ << "[";
78 if (enable_process_id) {
79 stream_ << base::GetUniqueIdForProcess();
80 }
81 if (enable_thread_id) {
82 stream_ << ':' << base::PlatformThread::CurrentId();
83 }
84 stream_ << "]";
85 }
86 stream_ << ": ";
87 stream_ << "[" << filename << "(" << line << ")] ";
88 }
89
90 } // namespace logging
91