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