1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/test/logging/win/log_file_printer.h"
15 #include "base/basictypes.h"
16 #include "base/compiler_specific.h"
17 #include "base/debug/trace_event.h"
18 #include "base/logging.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_piece.h"
21 #include "base/time/time.h"
22 #include "chrome/test/logging/win/log_file_reader.h"
26 // TODO(grt) This duplicates private behavior in base/logging.cc's
27 // LogMessage::Init. That behavior should be exposed and used here (possibly
28 // by moving this function to logging.cc, making it use log_severity_names, and
29 // publishing it in logging.h with BASE_EXPORT).
30 void WriteSeverityToStream(logging::LogSeverity severity, std::ostream* out) {
32 case logging::LOG_INFO:
35 case logging::LOG_WARNING:
38 case logging::LOG_ERROR:
41 case logging::LOG_FATAL:
46 *out << "VERBOSE" << -severity;
53 // TODO(grt) This duplicates private behavior in base/logging.cc's
54 // LogMessage::Init. That behavior should be exposed and used here (possibly
55 // by moving this function to logging.cc and publishing it in logging.h with
57 void WriteLocationToStream(const base::StringPiece& file,
60 base::StringPiece filename(file);
61 size_t last_slash_pos = filename.find_last_of("\\/");
62 if (last_slash_pos != base::StringPiece::npos)
63 filename.remove_prefix(last_slash_pos + 1);
65 *out << filename << '(' << line << ')';
68 // Returns a pretty string for the trace event types that appear in ETW logs.
69 const char* GetTraceTypeString(char event_type) {
71 case TRACE_EVENT_PHASE_BEGIN:
74 case TRACE_EVENT_PHASE_END:
77 case TRACE_EVENT_PHASE_INSTANT:
87 class EventPrinter : public logging_win::LogFileDelegate {
89 explicit EventPrinter(std::ostream* out);
90 virtual ~EventPrinter();
92 virtual void OnUnknownEvent(const EVENT_TRACE* event) OVERRIDE;
94 virtual void OnUnparsableEvent(const EVENT_TRACE* event) OVERRIDE;
96 virtual void OnFileHeader(const EVENT_TRACE* event,
97 const TRACE_LOGFILE_HEADER* header) OVERRIDE;
99 virtual void OnLogMessage(const EVENT_TRACE* event,
100 logging::LogSeverity severity,
101 const base::StringPiece& message) OVERRIDE;
103 virtual void OnLogMessageFull(const EVENT_TRACE* event,
104 logging::LogSeverity severity,
106 const intptr_t* backtrace,
108 const base::StringPiece& file,
109 const base::StringPiece& message) OVERRIDE;
111 virtual void OnTraceEvent(const EVENT_TRACE* event,
112 const base::StringPiece& name,
115 const base::StringPiece& extra,
117 const intptr_t* backtrace) OVERRIDE;
120 void PrintTimeStamp(LARGE_INTEGER time_stamp);
121 void PrintEventContext(const EVENT_TRACE* event,
122 const base::StringPiece& level,
123 const base::StringPiece& context);
124 void PrintBadEvent(const EVENT_TRACE* event, const base::StringPiece& error);
127 DISALLOW_COPY_AND_ASSIGN(EventPrinter);
130 EventPrinter::EventPrinter(std::ostream* out)
134 EventPrinter::~EventPrinter() {
137 void EventPrinter::PrintTimeStamp(LARGE_INTEGER time_stamp) {
138 FILETIME event_time = {};
139 base::Time::Exploded time_exploded = {};
140 event_time.dwLowDateTime = time_stamp.LowPart;
141 event_time.dwHighDateTime = time_stamp.HighPart;
142 base::Time::FromFileTime(event_time).LocalExplode(&time_exploded);
144 *out_ << std::setfill('0')
145 << std::setw(2) << time_exploded.month
146 << std::setw(2) << time_exploded.day_of_month
148 << std::setw(2) << time_exploded.hour
149 << std::setw(2) << time_exploded.minute
150 << std::setw(2) << time_exploded.second
152 << std::setw(3) << time_exploded.millisecond;
155 // Prints the context info at the start of each line: pid, tid, time, etc.
156 void EventPrinter::PrintEventContext(const EVENT_TRACE* event,
157 const base::StringPiece& level,
158 const base::StringPiece& context) {
159 *out_ << '[' << event->Header.ProcessId << ':'
160 << event->Header.ThreadId << ':';
161 PrintTimeStamp(event->Header.TimeStamp);
163 *out_ << ':' << level;
164 if (!context.empty())
165 *out_ << ':' << context;
169 // Prints a useful message for events that can't be otherwise printed.
170 void EventPrinter::PrintBadEvent(const EVENT_TRACE* event,
171 const base::StringPiece& error) {
173 StringFromGUID2(event->Header.Guid, &guid[0], arraysize(guid));
174 *out_ << error << " (class=" << guid << ", type="
175 << static_cast<int>(event->Header.Class.Type) << ")";
178 void EventPrinter::OnUnknownEvent(const EVENT_TRACE* event) {
179 base::StringPiece empty;
180 PrintEventContext(event, empty, empty);
181 PrintBadEvent(event, "unsupported event");
184 void EventPrinter::OnUnparsableEvent(const EVENT_TRACE* event) {
185 base::StringPiece empty;
186 PrintEventContext(event, empty, empty);
187 PrintBadEvent(event, "parse error");
190 void EventPrinter::OnFileHeader(const EVENT_TRACE* event,
191 const TRACE_LOGFILE_HEADER* header) {
192 base::StringPiece empty;
193 PrintEventContext(event, empty, empty);
195 *out_ << "Log captured from Windows "
196 << static_cast<int>(header->VersionDetail.MajorVersion) << '.'
197 << static_cast<int>(header->VersionDetail.MinorVersion) << '.'
198 << static_cast<int>(header->VersionDetail.SubVersion) << '.'
199 << static_cast<int>(header->VersionDetail.SubMinorVersion)
200 << ". " << header->EventsLost << " events lost, "
201 << header->BuffersLost << " buffers lost." << std::endl;
204 void EventPrinter::OnLogMessage(const EVENT_TRACE* event,
205 logging::LogSeverity severity,
206 const base::StringPiece& message) {
207 std::ostringstream level_stream;
208 WriteSeverityToStream(severity, &level_stream);
209 PrintEventContext(event, level_stream.str(), base::StringPiece());
210 *out_ << message << std::endl;
213 void EventPrinter::OnLogMessageFull(const EVENT_TRACE* event,
214 logging::LogSeverity severity,
216 const intptr_t* backtrace,
218 const base::StringPiece& file,
219 const base::StringPiece& message) {
220 std::ostringstream level_stream;
221 std::ostringstream location_stream;
222 WriteSeverityToStream(severity, &level_stream);
223 WriteLocationToStream(file, line, &location_stream);
224 PrintEventContext(event, level_stream.str(), location_stream.str());
225 *out_ << message << std::endl;
228 void EventPrinter::OnTraceEvent(const EVENT_TRACE* event,
229 const base::StringPiece& name,
232 const base::StringPiece& extra,
234 const intptr_t* backtrace) {
235 PrintEventContext(event, GetTraceTypeString(type), base::StringPiece());
236 *out_ << name << " (id=0x" << std::hex << id << std::dec << ") " << extra
242 void logging_win::PrintLogFile(const base::FilePath& log_file,
244 EventPrinter printer(out);
245 logging_win::ReadLogFile(log_file, &printer);