Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: base/debug/trace_event.cc

Issue 6551019: Trace_event upgrades (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More gooder js thanks to arv. Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/trace_event.h" 5 #include "base/debug/trace_event.h"
6 6
7 #if defined(OS_WIN)
8 #include "base/debug/trace_event_win.h"
9 #endif
7 #include "base/format_macros.h" 10 #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/process_util.h" 11 #include "base/process_util.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
15 #include "base/time.h" 14 #include "base/time.h"
16 15
17 #define USE_UNRELIABLE_NOW 16 #define USE_UNRELIABLE_NOW
18 17
19 namespace base { 18 namespace base {
20 namespace debug { 19 namespace debug {
21 20
22 static const char* kEventTypeNames[] = { 21 #define GPU_TRACE_MAX_EVENTS_TO_BUFFER 16384
rvargas (doing something else) 2011/02/25 23:38:33 ?
23 "BEGIN", 22
24 "END", 23 ////////////////////////////////////////////////////////////////////////////////
25 "INSTANT" 24 //
26 }; 25 // TraceLog::Category
27 26 //
28 static const FilePath::CharType* kLogFileName = 27 ////////////////////////////////////////////////////////////////////////////////
29 FILE_PATH_LITERAL("trace_%d.log"); 28 TraceCategory::TraceCategory(const char* name, bool enabled)
29 : name_(name) {
30 base::subtle::NoBarrier_Store(&enabled_,
31 static_cast<base::subtle::Atomic32>(enabled));
32 }
33
34 TraceCategory::~TraceCategory() {
35 base::subtle::NoBarrier_Store(&enabled_,
36 static_cast<base::subtle::Atomic32>(0));
37 }
38
39 ////////////////////////////////////////////////////////////////////////////////
40 //
41 // TraceEvent
42 //
43 ////////////////////////////////////////////////////////////////////////////////
44
45 namespace {
46 const char* GetPhaseStr(TraceEventPhase phase) {
47 if (phase== TRACE_EVENT_PHASE_BEGIN) {
48 return "B";
49 } else if (phase == TRACE_EVENT_PHASE_INSTANT) {
50 return "I";
51 } else if (phase == TRACE_EVENT_PHASE_END) {
52 return "E";
53 } else {
54 DCHECK(false);
55 return "?";
56 }
57 }
58 }
59
60 void TraceEvent::AppendAsJSON(std::string& out,
61 const std::vector<TraceEvent>& events) {
62 out += "[";
63 for (size_t i = 0; i < events.size(); ++i) {
64 if (i > 0)
65 out += ",";
66 events[i].AppendAsJSON(out);
67 }
68 out += "]";
Ken Russell (switch to Gerrit) 2011/02/25 00:56:36 Are there more efficient ways of building up C++ s
69 }
70
71 void TraceEvent::AppendAsJSON(std::string& out) const {
72 int nargs = 0;
73 for (int i = 0; i < TRACE_MAX_NUM_ARGS; ++i) {
74 if (argNames[i] == NULL)
75 break;
76 nargs += 1;
77 }
78
79 const char* phaseStr = GetPhaseStr(phase);
80 int64 time_int64 = timestamp.ToInternalValue();
81 long long unsigned int time_llui =
82 static_cast<long long unsigned int>(time_int64);
83 StringAppendF(&out,
84 "{cat:'%s',pid:%i,tid:%i,ts:0x%llx,ph:'%s',name:'%s',args:{",
85 category->name(),
86 static_cast<int>(processId),
87 static_cast<int>(threadId),
88 time_llui,
89 phaseStr,
90 name);
91 for (int i = 0; i < nargs; ++i) {
92 if (i > 0)
93 out += ",";
94 out += argNames[i];
95 out += ":'";
96 out += argValues[i];
97 out += "'";
98 }
99 out += "}}";
100 }
101
102 ////////////////////////////////////////////////////////////////////////////////
103 //
104 // TraceLog
105 //
106 ////////////////////////////////////////////////////////////////////////////////
30 107
31 // static 108 // static
32 TraceLog* TraceLog::GetInstance() { 109 TraceLog* TraceLog::GetInstance() {
33 return Singleton<TraceLog, DefaultSingletonTraits<TraceLog> >::get(); 110 return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog> >::get();
34 } 111 }
35 112
36 // static 113 TraceLog::TraceLog()
37 bool TraceLog::IsTracing() { 114 : enabled_(false)
38 return TraceLog::GetInstance()->enabled_; 115 {
39 } 116 logged_events_.reserve(1024);
40 117 }
41 // static 118
42 bool TraceLog::StartTracing() { 119 TraceLog::~TraceLog() {
43 return TraceLog::GetInstance()->Start(); 120 }
44 } 121
45 122 TraceCategory* TraceLog::GetCategory(const char* name) {
46 // static 123 AutoLock lock(lock_);
47 void TraceLog::StopTracing() { 124 // TODO(nduca) replace with a hash_map
48 return TraceLog::GetInstance()->Stop(); 125 for (int i = categories_.size() - 1; i >= 0; i-- ) {
49 } 126 if (strcmp(categories_[i]->name(), name) == 0)
50 127 return categories_[i];
51 void TraceLog::Trace(const std::string& name, 128 }
52 EventType type, 129 TraceCategory* category = new TraceCategory(name, enabled_);
53 const void* id, 130 categories_.push_back(category);
54 const std::wstring& extra, 131 return category;
55 const char* file, 132 }
56 int line) { 133
57 if (!enabled_) 134 void TraceLog::SetEnabled(bool enabled) {
135 AutoLock lock(lock_);
136 if (enabled == enabled_)
58 return; 137 return;
59 Trace(name, type, id, WideToUTF8(extra), file, line); 138 if (enabled) {
60 } 139 /* enable all categories */
61 140 enabled_ = true;
62 void TraceLog::Trace(const std::string& name, 141 for (size_t i = 0; i < categories_.size(); i++) {
63 EventType type, 142 base::subtle::NoBarrier_Store(&categories_[i]->enabled_,
64 const void* id, 143 static_cast<base::subtle::Atomic32>(1));
65 const std::string& extra, 144 }
66 const char* file, 145 } else {
67 int line) { 146 /* disable all categories */
68 if (!enabled_) 147 for (size_t i = 0; i < categories_.size(); i++) {
69 return; 148 base::subtle::NoBarrier_Store(&categories_[i]->enabled_,
70 149 static_cast<base::subtle::Atomic32>(0));
150 }
151 enabled_ = false;
152 FlushWithLockAlreadyHeld();
153 }
154 }
155
156 void TraceLog::SetOutputCallback(TraceLog::OutputCallback* cb) {
157 AutoLock lock(lock_);
158 if (enabled_) {
159 FlushWithLockAlreadyHeld();
160 }
161 output_callback_.reset(cb);
162 }
163
164 void TraceLog::AddRemotelyCollectedData(const std::string& json_events) {
165 AutoLock lock(lock_);
166 if (output_callback_.get())
167 output_callback_->Run(json_events);
168 }
169
170 void TraceLog::Flush() {
171 AutoLock lock(lock_);
172 FlushWithLockAlreadyHeld();
173 }
174
175 void TraceLog::FlushWithLockAlreadyHeld() {
176 if (output_callback_.get() && logged_events_.size()) {
177 std::string json_events;
178 TraceEvent::AppendAsJSON(json_events, logged_events_);
179 output_callback_->Run(json_events);
180 }
181 logged_events_.erase(logged_events_.begin(), logged_events_.end());
182 }
183
184 void TraceLog::AddTraceEvent(TraceEventPhase phase,
185 const char* file, int line,
186 TraceCategory* category,
187 const char* name,
188 const char* arg1name, const char* arg1val,
189 const char* arg2name, const char* arg2val) {
190 DCHECK(file && name);
71 #ifdef USE_UNRELIABLE_NOW 191 #ifdef USE_UNRELIABLE_NOW
72 TimeTicks tick = TimeTicks::HighResNow(); 192 TimeTicks now = TimeTicks::HighResNow();
73 #else 193 #else
74 TimeTicks tick = TimeTicks::Now(); 194 TimeTicks now = TimeTicks::Now();
75 #endif 195 #endif
76 TimeDelta delta = tick - trace_start_time_; 196 //static_cast<unsigned long>(base::GetCurrentProcId()),
77 int64 usec = delta.InMicroseconds(); 197 AutoLock lock(lock_);
78 std::string msg = 198 logged_events_.push_back(TraceEvent());
79 StringPrintf("{'pid':'0x%lx', 'tid':'0x%lx', 'type':'%s', " 199 TraceEvent& event = logged_events_.back();
80 "'name':'%s', 'id':'%p', 'extra':'%s', 'file':'%s', " 200 event.processId = static_cast<unsigned long>(base::GetCurrentProcId());
81 "'line_number':'%d', 'usec_begin': %" PRId64 "},\n", 201 event.threadId = PlatformThread::CurrentId();
82 static_cast<unsigned long>(base::GetCurrentProcId()), 202 event.timestamp = now;
83 static_cast<unsigned long>(PlatformThread::CurrentId()), 203 event.phase = phase;
84 kEventTypeNames[type], 204 event.category = category;
85 name.c_str(), 205 event.name = name;
86 id, 206 event.argNames[0] = arg1name;
87 extra.c_str(), 207 event.argValues[0] = arg1name ? arg1val : "";
88 file, 208 event.argNames[1] = arg2name;
89 line, 209 event.argValues[1] = arg2name ? arg2val : "";
90 usec); 210 COMPILE_ASSERT(TRACE_MAX_NUM_ARGS == 2, TraceEvent_arc_count_out_of_sync);
91 211
92 Log(msg); 212 if (logged_events_.size() > GPU_TRACE_MAX_EVENTS_TO_BUFFER)
93 } 213 FlushWithLockAlreadyHeld();
94 214 }
95 TraceLog::TraceLog() : enabled_(false), log_file_(NULL) { 215
96 base::ProcessHandle proc = base::GetCurrentProcessHandle(); 216 void TraceLog::AddTraceEventLegacy(TraceEventPhase phase,
97 #if !defined(OS_MACOSX) 217 const char* file, int line,
98 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc)); 218 const char* name,
99 #else 219 const void* id,
100 // The default port provider is sufficient to get data for the current 220 const char* extra) {
101 // process. 221 // Legacy trace points on windows called to ETW
102 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc, 222 #if defined(OS_WIN)
103 NULL)); 223 TraceEventETWProvider::Trace(name, phase, id, extra);
104 #endif 224 #endif
105 } 225
106 226 // Also add new trace event behavior
107 TraceLog::~TraceLog() { 227 static TraceCategory* category = GetCategory("Legacy Trace Event");
108 Stop(); 228 if (category->enabled_) {
109 } 229 AddTraceEvent(phase, file, line, category, name,
110 230 "id", StringPrintf("%p", id).c_str(),
111 bool TraceLog::OpenLogFile() { 231 "extra", extra ? extra : "");
112 FilePath::StringType pid_filename = 232 }
113 StringPrintf(kLogFileName, base::GetCurrentProcId());
114 FilePath log_file_path;
115 if (!PathService::Get(base::DIR_EXE, &log_file_path))
116 return false;
117 log_file_path = log_file_path.Append(pid_filename);
118 log_file_ = file_util::OpenFile(log_file_path, "a");
119 if (!log_file_) {
120 // try the current directory
121 log_file_ = file_util::OpenFile(FilePath(pid_filename), "a");
122 if (!log_file_) {
123 return false;
124 }
125 }
126 return true;
127 }
128
129 void TraceLog::CloseLogFile() {
130 if (log_file_) {
131 file_util::CloseFile(log_file_);
132 }
133 }
134
135 bool TraceLog::Start() {
136 if (enabled_)
137 return true;
138 enabled_ = OpenLogFile();
139 if (enabled_) {
140 Log("var raw_trace_events = [\n");
141 trace_start_time_ = TimeTicks::Now();
142 timer_.Start(TimeDelta::FromMilliseconds(250), this, &TraceLog::Heartbeat);
143 }
144 return enabled_;
145 }
146
147 void TraceLog::Stop() {
148 if (enabled_) {
149 enabled_ = false;
150 Log("];\n");
151 CloseLogFile();
152 timer_.Stop();
153 }
154 }
155
156 void TraceLog::Heartbeat() {
157 std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage());
158 TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu);
159 }
160
161 void TraceLog::Log(const std::string& msg) {
162 AutoLock lock(file_lock_);
163
164 fprintf(log_file_, "%s", msg.c_str());
165 } 233 }
166 234
167 } // namespace debug 235 } // namespace debug
168 } // namespace base 236 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698