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 3// found in the LICENSE file. 4 5#include "base/debug/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/stringprintf.h" 14#include "base/utf_string_conversions.h" 15#include "base/time.h" 16 17#define USE_UNRELIABLE_NOW 18 19namespace base { 20namespace debug { 21 22static const char* kEventTypeNames[] = { 23 "BEGIN", 24 "END", 25 "INSTANT" 26}; 27 28static const FilePath::CharType* kLogFileName = 29 FILE_PATH_LITERAL("trace_%d.log"); 30 31// static 32TraceLog* TraceLog::GetInstance() { 33 return Singleton<TraceLog, DefaultSingletonTraits<TraceLog> >::get(); 34} 35 36// static 37bool TraceLog::IsTracing() { 38 return TraceLog::GetInstance()->enabled_; 39} 40 41// static 42bool TraceLog::StartTracing() { 43 return TraceLog::GetInstance()->Start(); 44} 45 46// static 47void TraceLog::StopTracing() { 48 return TraceLog::GetInstance()->Stop(); 49} 50 51void TraceLog::Trace(const std::string& name, 52 EventType type, 53 const void* id, 54 const std::wstring& extra, 55 const char* file, 56 int line) { 57 if (!enabled_) 58 return; 59 Trace(name, type, id, WideToUTF8(extra), file, line); 60} 61 62void TraceLog::Trace(const std::string& name, 63 EventType type, 64 const void* id, 65 const std::string& extra, 66 const char* file, 67 int line) { 68 if (!enabled_) 69 return; 70 71#ifdef USE_UNRELIABLE_NOW 72 TimeTicks tick = TimeTicks::HighResNow(); 73#else 74 TimeTicks tick = TimeTicks::Now(); 75#endif 76 TimeDelta delta = tick - trace_start_time_; 77 int64 usec = delta.InMicroseconds(); 78 std::string msg = 79 StringPrintf("{'pid':'0x%lx', 'tid':'0x%lx', 'type':'%s', " 80 "'name':'%s', 'id':'%p', 'extra':'%s', 'file':'%s', " 81 "'line_number':'%d', 'usec_begin': %" PRId64 "},\n", 82 static_cast<unsigned long>(base::GetCurrentProcId()), 83 static_cast<unsigned long>(PlatformThread::CurrentId()), 84 kEventTypeNames[type], 85 name.c_str(), 86 id, 87 extra.c_str(), 88 file, 89 line, 90 usec); 91 92 Log(msg); 93} 94 95TraceLog::TraceLog() : enabled_(false), log_file_(NULL) { 96 base::ProcessHandle proc = base::GetCurrentProcessHandle(); 97#if !defined(OS_MACOSX) 98 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc)); 99#else 100 // The default port provider is sufficient to get data for the current 101 // process. 102 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc, 103 NULL)); 104#endif 105} 106 107TraceLog::~TraceLog() { 108 Stop(); 109} 110 111bool TraceLog::OpenLogFile() { 112 FilePath::StringType pid_filename = 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 129void TraceLog::CloseLogFile() { 130 if (log_file_) { 131 file_util::CloseFile(log_file_); 132 } 133} 134 135bool 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 147void TraceLog::Stop() { 148 if (enabled_) { 149 enabled_ = false; 150 Log("];\n"); 151 CloseLogFile(); 152 timer_.Stop(); 153 } 154} 155 156void TraceLog::Heartbeat() { 157 std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage()); 158 TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu); 159} 160 161void TraceLog::Log(const std::string& msg) { 162 AutoLock lock(file_lock_); 163 164 fprintf(log_file_, "%s", msg.c_str()); 165} 166 167} // namespace debug 168} // namespace base 169