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/logging.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_piece.h"
20 #include "base/time/time.h"
21 #include "base/trace_event/trace_event.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 ~EventPrinter() override
;
92 void OnUnknownEvent(const EVENT_TRACE
* event
) override
;
94 void OnUnparsableEvent(const EVENT_TRACE
* event
) override
;
96 void OnFileHeader(const EVENT_TRACE
* event
,
97 const TRACE_LOGFILE_HEADER
* header
) override
;
99 void OnLogMessage(const EVENT_TRACE
* event
,
100 logging::LogSeverity severity
,
101 const base::StringPiece
& message
) override
;
103 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 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
);