| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/debug/trace_event.h" |
| |
| #include "base/format_macros.h" |
| #include "base/file_path.h" |
| #include "base/file_util.h" |
| #include "base/path_service.h" |
| #include "base/platform_thread.h" |
| #include "base/process_util.h" |
| #include "base/stringprintf.h" |
| #include "base/utf_string_conversions.h" |
| #include "base/time.h" |
| |
| #define USE_UNRELIABLE_NOW |
| |
| namespace base { |
| namespace debug { |
| |
| static const char* kEventTypeNames[] = { |
| "BEGIN", |
| "END", |
| "INSTANT" |
| }; |
| |
| static const FilePath::CharType* kLogFileName = |
| FILE_PATH_LITERAL("trace_%d.log"); |
| |
| // static |
| TraceLog* TraceLog::GetInstance() { |
| return Singleton<TraceLog, DefaultSingletonTraits<TraceLog> >::get(); |
| } |
| |
| // static |
| bool TraceLog::IsTracing() { |
| return TraceLog::GetInstance()->enabled_; |
| } |
| |
| // static |
| bool TraceLog::StartTracing() { |
| return TraceLog::GetInstance()->Start(); |
| } |
| |
| // static |
| void TraceLog::StopTracing() { |
| return TraceLog::GetInstance()->Stop(); |
| } |
| |
| void TraceLog::Trace(const std::string& name, |
| EventType type, |
| const void* id, |
| const std::wstring& extra, |
| const char* file, |
| int line) { |
| if (!enabled_) |
| return; |
| Trace(name, type, id, WideToUTF8(extra), file, line); |
| } |
| |
| void TraceLog::Trace(const std::string& name, |
| EventType type, |
| const void* id, |
| const std::string& extra, |
| const char* file, |
| int line) { |
| if (!enabled_) |
| return; |
| |
| #ifdef USE_UNRELIABLE_NOW |
| TimeTicks tick = TimeTicks::HighResNow(); |
| #else |
| TimeTicks tick = TimeTicks::Now(); |
| #endif |
| TimeDelta delta = tick - trace_start_time_; |
| int64 usec = delta.InMicroseconds(); |
| std::string msg = |
| StringPrintf("{'pid':'0x%lx', 'tid':'0x%lx', 'type':'%s', " |
| "'name':'%s', 'id':'%p', 'extra':'%s', 'file':'%s', " |
| "'line_number':'%d', 'usec_begin': %" PRId64 "},\n", |
| static_cast<unsigned long>(base::GetCurrentProcId()), |
| static_cast<unsigned long>(PlatformThread::CurrentId()), |
| kEventTypeNames[type], |
| name.c_str(), |
| id, |
| extra.c_str(), |
| file, |
| line, |
| usec); |
| |
| Log(msg); |
| } |
| |
| TraceLog::TraceLog() : enabled_(false), log_file_(NULL) { |
| base::ProcessHandle proc = base::GetCurrentProcessHandle(); |
| #if !defined(OS_MACOSX) |
| process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc)); |
| #else |
| // The default port provider is sufficient to get data for the current |
| // process. |
| process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(proc, |
| NULL)); |
| #endif |
| } |
| |
| TraceLog::~TraceLog() { |
| Stop(); |
| } |
| |
| bool TraceLog::OpenLogFile() { |
| FilePath::StringType pid_filename = |
| StringPrintf(kLogFileName, base::GetCurrentProcId()); |
| FilePath log_file_path; |
| if (!PathService::Get(base::DIR_EXE, &log_file_path)) |
| return false; |
| log_file_path = log_file_path.Append(pid_filename); |
| log_file_ = file_util::OpenFile(log_file_path, "a"); |
| if (!log_file_) { |
| // try the current directory |
| log_file_ = file_util::OpenFile(FilePath(pid_filename), "a"); |
| if (!log_file_) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| void TraceLog::CloseLogFile() { |
| if (log_file_) { |
| file_util::CloseFile(log_file_); |
| } |
| } |
| |
| bool TraceLog::Start() { |
| if (enabled_) |
| return true; |
| enabled_ = OpenLogFile(); |
| if (enabled_) { |
| Log("var raw_trace_events = [\n"); |
| trace_start_time_ = TimeTicks::Now(); |
| timer_.Start(TimeDelta::FromMilliseconds(250), this, &TraceLog::Heartbeat); |
| } |
| return enabled_; |
| } |
| |
| void TraceLog::Stop() { |
| if (enabled_) { |
| enabled_ = false; |
| Log("];\n"); |
| CloseLogFile(); |
| timer_.Stop(); |
| } |
| } |
| |
| void TraceLog::Heartbeat() { |
| std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage()); |
| TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu); |
| } |
| |
| void TraceLog::Log(const std::string& msg) { |
| AutoLock lock(file_lock_); |
| |
| fprintf(log_file_, "%s", msg.c_str()); |
| } |
| |
| } // namespace debug |
| } // namespace base |