diff options
author | scheib@chromium.org <scheib@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-05 20:14:33 +0000 |
---|---|---|
committer | scheib@chromium.org <scheib@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-05 20:14:33 +0000 |
commit | 39a52b444388584f604a5b14ed5983d2f23a418a (patch) | |
tree | 2531335e6735df54d7f525e896e61f8f249a2d47 /base/debug/trace_event.cc | |
parent | 4d4c0780f53e428a1d4c24ebf4e509490d56a7fc (diff) | |
download | chromium_src-39a52b444388584f604a5b14ed5983d2f23a418a.zip chromium_src-39a52b444388584f604a5b14ed5983d2f23a418a.tar.gz chromium_src-39a52b444388584f604a5b14ed5983d2f23a418a.tar.bz2 |
Revert 84284 - Merge gpu_trace_event back into base/debug/trace_event.Initial land attempt at http://codereview.chromium.org/6551019/gpu_trace_event fork at http://codereview.chromium.org/6691013- gpu_trace_event renamed to base/debug/trace_event and modified as appropriate for base::debug- Unit Tests implemented for trace_event- gpu_common library removed (was added only for gpu_trace_event)- Existing calls to trace_event suffixed with _ETW to make ETW calls (see decisions and incremental plans at end of 6551019)- GPU trace calls renamed to new calls.- Tracing switch removed from test_shell, as linux log file support removed.BUG=79509TEST=trace_event_win_unittest and about:gpuReview URL: http://codereview.chromium.org/6862002
TBR=scheib@chromium.org
Review URL: http://codereview.chromium.org/6933035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84293 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/debug/trace_event.cc')
-rw-r--r-- | base/debug/trace_event.cc | 452 |
1 files changed, 117 insertions, 335 deletions
diff --git a/base/debug/trace_event.cc b/base/debug/trace_event.cc index e1f6061..c219cec 100644 --- a/base/debug/trace_event.cc +++ b/base/debug/trace_event.cc @@ -1,15 +1,16 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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" -#if defined(OS_WIN) -#include "base/debug/trace_event_win.h" -#endif #include "base/format_macros.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/path_service.h" #include "base/process_util.h" #include "base/stringprintf.h" +#include "base/threading/platform_thread.h" #include "base/utf_string_conversions.h" #include "base/time.h" @@ -18,368 +19,149 @@ namespace base { namespace debug { -// Controls the number of trace events we will buffer in-memory -// before throwing them away. -const size_t kTraceEventBufferSize = 500000; -const size_t kTraceEventBatchSize = 1000; - -#define TRACE_EVENT_MAX_CATEGORIES 42 - -static TraceCategory g_categories[TRACE_EVENT_MAX_CATEGORIES] = { - { "tracing already shutdown", false }, - { "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES", - false } +static const char* kEventTypeNames[] = { + "BEGIN", + "END", + "INSTANT" }; -static const TraceCategory* const g_category_already_shutdown = - &g_categories[0]; -static const TraceCategory* const g_category_categories_exhausted = - &g_categories[1]; -static int g_category_index = 2; // skip initial 2 error categories - -//////////////////////////////////////////////////////////////////////////////// -// -// TraceValue -// -//////////////////////////////////////////////////////////////////////////////// - -void TraceValue::Destroy() { - if (type_ == TRACE_TYPE_STRING) { - value_.as_string_refptr->Release(); - value_.as_string_refptr = NULL; - } - type_ = TRACE_TYPE_UNDEFINED; - value_.as_uint = 0ull; -} - -TraceValue& TraceValue::operator=(const TraceValue& rhs) { - if (this == &rhs) - return *this; - - Destroy(); - - type_ = rhs.type_; - switch(type_) { - case TRACE_TYPE_UNDEFINED: - return *this; - case TRACE_TYPE_BOOL: - value_.as_bool = rhs.value_.as_bool; - return *this; - case TRACE_TYPE_UINT: - value_.as_uint = rhs.value_.as_uint; - return *this; - case TRACE_TYPE_INT: - value_.as_int = rhs.value_.as_int; - return *this; - case TRACE_TYPE_DOUBLE: - value_.as_double = rhs.value_.as_double; - return *this; - case TRACE_TYPE_POINTER: - value_.as_pointer = rhs.value_.as_pointer; - return *this; - case TRACE_TYPE_STRING: - value_.as_string_refptr = rhs.value_.as_string_refptr; - value_.as_string_refptr->AddRef(); - return *this; - default: - NOTREACHED(); - return *this; - } -} - -void TraceValue::AppendAsJSON(std::string* out) const { - char temp_string[128]; - std::string::size_type start_pos; - switch (type_) { - case TRACE_TYPE_BOOL: - *out += as_bool()? "true" : "false"; - break; - case TRACE_TYPE_UINT: - base::snprintf(temp_string, arraysize(temp_string), "%llu", - static_cast<unsigned long long>(as_uint())); - *out += temp_string; - break; - case TRACE_TYPE_INT: - base::snprintf(temp_string, arraysize(temp_string), "%lld", - static_cast<long long>(as_int())); - *out += temp_string; - break; - case TRACE_TYPE_DOUBLE: - base::snprintf(temp_string, arraysize(temp_string), "%f", as_double()); - *out += temp_string; - break; - case TRACE_TYPE_POINTER: - base::snprintf(temp_string, arraysize(temp_string), "%llu", - static_cast<unsigned long long>( - reinterpret_cast<intptr_t>( - as_pointer()))); - *out += temp_string; - break; - case TRACE_TYPE_STRING: - *out += "\""; - start_pos = out->size(); - *out += as_string(); - // replace " character with ' - while ((start_pos = out->find_first_of('\"', start_pos)) != - std::string::npos) - (*out)[start_pos] = '\''; - *out += "\""; - break; - default: - NOTREACHED() << "Don't know how to print this value"; - break; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -// TraceEvent -// -//////////////////////////////////////////////////////////////////////////////// -namespace { +static const FilePath::CharType* kLogFileName = + FILE_PATH_LITERAL("trace_%d.log"); -const char* GetPhaseStr(TraceEventPhase phase) { - switch(phase) { - case TRACE_EVENT_PHASE_BEGIN: - return "B"; - case TRACE_EVENT_PHASE_INSTANT: - return "I"; - case TRACE_EVENT_PHASE_END: - return "E"; - default: - NOTREACHED() << "Invalid phase argument"; - return "?"; - } +// static +TraceLog* TraceLog::GetInstance() { + return Singleton<TraceLog, DefaultSingletonTraits<TraceLog> >::get(); } -} // namespace - -TraceEvent::TraceEvent() - : process_id(0), - thread_id(0), - phase(TRACE_EVENT_PHASE_BEGIN), - category(NULL), - name(NULL) { - memset(arg_names, 0, sizeof(arg_names)); +// static +bool TraceLog::IsTracing() { + return TraceLog::GetInstance()->enabled_; } -TraceEvent::~TraceEvent() { +// static +bool TraceLog::StartTracing() { + return TraceLog::GetInstance()->Start(); } -void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events, - size_t start, - size_t count, - std::string* out) { - *out += "["; - for (size_t i = 0; i < count && start + i < events.size(); ++i) { - if (i > 0) - *out += ","; - events[i + start].AppendAsJSON(out); - } - *out += "]"; +// static +void TraceLog::StopTracing() { + return TraceLog::GetInstance()->Stop(); } -void TraceEvent::AppendAsJSON(std::string* out) const { - const char* phase_str = GetPhaseStr(phase); - int64 time_int64 = timestamp.ToInternalValue(); - // Category name checked at category creation time. - DCHECK(!strchr(name, '"')); - StringAppendF(out, - "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%lld," - "\"ph\":\"%s\",\"name\":\"%s\",\"args\":{", - category->name, - static_cast<int>(process_id), - static_cast<int>(thread_id), - static_cast<long long>(time_int64), - phase_str, - name); - - // Output argument names and values, stop at first NULL argument name. - for (size_t i = 0; i < kTraceMaxNumArgs && arg_names[i]; ++i) { - if (i > 0) - *out += ","; - *out += "\""; - *out += arg_names[i]; - *out += "\":"; - arg_values[i].AppendAsJSON(out); - } - *out += "}}"; +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); } -//////////////////////////////////////////////////////////////////////////////// -// -// TraceLog -// -//////////////////////////////////////////////////////////////////////////////// - -// static -TraceLog* TraceLog::GetInstance() { - return Singleton<TraceLog, StaticMemorySingletonTraits<TraceLog> >::get(); -} +void TraceLog::Trace(const std::string& name, + EventType type, + const void* id, + const std::string& extra, + const char* file, + int line) { + if (!enabled_) + return; -TraceLog::TraceLog() - : enabled_(false) { - logged_events_.reserve(1024); +#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() { -} - -const TraceCategory* TraceLog::GetCategory(const char* name) { - TraceLog* tracelog = GetInstance(); - if (!tracelog){ - CHECK(!g_category_already_shutdown->enabled); - return g_category_already_shutdown; + 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 tracelog->GetCategoryInternal(name); + return true; } -const TraceCategory* TraceLog::GetCategoryInternal(const char* name) { - AutoLock lock(lock_); - DCHECK(!strchr(name, '"')) << "Names may not contain double quote char"; - - // Search for pre-existing category matching this name - for (int i = 0; i < g_category_index; i++) { - if (strcmp(g_categories[i].name, name) == 0) - return &g_categories[i]; - } - - // Create a new category - DCHECK(g_category_index < TRACE_EVENT_MAX_CATEGORIES) << - "must increase TRACE_EVENT_MAX_CATEGORIES"; - if (g_category_index < TRACE_EVENT_MAX_CATEGORIES) { - int new_index = g_category_index++; - g_categories[new_index].name = name; - DCHECK(!g_categories[new_index].enabled); - g_categories[new_index].enabled = enabled_; - return &g_categories[new_index]; - } else { - return g_category_categories_exhausted; +void TraceLog::CloseLogFile() { + if (log_file_) { + file_util::CloseFile(log_file_); } } -void TraceLog::SetEnabled(bool enabled) { - { - AutoLock lock(lock_); - if (enabled == enabled_) - return; - enabled_ = enabled; - for (int i = 0; i < g_category_index; i++) { - //TODO(scheib): If changed to enable specific categories instead of all - // check GetCategoryInternal creation code that users TraceLog::enabled_ - g_categories[i].enabled = enabled; - } - } // release lock - if (!enabled) - Flush(); -} - -float TraceLog::GetBufferPercentFull() const { - return (float)((double)logged_events_.size()/(double)kTraceEventBufferSize); -} - -void TraceLog::SetOutputCallback(const TraceLog::OutputCallback& cb) { - Flush(); - AutoLock lock(lock_); - output_callback_ = cb; -} - -void TraceLog::SetBufferFullCallback(const TraceLog::BufferFullCallback& cb) { - AutoLock lock(lock_); - buffer_full_callback_ = cb; +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::Flush() { - std::vector<TraceEvent> previous_logged_events; - OutputCallback output_callback_copy; - { - AutoLock lock(lock_); - previous_logged_events.swap(logged_events_); - output_callback_copy = output_callback_; - } // release lock - - if (output_callback_copy.is_null()) - return; - - for (size_t i = 0; - i < previous_logged_events.size(); - i += kTraceEventBatchSize) { - scoped_refptr<RefCountedString> json_events_str_ptr = - new RefCountedString(); - TraceEvent::AppendEventsAsJSON(previous_logged_events, - i, - kTraceEventBatchSize, - &(json_events_str_ptr->data)); - output_callback_copy.Run(json_events_str_ptr.get()); +void TraceLog::Stop() { + if (enabled_) { + enabled_ = false; + Log("];\n"); + CloseLogFile(); + timer_.Stop(); } } -void TraceLog::AddTraceEvent(TraceEventPhase phase, - const char* file, int line, - const TraceCategory* category, - const char* name, - const char* arg1_name, TraceValue arg1_val, - const char* arg2_name, TraceValue arg2_val) { - DCHECK(file && name); -#ifdef USE_UNRELIABLE_NOW - TimeTicks now = TimeTicks::HighResNow(); -#else - TimeTicks now = TimeTicks::Now(); -#endif - BufferFullCallback buffer_full_callback_copy; - { - AutoLock lock(lock_); - if (!enabled_ || !category->enabled) - return; - if (logged_events_.size() >= kTraceEventBufferSize) - return; - logged_events_.push_back(TraceEvent()); - TraceEvent& event = logged_events_.back(); - event.process_id = static_cast<unsigned long>(base::GetCurrentProcId()); - event.thread_id = PlatformThread::CurrentId(); - event.timestamp = now; - event.phase = phase; - event.category = category; - event.name = name; - event.arg_names[0] = arg1_name; - event.arg_values[0] = arg1_val; - event.arg_names[1] = arg2_name; - event.arg_values[1] = arg2_val; - COMPILE_ASSERT(kTraceMaxNumArgs == 2, TraceEvent_arg_count_out_of_sync); - - if (logged_events_.size() == kTraceEventBufferSize) { - buffer_full_callback_copy = buffer_full_callback_; - } - } // release lock - - if (!buffer_full_callback_copy.is_null()) - buffer_full_callback_copy.Run(); +void TraceLog::Heartbeat() { + std::string cpu = StringPrintf("%.0f", process_metrics_->GetCPUUsage()); + TRACE_EVENT_INSTANT("heartbeat.cpu", 0, cpu); } -void TraceLog::AddTraceEventEtw(TraceEventPhase phase, - const char* file, int line, - const char* name, - const void* id, - const char* extra) { - // Legacy trace points on windows called to ETW -#if defined(OS_WIN) - TraceEventETWProvider::Trace(name, phase, id, extra); -#endif - - // Also add new trace event behavior - static const TraceCategory* category = GetCategory("ETW Trace Event"); - if (category->enabled) { - TraceLog* tracelog = TraceLog::GetInstance(); - if (!tracelog) - return; - tracelog->AddTraceEvent(phase, file, line, category, name, - "id", id, - "extra", extra ? extra : ""); - } -} +void TraceLog::Log(const std::string& msg) { + AutoLock lock(file_lock_); -void TraceLog::Resurrect() { - StaticMemorySingletonTraits<TraceLog>::Resurrect(); + fprintf(log_file_, "%s", msg.c_str()); } } // namespace debug |