1 // Copyright (c) 2006-2008 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.
4
5 #include "base/trace_event.h"
6
7 #include "base/format_macros.h"
8 #include "base/file_path.h"
9 #include "base/file_util.h"
10 #include "base/path_service.h"
11 #include "base/platform_thread.h"
12 #include "base/process_util.h"
13 #include "base/string_util.h"
14 #include "base/utf_string_conversions.h"
15 #include "base/time.h"
16
17 #define USE_UNRELIABLE_NOW
18
19 namespace base {
20
21 static const char* kEventTypeNames[] = {
22 "BEGIN",
23 "END",
24 "INSTANT"
25 };
26
27 static const FilePath::CharType* kLogFileName =
28 FILE_PATH_LITERAL("trace_%d.log");
29
TraceLog()30 TraceLog::TraceLog() : enabled_(false), log_file_(NULL) {
31 base::ProcessHandle proc = base::GetCurrentProcessHandle();
32 #if !defined(OS_MACOSX)
33 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc));
34 #else
35 // The default port provider is sufficient to get data for the current
36 // process.
37 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc,
38 NULL));
39 #endif
40 }
41
~TraceLog()42 TraceLog::~TraceLog() {
43 Stop();
44 }
45
46 // static
IsTracing()47 bool TraceLog::IsTracing() {
48 TraceLog* trace = Singleton<TraceLog>::get();
49 return trace->enabled_;
50 }
51
52 // static
StartTracing()53 bool TraceLog::StartTracing() {
54 TraceLog* trace = Singleton<TraceLog>::get();
55 return trace->Start();
56 }
57
Start()58 bool TraceLog::Start() {
59 if (enabled_)
60 return true;
61 enabled_ = OpenLogFile();
62 if (enabled_) {
63 Log("var raw_trace_events = [\n");
64 trace_start_time_ = TimeTicks::Now();
65 timer_.Start(TimeDelta::FromMilliseconds(250), this, &TraceLog::Heartbeat);
66 }
67 return enabled_;
68 }
69
70 // static
StopTracing()71 void TraceLog::StopTracing() {
72 TraceLog* trace = Singleton<TraceLog>::get();
73 return trace->Stop();
74 }
75
Stop()76 void TraceLog::Stop() {
77 if (enabled_) {
78 enabled_ = false;
79 Log("];\n");
80 CloseLogFile();
81 timer_.Stop();
82 }
83 }
84
Heartbeat()85 void TraceLog::Heartbeat() {
86 std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage());
87 TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu);
88 }
89
CloseLogFile()90 void TraceLog::CloseLogFile() {
91 if (log_file_) {
92 file_util::CloseFile(log_file_);
93 }
94 }
95
OpenLogFile()96 bool TraceLog::OpenLogFile() {
97 FilePath::StringType pid_filename =
98 StringPrintf(kLogFileName, base::GetCurrentProcId());
99 FilePath log_file_path;
100 if (!PathService::Get(base::DIR_EXE, &log_file_path))
101 return false;
102 log_file_path = log_file_path.Append(pid_filename);
103 log_file_ = file_util::OpenFile(log_file_path, "a");
104 if (!log_file_) {
105 // try the current directory
106 log_file_ = file_util::OpenFile(FilePath(pid_filename), "a");
107 if (!log_file_) {
108 return false;
109 }
110 }
111 return true;
112 }
113
Trace(const std::string & name,EventType type,const void * id,const std::wstring & extra,const char * file,int line)114 void TraceLog::Trace(const std::string& name,
115 EventType type,
116 const void* id,
117 const std::wstring& extra,
118 const char* file,
119 int line) {
120 if (!enabled_)
121 return;
122 Trace(name, type, id, WideToUTF8(extra), file, line);
123 }
124
Trace(const std::string & name,EventType type,const void * id,const std::string & extra,const char * file,int line)125 void TraceLog::Trace(const std::string& name,
126 EventType type,
127 const void* id,
128 const std::string& extra,
129 const char* file,
130 int line) {
131 if (!enabled_)
132 return;
133
134 #ifdef USE_UNRELIABLE_NOW
135 TimeTicks tick = TimeTicks::HighResNow();
136 #else
137 TimeTicks tick = TimeTicks::Now();
138 #endif
139 TimeDelta delta = tick - trace_start_time_;
140 int64 usec = delta.InMicroseconds();
141 std::string msg =
142 StringPrintf("{'pid':'0x%lx', 'tid':'0x%lx', 'type':'%s', "
143 "'name':'%s', 'id':'%p', 'extra':'%s', 'file':'%s', "
144 "'line_number':'%d', 'usec_begin': %" PRId64 "},\n",
145 static_cast<unsigned long>(base::GetCurrentProcId()),
146 static_cast<unsigned long>(PlatformThread::CurrentId()),
147 kEventTypeNames[type],
148 name.c_str(),
149 id,
150 extra.c_str(),
151 file,
152 line,
153 usec);
154
155 Log(msg);
156 }
157
Log(const std::string & msg)158 void TraceLog::Log(const std::string& msg) {
159 AutoLock lock(file_lock_);
160
161 fprintf(log_file_, "%s", msg.c_str());
162 }
163
164 } // namespace base
165