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_ERROR_REPORT
:
42 *out
<< "ERROR_REPORT";
44 case logging::LOG_FATAL
:
49 *out
<< "VERBOSE" << -severity
;
56 // TODO(grt) This duplicates private behavior in base/logging.cc's
57 // LogMessage::Init. That behavior should be exposed and used here (possibly
58 // by moving this function to logging.cc and publishing it in logging.h with
60 void WriteLocationToStream(const base::StringPiece
& file
,
63 base::StringPiece
filename(file
);
64 size_t last_slash_pos
= filename
.find_last_of("\\/");
65 if (last_slash_pos
!= base::StringPiece::npos
)
66 filename
.remove_prefix(last_slash_pos
+ 1);
68 *out
<< filename
<< '(' << line
<< ')';
71 // Returns a pretty string for the trace event types that appear in ETW logs.
72 const char* GetTraceTypeString(char event_type
) {
74 case TRACE_EVENT_PHASE_BEGIN
:
77 case TRACE_EVENT_PHASE_END
:
80 case TRACE_EVENT_PHASE_INSTANT
:
90 class EventPrinter
: public logging_win::LogFileDelegate
{
92 explicit EventPrinter(std::ostream
* out
);
93 virtual ~EventPrinter();
95 virtual void OnUnknownEvent(const EVENT_TRACE
* event
) OVERRIDE
;
97 virtual void OnUnparsableEvent(const EVENT_TRACE
* event
) OVERRIDE
;
99 virtual void OnFileHeader(const EVENT_TRACE
* event
,
100 const TRACE_LOGFILE_HEADER
* header
) OVERRIDE
;
102 virtual void OnLogMessage(const EVENT_TRACE
* event
,
103 logging::LogSeverity severity
,
104 const base::StringPiece
& message
) OVERRIDE
;
106 virtual void OnLogMessageFull(const EVENT_TRACE
* event
,
107 logging::LogSeverity severity
,
109 const intptr_t* backtrace
,
111 const base::StringPiece
& file
,
112 const base::StringPiece
& message
) OVERRIDE
;
114 virtual void OnTraceEvent(const EVENT_TRACE
* event
,
115 const base::StringPiece
& name
,
118 const base::StringPiece
& extra
,
120 const intptr_t* backtrace
) OVERRIDE
;
123 void PrintTimeStamp(LARGE_INTEGER time_stamp
);
124 void PrintEventContext(const EVENT_TRACE
* event
,
125 const base::StringPiece
& level
,
126 const base::StringPiece
& context
);
127 void PrintBadEvent(const EVENT_TRACE
* event
, const base::StringPiece
& error
);
130 DISALLOW_COPY_AND_ASSIGN(EventPrinter
);
133 EventPrinter::EventPrinter(std::ostream
* out
)
137 EventPrinter::~EventPrinter() {
140 void EventPrinter::PrintTimeStamp(LARGE_INTEGER time_stamp
) {
141 FILETIME event_time
= {};
142 base::Time::Exploded time_exploded
= {};
143 event_time
.dwLowDateTime
= time_stamp
.LowPart
;
144 event_time
.dwHighDateTime
= time_stamp
.HighPart
;
145 base::Time::FromFileTime(event_time
).LocalExplode(&time_exploded
);
147 *out_
<< std::setfill('0')
148 << std::setw(2) << time_exploded
.month
149 << std::setw(2) << time_exploded
.day_of_month
151 << std::setw(2) << time_exploded
.hour
152 << std::setw(2) << time_exploded
.minute
153 << std::setw(2) << time_exploded
.second
155 << std::setw(3) << time_exploded
.millisecond
;
158 // Prints the context info at the start of each line: pid, tid, time, etc.
159 void EventPrinter::PrintEventContext(const EVENT_TRACE
* event
,
160 const base::StringPiece
& level
,
161 const base::StringPiece
& context
) {
162 *out_
<< '[' << event
->Header
.ProcessId
<< ':'
163 << event
->Header
.ThreadId
<< ':';
164 PrintTimeStamp(event
->Header
.TimeStamp
);
166 *out_
<< ':' << level
;
167 if (!context
.empty())
168 *out_
<< ':' << context
;
172 // Prints a useful message for events that can't be otherwise printed.
173 void EventPrinter::PrintBadEvent(const EVENT_TRACE
* event
,
174 const base::StringPiece
& error
) {
176 StringFromGUID2(event
->Header
.Guid
, &guid
[0], arraysize(guid
));
177 *out_
<< error
<< " (class=" << guid
<< ", type="
178 << static_cast<int>(event
->Header
.Class
.Type
) << ")";
181 void EventPrinter::OnUnknownEvent(const EVENT_TRACE
* event
) {
182 base::StringPiece empty
;
183 PrintEventContext(event
, empty
, empty
);
184 PrintBadEvent(event
, "unsupported event");
187 void EventPrinter::OnUnparsableEvent(const EVENT_TRACE
* event
) {
188 base::StringPiece empty
;
189 PrintEventContext(event
, empty
, empty
);
190 PrintBadEvent(event
, "parse error");
193 void EventPrinter::OnFileHeader(const EVENT_TRACE
* event
,
194 const TRACE_LOGFILE_HEADER
* header
) {
195 base::StringPiece empty
;
196 PrintEventContext(event
, empty
, empty
);
198 *out_
<< "Log captured from Windows "
199 << static_cast<int>(header
->VersionDetail
.MajorVersion
) << '.'
200 << static_cast<int>(header
->VersionDetail
.MinorVersion
) << '.'
201 << static_cast<int>(header
->VersionDetail
.SubVersion
) << '.'
202 << static_cast<int>(header
->VersionDetail
.SubMinorVersion
)
203 << ". " << header
->EventsLost
<< " events lost, "
204 << header
->BuffersLost
<< " buffers lost." << std::endl
;
207 void EventPrinter::OnLogMessage(const EVENT_TRACE
* event
,
208 logging::LogSeverity severity
,
209 const base::StringPiece
& message
) {
210 std::ostringstream level_stream
;
211 WriteSeverityToStream(severity
, &level_stream
);
212 PrintEventContext(event
, level_stream
.str(), base::StringPiece());
213 *out_
<< message
<< std::endl
;
216 void EventPrinter::OnLogMessageFull(const EVENT_TRACE
* event
,
217 logging::LogSeverity severity
,
219 const intptr_t* backtrace
,
221 const base::StringPiece
& file
,
222 const base::StringPiece
& message
) {
223 std::ostringstream level_stream
;
224 std::ostringstream location_stream
;
225 WriteSeverityToStream(severity
, &level_stream
);
226 WriteLocationToStream(file
, line
, &location_stream
);
227 PrintEventContext(event
, level_stream
.str(), location_stream
.str());
228 *out_
<< message
<< std::endl
;
231 void EventPrinter::OnTraceEvent(const EVENT_TRACE
* event
,
232 const base::StringPiece
& name
,
235 const base::StringPiece
& extra
,
237 const intptr_t* backtrace
) {
238 PrintEventContext(event
, GetTraceTypeString(type
), base::StringPiece());
239 *out_
<< name
<< " (id=0x" << std::hex
<< id
<< std::dec
<< ") " << extra
245 void logging_win::PrintLogFile(const base::FilePath
& log_file
,
247 EventPrinter
printer(out
);
248 logging_win::ReadLogFile(log_file
, &printer
);