summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
Diffstat (limited to 'base')
-rw-r--r--base/debug/trace_event.cc373
-rw-r--r--base/debug/trace_event.h715
-rw-r--r--base/debug/trace_event_unittest.cc118
-rw-r--r--base/debug/trace_event_win.cc6
-rw-r--r--base/debug/trace_event_win.h10
-rw-r--r--base/test/trace_event_analyzer.cc156
-rw-r--r--base/test/trace_event_analyzer.h13
7 files changed, 819 insertions, 572 deletions
diff --git a/base/debug/trace_event.cc b/base/debug/trace_event.cc
index 969af1c..c554769 100644
--- a/base/debug/trace_event.cc
+++ b/base/debug/trace_event.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -45,27 +45,21 @@ const size_t kTraceEventBatchSize = 1000;
namespace {
-// Specify these values when the corresponding argument of AddTraceEvent is not
-// used.
-static const char* kNoArgName = NULL;
-static const int kNoArgValue = 0;
-static const int kNoThreshholdBeginId = -1;
-static const int64 kNoThresholdValue = 0;
-static const int kNoEventId = 0;
-
-TraceCategory g_categories[TRACE_EVENT_MAX_CATEGORIES] = {
- { "tracing already shutdown", false },
- { "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES",
- false },
- { "__metadata",
- false }
+// Parallel arrays g_categories and g_category_enabled are separate so that
+// a pointer to a member of g_category_enabled can be easily converted to an
+// index into g_categories. This allows macros to deal only with char enabled
+// pointers from g_category_enabled, and we can convert internally to determine
+// the category name from the char enabled pointer.
+const char* g_categories[TRACE_EVENT_MAX_CATEGORIES] = {
+ "tracing already shutdown",
+ "tracing categories exhausted; must increase TRACE_EVENT_MAX_CATEGORIES",
+ "__metadata",
};
-const TraceCategory* const g_category_already_shutdown =
- &g_categories[0];
-const TraceCategory* const g_category_categories_exhausted =
- &g_categories[1];
-const TraceCategory* const g_category_metadata =
- &g_categories[2];
+// The enabled flag is char instead of bool so that the API can be used from C.
+unsigned char g_category_enabled[TRACE_EVENT_MAX_CATEGORIES] = { 0 };
+const int g_category_already_shutdown = 0;
+const int g_category_categories_exhausted = 1;
+const int g_category_metadata = 2;
int g_category_index = 3; // skip initial 3 categories
// The most-recently captured name of the current thread
@@ -73,41 +67,35 @@ LazyInstance<ThreadLocalPointer<const char>,
LeakyLazyInstanceTraits<ThreadLocalPointer<const char> > >
g_current_thread_name = LAZY_INSTANCE_INITIALIZER;
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// TraceValue
-//
-////////////////////////////////////////////////////////////////////////////////
-
-void TraceValue::AppendAsJSON(std::string* out) const {
+void AppendValueAsJSON(unsigned char type,
+ TraceEvent::TraceValue value,
+ std::string* out) {
std::string::size_type start_pos;
- switch (type_) {
- case TRACE_TYPE_BOOL:
- *out += as_bool() ? "true" : "false";
+ switch (type) {
+ case TRACE_VALUE_TYPE_BOOL:
+ *out += value.as_bool ? "true" : "false";
break;
- case TRACE_TYPE_UINT:
- StringAppendF(out, "%" PRIu64, as_uint());
+ case TRACE_VALUE_TYPE_UINT:
+ StringAppendF(out, "%" PRIu64, static_cast<uint64>(value.as_uint));
break;
- case TRACE_TYPE_INT:
- StringAppendF(out, "%" PRId64, as_int());
+ case TRACE_VALUE_TYPE_INT:
+ StringAppendF(out, "%" PRId64, static_cast<int64>(value.as_int));
break;
- case TRACE_TYPE_DOUBLE:
- StringAppendF(out, "%f", as_double());
+ case TRACE_VALUE_TYPE_DOUBLE:
+ StringAppendF(out, "%f", value.as_double);
break;
- case TRACE_TYPE_POINTER:
+ case TRACE_VALUE_TYPE_POINTER:
// JSON only supports double and int numbers.
// So as not to lose bits from a 64-bit pointer, output as a hex string.
StringAppendF(out, "\"%" PRIx64 "\"", static_cast<uint64>(
reinterpret_cast<intptr_t>(
- as_pointer())));
+ value.as_pointer)));
break;
- case TRACE_TYPE_STRING:
- case TRACE_TYPE_STATIC_STRING:
+ case TRACE_VALUE_TYPE_STRING:
+ case TRACE_VALUE_TYPE_COPY_STRING:
*out += "\"";
start_pos = out->size();
- *out += as_string() ? as_string() : "NULL";
+ *out += value.as_string ? value.as_string : "NULL";
// insert backslash before special characters for proper json format.
while ((start_pos = out->find_first_of("\\\"", start_pos)) !=
std::string::npos) {
@@ -123,16 +111,7 @@ void TraceValue::AppendAsJSON(std::string* out) const {
}
}
-////////////////////////////////////////////////////////////////////////////////
-//
-// TraceID
-//
-////////////////////////////////////////////////////////////////////////////////
-
-TraceID::TraceID(void* rhs) {
- data_ = base::debug::TraceLog::GetInstance()->GetIntraProcessID(
- static_cast<uint64>(reinterpret_cast<uintptr_t>(rhs)));
-}
+} // namespace
////////////////////////////////////////////////////////////////////////////////
//
@@ -161,7 +140,7 @@ void CopyTraceEventParameter(char** buffer,
TraceEvent::TraceEvent()
: id_(0u),
- category_(NULL),
+ category_enabled_(NULL),
name_(NULL),
thread_id_(0),
phase_(TRACE_EVENT_PHASE_BEGIN),
@@ -172,43 +151,54 @@ TraceEvent::TraceEvent()
TraceEvent::TraceEvent(int thread_id,
TimeTicks timestamp,
- TraceEventPhase phase,
- const TraceCategory* category,
+ char phase,
+ const unsigned char* category_enabled,
const char* name,
- TraceID id,
- const char* arg1_name, const TraceValue& arg1_val,
- const char* arg2_name, const TraceValue& arg2_val,
- TraceEventFlags flags)
+ unsigned long long id,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
+ unsigned char flags)
: timestamp_(timestamp),
id_(id),
- category_(category),
+ category_enabled_(category_enabled),
name_(name),
thread_id_(thread_id),
phase_(phase),
flags_(flags) {
- COMPILE_ASSERT(kTraceMaxNumArgs == 2, TraceEvent_arg_count_out_of_sync);
- arg_names_[0] = arg1_name;
- arg_names_[1] = arg2_name;
- arg_values_[0] = arg1_val;
- arg_values_[1] = arg2_val;
+ // Clamp num_args since it may have been set by a third_party library.
+ num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
+ int i = 0;
+ for (; i < num_args; ++i) {
+ arg_names_[i] = arg_names[i];
+ arg_values_[i].as_uint = arg_values[i];
+ arg_types_[i] = arg_types[i];
+ }
+ for (; i < kTraceMaxNumArgs; ++i) {
+ arg_names_[i] = NULL;
+ arg_values_[i].as_uint = 0u;
+ arg_types_[i] = TRACE_VALUE_TYPE_UINT;
+ }
bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
size_t alloc_size = 0;
if (copy) {
alloc_size += GetAllocLength(name);
- alloc_size += GetAllocLength(arg1_name);
- alloc_size += GetAllocLength(arg2_name);
+ for (i = 0; i < num_args; ++i) {
+ alloc_size += GetAllocLength(arg_names_[i]);
+ if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
+ arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
+ }
}
- bool arg1_is_copy = (arg1_val.type() == TraceValue::TRACE_TYPE_STRING);
- bool arg2_is_copy = (arg2_val.type() == TraceValue::TRACE_TYPE_STRING);
-
- // We only take a copy of arg_vals if they are of type string (not static
- // string), regardless of the |copy| flag.
- if (arg1_is_copy)
- alloc_size += GetAllocLength(arg1_val.as_string());
- if (arg2_is_copy)
- alloc_size += GetAllocLength(arg2_val.as_string());
+ bool arg_is_copy[kTraceMaxNumArgs];
+ for (i = 0; i < num_args; ++i) {
+ // We only take a copy of arg_vals if they are of type COPY_STRING.
+ arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
+ if (arg_is_copy[i])
+ alloc_size += GetAllocLength(arg_values_[i].as_string);
+ }
if (alloc_size) {
parameter_copy_storage_ = new base::RefCountedString;
@@ -217,13 +207,13 @@ TraceEvent::TraceEvent(int thread_id,
const char* end = ptr + alloc_size;
if (copy) {
CopyTraceEventParameter(&ptr, &name_, end);
- CopyTraceEventParameter(&ptr, &arg_names_[0], end);
- CopyTraceEventParameter(&ptr, &arg_names_[1], end);
+ for (i = 0; i < num_args; ++i)
+ CopyTraceEventParameter(&ptr, &arg_names_[i], end);
+ }
+ for (i = 0; i < num_args; ++i) {
+ if (arg_is_copy[i])
+ CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end);
}
- if (arg1_is_copy)
- CopyTraceEventParameter(&ptr, arg_values_[0].as_assignable_string(), end);
- if (arg2_is_copy)
- CopyTraceEventParameter(&ptr, arg_values_[1].as_assignable_string(), end);
DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end;
}
}
@@ -243,7 +233,6 @@ void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events,
}
void TraceEvent::AppendAsJSON(std::string* out) const {
- const char phase_char = GetPhaseChar(phase_);
int64 time_int64 = timestamp_.ToInternalValue();
int process_id = TraceLog::GetInstance()->process_id();
// Category name checked at category creation time.
@@ -251,28 +240,28 @@ void TraceEvent::AppendAsJSON(std::string* out) const {
StringAppendF(out,
"{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ","
"\"ph\":\"%c\",\"name\":\"%s\",\"args\":{",
- category_->name,
+ TraceLog::GetCategoryName(category_enabled_),
process_id,
thread_id_,
time_int64,
- phase_char,
+ phase_,
name_);
// Output argument names and values, stop at first NULL argument name.
- for (size_t i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
+ for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
if (i > 0)
*out += ",";
*out += "\"";
*out += arg_names_[i];
*out += "\":";
- arg_values_[i].AppendAsJSON(out);
+ AppendValueAsJSON(arg_types_[i], arg_values_[i], out);
}
*out += "}";
// If id_ is set, print it out as a hex string so we don't loose any
// bits (it might be a 64-bit pointer).
if (flags_ & TRACE_EVENT_FLAG_HAS_ID)
- StringAppendF(out, ",\"id\":\"%" PRIx64 "\"", id_.data());
+ StringAppendF(out, ",\"id\":\"%" PRIx64 "\"", static_cast<uint64>(id_));
*out += "}";
}
@@ -338,47 +327,62 @@ TraceLog::TraceLog()
TraceLog::~TraceLog() {
}
-const TraceCategory* TraceLog::GetCategory(const char* name) {
+const unsigned char* TraceLog::GetCategoryEnabled(const char* name) {
TraceLog* tracelog = GetInstance();
- if (!tracelog){
- DCHECK(!g_category_already_shutdown->enabled);
- return g_category_already_shutdown;
+ if (!tracelog) {
+ DCHECK(!g_category_enabled[g_category_already_shutdown]);
+ return &g_category_enabled[g_category_already_shutdown];
}
- return tracelog->GetCategoryInternal(name);
+ return tracelog->GetCategoryEnabledInternal(name);
+}
+
+const char* TraceLog::GetCategoryName(const unsigned char* category_enabled) {
+ // Calculate the index of the category by finding category_enabled in
+ // g_category_enabled array.
+ uintptr_t category_begin = reinterpret_cast<uintptr_t>(g_category_enabled);
+ uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_enabled);
+ DCHECK(category_ptr >= category_begin &&
+ category_ptr < reinterpret_cast<uintptr_t>(g_category_enabled +
+ TRACE_EVENT_MAX_CATEGORIES)) <<
+ "out of bounds category pointer";
+ uintptr_t category_index =
+ (category_ptr - category_begin) / sizeof(g_category_enabled[0]);
+ return g_categories[category_index];
}
static void EnableMatchingCategory(int category_index,
const std::vector<std::string>& patterns,
- bool is_included) {
+ unsigned char is_included) {
std::vector<std::string>::const_iterator ci = patterns.begin();
bool is_match = false;
for (; ci != patterns.end(); ++ci) {
- is_match = MatchPattern(g_categories[category_index].name, ci->c_str());
+ is_match = MatchPattern(g_categories[category_index], ci->c_str());
if (is_match)
break;
}
- ANNOTATE_BENIGN_RACE(&g_categories[category_index].enabled,
+ ANNOTATE_BENIGN_RACE(&g_category_enabled[category_index],
"trace_event category enabled");
- g_categories[category_index].enabled = is_match ? is_included : !is_included;
+ g_category_enabled[category_index] = is_match ?
+ is_included : (is_included ^ 1);
}
// Enable/disable each category based on the category filters in |patterns|.
// If the category name matches one of the patterns, its enabled status is set
// to |is_included|. Otherwise its enabled status is set to !|is_included|.
static void EnableMatchingCategories(const std::vector<std::string>& patterns,
- bool is_included) {
+ unsigned char is_included) {
for (int i = 0; i < g_category_index; i++)
EnableMatchingCategory(i, patterns, is_included);
}
-const TraceCategory* TraceLog::GetCategoryInternal(const char* name) {
+const unsigned char* TraceLog::GetCategoryEnabledInternal(const char* name) {
AutoLock lock(lock_);
DCHECK(!strchr(name, '"')) << "Category names may not contain double quote";
// 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];
+ if (strcmp(g_categories[i], name) == 0)
+ return &g_category_enabled[i];
}
// Create a new category
@@ -386,30 +390,30 @@ const TraceCategory* TraceLog::GetCategoryInternal(const char* name) {
"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] = name;
+ DCHECK(!g_category_enabled[new_index]);
if (enabled_) {
// Note that if both included and excluded_categories are empty, the else
// clause below excludes nothing, thereby enabling this category.
if (!included_categories_.empty())
- EnableMatchingCategory(new_index, included_categories_, true);
+ EnableMatchingCategory(new_index, included_categories_, 1);
else
- EnableMatchingCategory(new_index, excluded_categories_, false);
+ EnableMatchingCategory(new_index, excluded_categories_, 0);
} else {
- ANNOTATE_BENIGN_RACE(&g_categories[new_index].enabled,
+ ANNOTATE_BENIGN_RACE(&g_category_enabled[new_index],
"trace_event category enabled");
- g_categories[new_index].enabled = false;
+ g_category_enabled[new_index] = 0;
}
- return &g_categories[new_index];
+ return &g_category_enabled[new_index];
} else {
- return g_category_categories_exhausted;
+ return &g_category_enabled[g_category_categories_exhausted];
}
}
void TraceLog::GetKnownCategories(std::vector<std::string>* categories) {
AutoLock lock(lock_);
for (int i = 0; i < g_category_index; i++)
- categories->push_back(g_categories[i].name);
+ categories->push_back(g_categories[i]);
}
void TraceLog::SetEnabled(const std::vector<std::string>& included_categories,
@@ -424,9 +428,9 @@ void TraceLog::SetEnabled(const std::vector<std::string>& included_categories,
// Note that if both included and excluded_categories are empty, the else
// clause below excludes nothing, thereby enabling all categories.
if (!included_categories_.empty())
- EnableMatchingCategories(included_categories_, true);
+ EnableMatchingCategories(included_categories_, 1);
else
- EnableMatchingCategories(excluded_categories_, false);
+ EnableMatchingCategories(excluded_categories_, 0);
}
void TraceLog::SetEnabled(const std::string& categories) {
@@ -470,7 +474,7 @@ void TraceLog::SetDisabled() {
included_categories_.clear();
excluded_categories_.clear();
for (int i = 0; i < g_category_index; i++)
- g_categories[i].enabled = false;
+ g_category_enabled[i] = 0;
AddThreadNameMetadataEvents();
AddClockSyncMetadataEvents();
} // release lock
@@ -523,22 +527,24 @@ void TraceLog::Flush() {
}
}
-int TraceLog::AddTraceEvent(TraceEventPhase phase,
- const TraceCategory* category,
+int TraceLog::AddTraceEvent(char phase,
+ const unsigned char* category_enabled,
const char* name,
- TraceID id,
- const char* arg1_name, TraceValue arg1_val,
- const char* arg2_name, TraceValue arg2_val,
+ unsigned long long id,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
int threshold_begin_id,
- int64 threshold,
- TraceEventFlags flags) {
+ long long threshold,
+ unsigned char flags) {
DCHECK(name);
TimeTicks now = TimeTicks::HighResNow();
BufferFullCallback buffer_full_callback_copy;
int ret_begin_id = -1;
{
AutoLock lock(lock_);
- if (!category->enabled)
+ if (!*category_enabled)
return -1;
if (logged_events_.size() >= kTraceEventBufferSize)
return -1;
@@ -592,9 +598,8 @@ int TraceLog::AddTraceEvent(TraceEventPhase phase,
ret_begin_id = static_cast<int>(logged_events_.size());
logged_events_.push_back(
TraceEvent(thread_id,
- now, phase, category, name, id,
- arg1_name, arg1_val,
- arg2_name, arg2_val,
+ now, phase, category_enabled, name, id,
+ num_args, arg_names, arg_types, arg_values,
flags));
if (logged_events_.size() == kTraceEventBufferSize) {
@@ -608,19 +613,18 @@ int TraceLog::AddTraceEvent(TraceEventPhase phase,
return ret_begin_id;
}
-void TraceLog::AddTraceEventEtw(TraceEventPhase phase,
+void TraceLog::AddTraceEventEtw(char phase,
const char* name,
const void* id,
const char* extra) {
#if defined(OS_WIN)
TraceEventETWProvider::Trace(name, phase, id, extra);
#endif
- INTERNAL_TRACE_EVENT_ADD(phase,
- "ETW Trace Event", name, "id", id, "extra", TRACE_STR_COPY(extra),
- TRACE_EVENT_FLAG_COPY);
+ INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
+ TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
}
-void TraceLog::AddTraceEventEtw(TraceEventPhase phase,
+void TraceLog::AddTraceEventEtw(char phase,
const char* name,
const void* id,
const std::string& extra)
@@ -628,25 +632,35 @@ void TraceLog::AddTraceEventEtw(TraceEventPhase phase,
#if defined(OS_WIN)
TraceEventETWProvider::Trace(name, phase, id, extra);
#endif
- INTERNAL_TRACE_EVENT_ADD(phase,
- "ETW Trace Event", name, "id", id, "extra", extra,
- TRACE_EVENT_FLAG_COPY);
-}
-
-int TraceLog::AddCounterEvent(const TraceCategory* category,
- const char* name,
- TraceID id,
- const char* value1_name, int32 value1_val,
- const char* value2_name, int32 value2_val,
- TraceEventFlags flags) {
- return AddTraceEvent(TRACE_EVENT_PHASE_COUNTER,
- category,
- name,
- id,
- value1_name, value1_val,
- value2_name, value2_val,
- -1, 0,
- flags);
+ INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
+ TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
+}
+
+void TraceLog::AddCounterEvent(const unsigned char* category_enabled,
+ const char* name,
+ unsigned long long id,
+ const char* value1_name, int value1_val,
+ const char* value2_name, int value2_val,
+ unsigned char flags) {
+ int num_args = value2_name ? 2 : 1;
+ const char* arg_names[2] = {value1_name, value2_name};
+ unsigned char arg_types[2];
+ unsigned long long arg_values[2];
+ trace_event_internal::SetTraceValue(value1_val, &arg_types[0],
+ &arg_values[0]);
+ trace_event_internal::SetTraceValue(value2_val, &arg_types[1],
+ &arg_values[1]);
+ AddTraceEvent(TRACE_EVENT_PHASE_COUNTER,
+ category_enabled,
+ name,
+ id,
+ num_args,
+ arg_names,
+ arg_types,
+ arg_values,
+ trace_event_internal::kNoThreshholdBeginId,
+ trace_event_internal::kNoThresholdValue,
+ flags);
}
void TraceLog::AddClockSyncMetadataEvents() {
@@ -693,14 +707,20 @@ void TraceLog::AddThreadNameMetadataEvents() {
for(base::hash_map<int, std::string>::iterator it = thread_names_.begin();
it != thread_names_.end();
it++) {
- if (!it->second.empty())
+ if (!it->second.empty()) {
+ int num_args = 1;
+ const char* arg_name = "name";
+ unsigned char arg_type;
+ unsigned long long arg_value;
+ trace_event_internal::SetTraceValue(it->second, &arg_type, &arg_value);
logged_events_.push_back(
TraceEvent(it->first,
TimeTicks(), TRACE_EVENT_PHASE_METADATA,
- g_category_metadata, "thread_name", 0,
- "name", it->second,
- NULL, 0,
+ &g_category_enabled[g_category_metadata],
+ "thread_name", trace_event_internal::kNoEventId,
+ num_args, &arg_name, &arg_type, &arg_value,
TRACE_EVENT_FLAG_NONE));
+ }
}
}
@@ -716,38 +736,42 @@ void TraceLog::SetProcessID(int process_id) {
process_id_ = process_id;
// Create a FNV hash from the process ID for XORing.
// See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details.
- uint64 offset_basis = 14695981039346656037ull;
- uint64 fnv_prime = 1099511628211ull;
+ unsigned long long offset_basis = 14695981039346656037ull;
+ unsigned long long fnv_prime = 1099511628211ull;
unsigned long long pid = static_cast<unsigned long long>(process_id_);
process_id_hash_ = (offset_basis ^ pid) * fnv_prime;
}
-namespace internal {
+} // namespace debug
+} // namespace base
+
+namespace trace_event_internal {
-void TraceEndOnScopeClose::Initialize(const TraceCategory* category,
+void TraceEndOnScopeClose::Initialize(const unsigned char* category_enabled,
const char* name) {
- data_.category = category;
+ data_.category_enabled = category_enabled;
data_.name = name;
p_data_ = &data_;
}
void TraceEndOnScopeClose::AddEventIfEnabled() {
// Only called when p_data_ is non-null.
- if (p_data_->category->enabled) {
- base::debug::TraceLog::GetInstance()->AddTraceEvent(
+ if (*p_data_->category_enabled) {
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
TRACE_EVENT_PHASE_END,
- p_data_->category,
+ p_data_->category_enabled,
p_data_->name, kNoEventId,
- kNoArgName, kNoArgValue, kNoArgName, kNoArgValue,
+ kZeroNumArgs, NULL, NULL, NULL,
kNoThreshholdBeginId, kNoThresholdValue, TRACE_EVENT_FLAG_NONE);
}
}
-void TraceEndOnScopeCloseThreshold::Initialize(const TraceCategory* category,
- const char* name,
- int threshold_begin_id,
- int64 threshold) {
- data_.category = category;
+void TraceEndOnScopeCloseThreshold::Initialize(
+ const unsigned char* category_enabled,
+ const char* name,
+ int threshold_begin_id,
+ long long threshold) {
+ data_.category_enabled = category_enabled;
data_.name = name;
data_.threshold_begin_id = threshold_begin_id;
data_.threshold = threshold;
@@ -756,18 +780,15 @@ void TraceEndOnScopeCloseThreshold::Initialize(const TraceCategory* category,
void TraceEndOnScopeCloseThreshold::AddEventIfEnabled() {
// Only called when p_data_ is non-null.
- if (p_data_->category->enabled) {
- base::debug::TraceLog::GetInstance()->AddTraceEvent(
+ if (*p_data_->category_enabled) {
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
TRACE_EVENT_PHASE_END,
- p_data_->category,
+ p_data_->category_enabled,
p_data_->name, kNoEventId,
- kNoArgName, kNoArgValue, kNoArgName, kNoArgValue,
+ kZeroNumArgs, NULL, NULL, NULL,
p_data_->threshold_begin_id, p_data_->threshold,
TRACE_EVENT_FLAG_NONE);
}
}
-} // namespace internal
-
-} // namespace debug
-} // namespace base
+} // namespace trace_event_internal
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
index 444c975..a1fff3e 100644
--- a/base/debug/trace_event.h
+++ b/base/debug/trace_event.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -126,7 +126,7 @@
// the static variable is safe, as they will be serialized by the lock and
// multiple calls will return the same pointer to the category.
//
-// Then the category.enabled flag is checked. This is a volatile bool, and
+// Then the category_enabled flag is checked. This is a unsigned char, and
// not intended to be multithread safe. It optimizes access to AddTraceEvent
// which is threadsafe internally via TraceLog::lock_. The enabled flag may
// cause some threads to incorrectly call or skip calling AddTraceEvent near
@@ -160,9 +160,56 @@
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/timer.h"
+////////////////////////////////////////////////////////////////////////////////
+// TODO(jbates): split this into a separate header.
+// This header is designed to be give you trace_event macros without specifying
+// how the events actually get collected and stored. If you need to expose trace
+// event to some other universe, you can copy-and-paste this file and just
+// implement these API macros.
+
+// unsigned char*
+// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name)
+#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \
+ base::debug::TraceLog::GetCategoryEnabled
+
+// Returns the threshold_begin_id used by TRACE_IF_LONGER_THAN macros.
+// int TRACE_EVENT_API_ADD_TRACE_EVENT(
+// char phase,
+// const unsigned char* category_enabled,
+// const char* name,
+// unsigned long long id,
+// int num_args,
+// const char** arg_names,
+// const unsigned char* arg_types,
+// const unsigned long long* arg_values,
+// int threshold_begin_id,
+// long long threshold,
+// unsigned char flags)
+#define TRACE_EVENT_API_ADD_TRACE_EVENT \
+ base::debug::TraceLog::GetInstance()->AddTraceEvent
+
+// void TRACE_EVENT_API_ADD_COUNTER_EVENT(
+// const unsigned char* category_enabled,
+// const char* name,
+// unsigned long long id,
+// const char* arg1_name, int arg1_val,
+// const char* arg2_name, int arg2_val,
+// unsigned char flags)
+#define TRACE_EVENT_API_ADD_COUNTER_EVENT \
+ base::debug::TraceLog::GetInstance()->AddCounterEvent
+
+// Mangle |pointer| with a process ID hash so that if |pointer| occurs on more
+// than one process, it will not collide in the trace data.
+// unsigned long long TRACE_EVENT_API_GET_ID_FROM_POINTER(void* pointer)
+#define TRACE_EVENT_API_GET_ID_FROM_POINTER \
+ base::debug::TraceLog::GetInstance()->GetInterProcessID
+
+////////////////////////////////////////////////////////////////////////////////
+
// By default, const char* argument values are assumed to have long-lived scope
// and will not be copied. Use this macro to force a const char* to be copied.
-#define TRACE_STR_COPY(str) base::debug::TraceValue::StringWithCopy(str)
+#define TRACE_STR_COPY(str) \
+ trace_event_internal::TraceStringWithCopy(str)
// Older style trace macros with explicit id and extra data
// Only these macros result in publishing data to ETW as currently implemented.
@@ -187,12 +234,12 @@
// - category and name strings must have application lifetime (statics or
// literals). They may not include " chars.
#define TRACE_EVENT0(category, name) \
- TRACE_EVENT1(category, name, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name)
#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
- TRACE_EVENT2(category, name, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val)
#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
- INTERNAL_TRACE_EVENT_ADD_SCOPED( \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val)
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
// Same as TRACE_EVENT except that they are not included in official builds.
#ifdef OFFICIAL_BUILD
@@ -229,25 +276,27 @@
// - category and name strings must have application lifetime (statics or
// literals). They may not include " chars.
#define TRACE_EVENT_INSTANT0(category, name) \
- TRACE_EVENT_INSTANT1(category, name, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
- TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, \
- TRACE_EVENT_FLAG_NONE)
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
#define TRACE_EVENT_COPY_INSTANT0(category, name) \
- TRACE_EVENT_COPY_INSTANT1(category, name, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
- TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
- category, name, \
- arg1_name, base::debug::TraceValue::ForceCopy(arg1_val), \
- arg2_name, base::debug::TraceValue::ForceCopy(arg2_val), \
- TRACE_EVENT_FLAG_COPY)
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
// associated arguments. If the category is not enabled, then this
@@ -255,50 +304,54 @@
// - category and name strings must have application lifetime (statics or
// literals). They may not include " chars.
#define TRACE_EVENT_BEGIN0(category, name) \
- TRACE_EVENT_BEGIN1(category, name, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
- TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, \
- TRACE_EVENT_FLAG_NONE)
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
#define TRACE_EVENT_COPY_BEGIN0(category, name) \
- TRACE_EVENT_COPY_BEGIN1(category, name, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
- TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
- category, name, \
- arg1_name, base::debug::TraceValue::ForceCopy(arg1_val), \
- arg2_name, base::debug::TraceValue::ForceCopy(arg2_val), \
- TRACE_EVENT_FLAG_COPY)
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
// Records a single END event for "name" immediately. If the category
// is not enabled, then this does nothing.
// - category and name strings must have application lifetime (statics or
// literals). They may not include " chars.
#define TRACE_EVENT_END0(category, name) \
- TRACE_EVENT_END1(category, name, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
- TRACE_EVENT_END2(category, name, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, \
- TRACE_EVENT_FLAG_NONE)
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
#define TRACE_EVENT_COPY_END0(category, name) \
- TRACE_EVENT_COPY_END1(category, name, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
- TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
- category, name, \
- arg1_name, base::debug::TraceValue::ForceCopy(arg1_val), \
- arg2_name, base::debug::TraceValue::ForceCopy(arg2_val), \
- TRACE_EVENT_FLAG_COPY)
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
// Time threshold event:
// Only record the event if the duration is greater than the specified
@@ -309,15 +362,15 @@
// - category and name strings must have application lifetime (statics or
// literals). They may not include " chars.
#define TRACE_EVENT_IF_LONGER_THAN0(threshold_us, category, name) \
- TRACE_EVENT_IF_LONGER_THAN1(threshold_us, category, name, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_IF_LONGER_THAN(threshold_us, category, name)
#define TRACE_EVENT_IF_LONGER_THAN1( \
- threshold_us, category, name, arg1_name, arg1_val) \
- TRACE_EVENT_IF_LONGER_THAN2(threshold_us, category, name, \
- arg1_name, arg1_val, NULL, 0)
+ threshold_us, category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_IF_LONGER_THAN( \
+ threshold_us, category, name, arg1_name, arg1_val)
#define TRACE_EVENT_IF_LONGER_THAN2( \
threshold_us, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
- INTERNAL_TRACE_EVENT_ADD_SCOPED_IF_LONGER_THAN(threshold_us, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val)
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_IF_LONGER_THAN( \
+ threshold_us, category, name, arg1_name, arg1_val, arg2_name, arg2_val)
// Records the value of a counter called "name" immediately. Value
// must be representable as a 32 bit integer.
@@ -336,14 +389,14 @@
#define TRACE_COUNTER2(category, name, value1_name, value1_val, \
value2_name, value2_val) \
INTERNAL_TRACE_EVENT_ADD_COUNTER( \
- category, name, 0, value1_name, value1_val, value2_name, value2_val, \
+ category, name, trace_event_internal::kNoEventId, \
+ value1_name, value1_val, value2_name, value2_val, \
TRACE_EVENT_FLAG_NONE)
#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
value2_name, value2_val) \
INTERNAL_TRACE_EVENT_ADD_COUNTER( \
- category, name, 0, \
- value1_name, value1_val, \
- value2_name, value2_val, \
+ category, name, trace_event_internal::kNoEventId, \
+ value1_name, value1_val, value2_name, value2_val, \
TRACE_EVENT_FLAG_COPY)
// Records the value of a counter called "name" immediately. Value
@@ -392,48 +445,54 @@
// will be xored with a hash of the process ID so that the same pointer on
// two different processes will not collide.
#define TRACE_EVENT_START0(category, name, id) \
- TRACE_EVENT_START1(category, name, id, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID)
#define TRACE_EVENT_START1(category, name, id, arg1_name, arg1_val) \
- TRACE_EVENT_START2(category, name, id, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID, arg1_name, arg1_val)
#define TRACE_EVENT_START2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
- category, name, id, arg1_name, arg1_val, arg2_name, arg2_val, \
- TRACE_EVENT_FLAG_HAS_ID)
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT_COPY_START0(category, name, id) \
- TRACE_EVENT_COPY_START1(category, name, id, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_START1(category, name, id, arg1_name, arg1_val) \
- TRACE_EVENT_COPY_START2(category, name, id, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
#define TRACE_EVENT_COPY_START2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_START, \
- category, name, id, \
- arg1_name, base::debug::TraceValue::ForceCopy(arg1_val), \
- arg2_name, base::debug::TraceValue::ForceCopy(arg2_val), \
- TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_COPY)
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
// Records a single FINISH event for "name" immediately. If the category
// is not enabled, then this does nothing.
#define TRACE_EVENT_FINISH0(category, name, id) \
- TRACE_EVENT_FINISH1(category, name, id, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID)
#define TRACE_EVENT_FINISH1(category, name, id, arg1_name, arg1_val) \
- TRACE_EVENT_FINISH2(category, name, id, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID, arg1_name, arg1_val)
#define TRACE_EVENT_FINISH2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
- category, name, id, arg1_name, arg1_val, arg2_name, arg2_val, \
- TRACE_EVENT_FLAG_HAS_ID)
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT_COPY_FINISH0(category, name, id) \
- TRACE_EVENT_COPY_FINISH1(category, name, id, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_FINISH1(category, name, id, arg1_name, arg1_val) \
- TRACE_EVENT_COPY_FINISH2(category, name, id, arg1_name, arg1_val, NULL, 0)
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
#define TRACE_EVENT_COPY_FINISH2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FINISH, \
- category, name, id, \
- arg1_name, base::debug::TraceValue::ForceCopy(arg1_val), \
- arg2_name, base::debug::TraceValue::ForceCopy(arg2_val), \
- TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_COPY)
+ category, name, id, TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
// Implementation detail: trace event macros create temporary variables
@@ -449,23 +508,21 @@
// Implementation detail: internal macro to create static category.
// - ANNOTATE_BENIGN_RACE, see Thread Safety above.
#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \
- static const base::debug::TraceCategory* \
- INTERNAL_TRACE_EVENT_UID(catstatic) = NULL; \
+ static const unsigned char* INTERNAL_TRACE_EVENT_UID(catstatic) = NULL; \
ANNOTATE_BENIGN_RACE(&INTERNAL_TRACE_EVENT_UID(catstatic), \
"trace_event category"); \
if (!INTERNAL_TRACE_EVENT_UID(catstatic)) \
INTERNAL_TRACE_EVENT_UID(catstatic) = \
- base::debug::TraceLog::GetCategory(category);
+ TRACE_EVENT_API_GET_CATEGORY_ENABLED(category);
// Implementation detail: internal macro to create static category and add
// event if the category is enabled.
-#define INTERNAL_TRACE_EVENT_ADD( \
- phase, category, name, arg1_name, arg1_val, arg2_name, arg2_val, flags) \
+#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
- if (INTERNAL_TRACE_EVENT_UID(catstatic)->enabled) { \
- base::debug::TraceLog::GetInstance()->AddTraceEvent( \
- phase, INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, 0, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, flags); \
+ if (*INTERNAL_TRACE_EVENT_UID(catstatic)) { \
+ trace_event_internal::AddTraceEvent( \
+ phase, INTERNAL_TRACE_EVENT_UID(catstatic), name, \
+ trace_event_internal::kNoEventId, flags, ##__VA_ARGS__); \
}
// Implementation detail: internal macro to create static category and
@@ -473,26 +530,26 @@
#define INTERNAL_TRACE_EVENT_ADD_COUNTER( \
category, name, id, arg1_name, arg1_val, arg2_name, arg2_val, flags) \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
- if (INTERNAL_TRACE_EVENT_UID(catstatic)->enabled) { \
- base::debug::TraceLog::GetInstance()->AddCounterEvent( \
+ if (*INTERNAL_TRACE_EVENT_UID(catstatic)) { \
+ TRACE_EVENT_API_ADD_COUNTER_EVENT( \
INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, id, arg1_name, arg1_val, arg2_name, arg2_val, flags); \
+ name, trace_event_internal::TraceID(id).data(), \
+ arg1_name, arg1_val, arg2_name, arg2_val, flags); \
}
// Implementation detail: internal macro to create static category and add begin
// event if the category is enabled. Also adds the end event when the scope
// ends.
-#define INTERNAL_TRACE_EVENT_ADD_SCOPED( \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
- base::debug::internal::TraceEndOnScopeClose \
+ trace_event_internal::TraceEndOnScopeClose \
INTERNAL_TRACE_EVENT_UID(profileScope); \
- if (INTERNAL_TRACE_EVENT_UID(catstatic)->enabled) { \
- base::debug::TraceLog::GetInstance()->AddTraceEvent( \
+ if (*INTERNAL_TRACE_EVENT_UID(catstatic)) { \
+ trace_event_internal::AddTraceEvent( \
TRACE_EVENT_PHASE_BEGIN, \
INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, 0, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, \
- TRACE_EVENT_FLAG_NONE); \
+ name, trace_event_internal::kNoEventId, \
+ TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
INTERNAL_TRACE_EVENT_UID(profileScope).Initialize( \
INTERNAL_TRACE_EVENT_UID(catstatic), name); \
}
@@ -501,17 +558,17 @@
// event if the category is enabled. Also adds the end event when the scope
// ends. If the elapsed time is < threshold time, the begin/end pair is erased.
#define INTERNAL_TRACE_EVENT_ADD_SCOPED_IF_LONGER_THAN(threshold, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
+ category, name, ...) \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
- base::debug::internal::TraceEndOnScopeCloseThreshold \
+ trace_event_internal::TraceEndOnScopeCloseThreshold \
INTERNAL_TRACE_EVENT_UID(profileScope); \
- if (INTERNAL_TRACE_EVENT_UID(catstatic)->enabled) { \
+ if (*INTERNAL_TRACE_EVENT_UID(catstatic)) { \
int INTERNAL_TRACE_EVENT_UID(begin_event_id) = \
- base::debug::TraceLog::GetInstance()->AddTraceEvent( \
+ trace_event_internal::AddTraceEvent( \
TRACE_EVENT_PHASE_BEGIN, \
INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, 0, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, \
- TRACE_EVENT_FLAG_NONE); \
+ name, trace_event_internal::kNoEventId, \
+ TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
INTERNAL_TRACE_EVENT_UID(profileScope).Initialize( \
INTERNAL_TRACE_EVENT_UID(catstatic), name, \
INTERNAL_TRACE_EVENT_UID(begin_event_id), threshold); \
@@ -519,13 +576,14 @@
// Implementation detail: internal macro to create static category and add
// event if the category is enabled.
-#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, \
- arg1_name, arg1_val, arg2_name, arg2_val, flags) \
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
+ ...) \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
- if (INTERNAL_TRACE_EVENT_UID(catstatic)->enabled) { \
- base::debug::TraceLog::GetInstance()->AddTraceEvent( \
+ if (*INTERNAL_TRACE_EVENT_UID(catstatic)) { \
+ trace_event_internal::AddTraceEvent( \
phase, INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, id, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, flags); \
+ name, trace_event_internal::TraceID(id).data(), flags, \
+ ##__VA_ARGS__); \
}
template <typename Type>
@@ -537,173 +595,35 @@ class RefCountedString;
namespace debug {
-// Categories allow enabling/disabling of streams of trace events
-struct TraceCategory {
- const char* name;
- volatile bool enabled;
-};
+const int kTraceMaxNumArgs = 2;
-const size_t kTraceMaxNumArgs = 2;
+// Notes regarding the following definitions:
+// New values can be added and propagated to third party libraries, but existing
+// definitions must never be changed, because third party libraries may use old
+// definitions.
// Phase indicates the nature of an event entry. E.g. part of a begin/end pair.
-typedef char TraceEventPhase;
-#define TRACE_EVENT_PHASE_BEGIN (base::debug::TraceEventPhase('B'))
-#define TRACE_EVENT_PHASE_END (base::debug::TraceEventPhase('E'))
-#define TRACE_EVENT_PHASE_INSTANT (base::debug::TraceEventPhase('I'))
-#define TRACE_EVENT_PHASE_START (base::debug::TraceEventPhase('S'))
-#define TRACE_EVENT_PHASE_FINISH (base::debug::TraceEventPhase('F'))
-#define TRACE_EVENT_PHASE_METADATA (base::debug::TraceEventPhase('M'))
-#define TRACE_EVENT_PHASE_COUNTER (base::debug::TraceEventPhase('C'))
-
-typedef uint8 TraceEventFlags;
-#define TRACE_EVENT_FLAG_NONE (base::debug::TraceEventFlags(0))
-#define TRACE_EVENT_FLAG_COPY (base::debug::TraceEventFlags(1<<0))
-#define TRACE_EVENT_FLAG_HAS_ID (base::debug::TraceEventFlags(1<<1))
-
-// Simple union of values. This is much lighter weight than base::Value, which
-// requires dynamic allocation and a vtable. To keep the trace runtime overhead
-// low, we want constant size storage here.
-class BASE_EXPORT TraceValue {
- public:
- enum Type {
- TRACE_TYPE_UNDEFINED,
- TRACE_TYPE_BOOL,
- TRACE_TYPE_UINT,
- TRACE_TYPE_INT,
- TRACE_TYPE_DOUBLE,
- TRACE_TYPE_POINTER,
- TRACE_TYPE_STRING,
- TRACE_TYPE_STATIC_STRING
- };
-
- TraceValue() : type_(TRACE_TYPE_UNDEFINED) {
- value_.as_uint = 0ull;
- }
- TraceValue(bool rhs) : type_(TRACE_TYPE_BOOL) {
- value_.as_bool = rhs;
- }
- TraceValue(uint64 rhs) : type_(TRACE_TYPE_UINT) {
- value_.as_uint = rhs;
- }
- TraceValue(uint32 rhs) : type_(TRACE_TYPE_UINT) {
- value_.as_uint = rhs;
- }
- TraceValue(uint16 rhs) : type_(TRACE_TYPE_UINT) {
- value_.as_uint = rhs;
- }
- TraceValue(uint8 rhs) : type_(TRACE_TYPE_UINT) {
- value_.as_uint = rhs;
- }
- TraceValue(int64 rhs) : type_(TRACE_TYPE_INT) {
- value_.as_int = rhs;
- }
- TraceValue(int32 rhs) : type_(TRACE_TYPE_INT) {
- value_.as_int = rhs;
- }
- TraceValue(int16 rhs) : type_(TRACE_TYPE_INT) {
- value_.as_int = rhs;
- }
- TraceValue(int8 rhs) : type_(TRACE_TYPE_INT) {
- value_.as_int = rhs;
- }
- TraceValue(double rhs) : type_(TRACE_TYPE_DOUBLE) {
- value_.as_double = rhs;
- }
- TraceValue(const void* rhs) : type_(TRACE_TYPE_POINTER) {
- value_.as_pointer = rhs;
- }
- TraceValue(const std::string& rhs) : type_(TRACE_TYPE_STRING) {
- value_.as_string = rhs.c_str();
- }
- TraceValue(const char* rhs) : type_(TRACE_TYPE_STATIC_STRING) {
- value_.as_string = rhs;
- }
-
- static TraceValue StringWithCopy(const char* rhs) {
- TraceValue value(rhs);
- if (rhs)
- value.type_ = TRACE_TYPE_STRING;
- return value;
- }
-
- static TraceValue ForceCopy(const TraceValue& rhs) {
- TraceValue value(rhs);
- if (value.type_ == TRACE_TYPE_STATIC_STRING && value.as_string())
- value.type_ = TRACE_TYPE_STRING;
- return value;
- }
-
- bool is_string() const {
- return type_ == TRACE_TYPE_STRING || type_ == TRACE_TYPE_STATIC_STRING;
- }
-
- void AppendAsJSON(std::string* out) const;
-
- Type type() const {
- return type_;
- }
- uint64 as_uint() const {
- DCHECK_EQ(TRACE_TYPE_UINT, type_);
- return value_.as_uint;
- }
- bool as_bool() const {
- DCHECK_EQ(TRACE_TYPE_BOOL, type_);
- return value_.as_bool;
- }
- int64 as_int() const {
- DCHECK_EQ(TRACE_TYPE_INT, type_);
- return value_.as_int;
- }
- double as_double() const {
- DCHECK_EQ(TRACE_TYPE_DOUBLE, type_);
- return value_.as_double;
- }
- const void* as_pointer() const {
- DCHECK_EQ(TRACE_TYPE_POINTER, type_);
- return value_.as_pointer;
- }
- const char* as_string() const {
- DCHECK(is_string());
- return value_.as_string;
- }
- const char** as_assignable_string() {
- DCHECK_EQ(TRACE_TYPE_STRING, type_);
- return &value_.as_string;
- }
-
- private:
- union Value {
- bool as_bool;
- uint64 as_uint;
- int64 as_int;
- double as_double;
- const void* as_pointer;
- const char* as_string;
- };
-
- Type type_;
- Value value_;
-};
-
-// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
-// are mangled with the Process ID so that they are unlikely to collide when the
-// same pointer is used on different processes.
-class BASE_EXPORT TraceID {
- public:
- TraceID() : data_(0u) {}
- TraceID(void* rhs);
- TraceID(unsigned long long rhs) : data_(static_cast<uint64>(rhs)) {}
- TraceID(unsigned long rhs) : data_(static_cast<uint64>(rhs)) {}
- TraceID(unsigned int rhs) : data_(static_cast<uint64>(rhs)) {}
- TraceID(long long rhs) : data_(static_cast<uint64>(rhs)) {}
- TraceID(long rhs) : data_(static_cast<uint64>(rhs)) {}
- TraceID(int rhs) : data_(static_cast<uint64>(rhs)) {}
-
- uint64 data() const { return data_; }
-
- private:
- uint64 data_;
-};
+#define TRACE_EVENT_PHASE_BEGIN ('B')
+#define TRACE_EVENT_PHASE_END ('E')
+#define TRACE_EVENT_PHASE_INSTANT ('I')
+#define TRACE_EVENT_PHASE_START ('S')
+#define TRACE_EVENT_PHASE_FINISH ('F')
+#define TRACE_EVENT_PHASE_METADATA ('M')
+#define TRACE_EVENT_PHASE_COUNTER ('C')
+
+// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
+#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0))
+#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1<<0))
+#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1<<1))
+
+// Type values for identifying types in the TraceValue union.
+#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
+#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
+#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
+#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
+#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
+#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
+#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
// Output records are "Events" and can be obtained via the
// OutputCallback whenever the tracing system decides to flush. This
@@ -711,26 +631,29 @@ class BASE_EXPORT TraceID {
// force it to happen.
class BASE_EXPORT TraceEvent {
public:
+ union TraceValue {
+ bool as_bool;
+ unsigned long long as_uint;
+ long long as_int;
+ double as_double;
+ const void* as_pointer;
+ const char* as_string;
+ };
+
TraceEvent();
TraceEvent(int thread_id,
TimeTicks timestamp,
- TraceEventPhase phase,
- const TraceCategory* category,
+ char phase,
+ const unsigned char* category_enabled,
const char* name,
- TraceID id,
- const char* arg1_name, const TraceValue& arg1_val,
- const char* arg2_name, const TraceValue& arg2_val,
- TraceEventFlags flags);
+ unsigned long long id,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
+ unsigned char flags);
~TraceEvent();
- static char GetPhaseChar(TraceEventPhase phase) {
- return static_cast<char>(phase);
- }
-
- static TraceEventPhase GetPhase(const char* phase) {
- return static_cast<TraceEventPhase>(*phase);
- }
-
// Serialize event data to JSON
static void AppendEventsAsJSON(const std::vector<TraceEvent>& events,
size_t start,
@@ -752,15 +675,16 @@ class BASE_EXPORT TraceEvent {
// Note: these are ordered by size (largest first) for optimal packing.
TimeTicks timestamp_;
// id_ can be used to store phase-specific data.
- TraceID id_;
+ unsigned long long id_;
TraceValue arg_values_[kTraceMaxNumArgs];
const char* arg_names_[kTraceMaxNumArgs];
- const TraceCategory* category_;
+ const unsigned char* category_enabled_;
const char* name_;
scoped_refptr<base::RefCountedString> parameter_copy_storage_;
int thread_id_;
- TraceEventPhase phase_;
- TraceEventFlags flags_;
+ char phase_;
+ unsigned char flags_;
+ unsigned char arg_types_[kTraceMaxNumArgs];
};
@@ -870,7 +794,8 @@ class BASE_EXPORT TraceLog {
void Flush();
// Called by TRACE_EVENT* macros, don't call this directly.
- static const TraceCategory* GetCategory(const char* name);
+ static const unsigned char* GetCategoryEnabled(const char* name);
+ static const char* GetCategoryName(const unsigned char* category_enabled);
// Called by TRACE_EVENT* macros, don't call this directly.
// Returns the index in the internal vector of the event if it was added, or
@@ -880,36 +805,41 @@ class BASE_EXPORT TraceLog {
// is less than the threshold, the begin/end event pair is dropped.
// If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied
// into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above.
- int AddTraceEvent(TraceEventPhase phase,
- const TraceCategory* category,
+ int AddTraceEvent(char phase,
+ const unsigned char* category_enabled,
const char* name,
- TraceID id,
- const char* arg1_name, TraceValue arg1_val,
- const char* arg2_name, TraceValue arg2_val,
+ unsigned long long id,
+ int num_args,
+ const char** arg_names,
+ const unsigned char* arg_types,
+ const unsigned long long* arg_values,
int threshold_begin_id,
- int64 threshold,
- TraceEventFlags flags);
- static void AddTraceEventEtw(TraceEventPhase phase,
+ long long threshold,
+ unsigned char flags);
+ static void AddTraceEventEtw(char phase,
const char* name,
const void* id,
const char* extra);
- static void AddTraceEventEtw(TraceEventPhase phase,
+ static void AddTraceEventEtw(char phase,
const char* name,
const void* id,
const std::string& extra);
// A wrapper around AddTraceEvent used by TRACE_COUNTERx macros
// that allows only integer values for the counters.
- int AddCounterEvent(const TraceCategory* category,
- const char* name,
- TraceID id,
- const char* arg1_name, int32 arg1_val,
- const char* arg2_name, int32 arg2_val,
- TraceEventFlags flags);
-
- // Mangle |id| with a hash based on the process ID so that if |id| occurs on
+ void AddCounterEvent(const unsigned char* category_enabled,
+ const char* name,
+ unsigned long long id,
+ const char* arg1_name, int arg1_val,
+ const char* arg2_name, int arg2_val,
+ unsigned char flags);
+
+ // Mangle |ptr| with a hash based on the process ID so that if |ptr| occurs on
// more than one process, it will not collide.
- uint64 GetIntraProcessID(uint64 id) const { return id ^ process_id_hash_; }
+ unsigned long long GetInterProcessID(void* ptr) const {
+ return static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(ptr)) ^
+ process_id_hash_;
+ }
int process_id() const { return process_id_; }
@@ -937,7 +867,7 @@ class BASE_EXPORT TraceLog {
TraceLog();
~TraceLog();
- const TraceCategory* GetCategoryInternal(const char* name);
+ const unsigned char* GetCategoryEnabledInternal(const char* name);
void AddThreadNameMetadataEvents();
void AddClockSyncMetadataEvents();
@@ -954,14 +884,180 @@ class BASE_EXPORT TraceLog {
base::hash_map<int, std::string> thread_names_;
// XORed with TraceID to make it unlikely to collide with other processes.
- uint64 process_id_hash_;
+ unsigned long long process_id_hash_;
int process_id_;
DISALLOW_COPY_AND_ASSIGN(TraceLog);
};
-namespace internal {
+} // namespace debug
+} // namespace base
+
+namespace trace_event_internal {
+
+// Specify these values when the corresponding argument of AddTraceEvent is not
+// used.
+const int kZeroNumArgs = 0;
+const int kNoThreshholdBeginId = -1;
+const long long kNoThresholdValue = 0;
+const unsigned long long kNoEventId = 0;
+
+// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
+// are mangled with the Process ID so that they are unlikely to collide when the
+// same pointer is used on different processes.
+class BASE_EXPORT TraceID {
+ public:
+ explicit TraceID(void* rhs) :
+ data_(TRACE_EVENT_API_GET_ID_FROM_POINTER(rhs)) {}
+ explicit TraceID(unsigned long long rhs) : data_(rhs) {}
+ explicit TraceID(unsigned long rhs) : data_(rhs) {}
+ explicit TraceID(unsigned int rhs) : data_(rhs) {}
+ explicit TraceID(unsigned short rhs) : data_(rhs) {}
+ explicit TraceID(unsigned char rhs) : data_(rhs) {}
+ explicit TraceID(long long rhs) :
+ data_(static_cast<unsigned long long>(rhs)) {}
+ explicit TraceID(long rhs) : data_(static_cast<unsigned long long>(rhs)) {}
+ explicit TraceID(int rhs) : data_(static_cast<unsigned long long>(rhs)) {}
+ explicit TraceID(short rhs) : data_(static_cast<unsigned long long>(rhs)) {}
+ explicit TraceID(signed char rhs) :
+ data_(static_cast<unsigned long long>(rhs)) {}
+
+ unsigned long long data() const { return data_; }
+
+ private:
+ unsigned long long data_;
+};
+
+// Simple union to store various types as unsigned long long.
+union TraceValueUnion {
+ bool as_bool;
+ unsigned long long as_uint;
+ long long as_int;
+ double as_double;
+ const void* as_pointer;
+ const char* as_string;
+};
+
+// Simple container for const char* that should be copied instead of retained.
+class TraceStringWithCopy {
+ public:
+ explicit TraceStringWithCopy(const char* str) : str_(str) {}
+ operator const char* () const { return str_; }
+ private:
+ const char* str_;
+};
+
+// Define SetTraceValue for each allowed type. It stores the type and
+// value in the return arguments. This allows this API to avoid declaring any
+// structures so that it is portable to third_party libraries.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
+ union_member, \
+ value_type_id) \
+ static inline void SetTraceValue(actual_type arg, \
+ unsigned char* type, \
+ unsigned long long* value) { \
+ TraceValueUnion type_value; \
+ type_value.union_member = arg; \
+ *type = value_type_id; \
+ *value = type_value.as_uint; \
+ }
+// Simpler form for int types that can be safely casted.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
+ value_type_id) \
+ static inline void SetTraceValue(actual_type arg, \
+ unsigned char* type, \
+ unsigned long long* value) { \
+ *type = value_type_id; \
+ *value = static_cast<unsigned long long>(arg); \
+ }
+
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE(bool, as_bool, TRACE_VALUE_TYPE_BOOL)
+INTERNAL_DECLARE_SET_TRACE_VALUE(double, as_double, TRACE_VALUE_TYPE_DOUBLE)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, as_pointer,
+ TRACE_VALUE_TYPE_POINTER)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, as_string,
+ TRACE_VALUE_TYPE_STRING)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, as_string,
+ TRACE_VALUE_TYPE_COPY_STRING)
+
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
+
+// std::string version of SetTraceValue so that trace arguments can be strings.
+static inline void SetTraceValue(const std::string& arg,
+ unsigned char* type,
+ unsigned long long* value) {
+ TraceValueUnion type_value;
+ type_value.as_string = arg.c_str();
+ *type = TRACE_VALUE_TYPE_COPY_STRING;
+ *value = type_value.as_uint;
+}
+
+// These AddTraceEvent template functions are defined here instead of in the
+// macro, because the arg_values could be temporary objects, such as
+// std::string. In order to store pointers to the internal c_str and pass
+// through to the tracing API, the arg_values must live throughout
+// these procedures.
+
+static inline int AddTraceEvent(char phase,
+ const unsigned char* category_enabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags) {
+ return TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, category_enabled, name, id,
+ kZeroNumArgs, NULL, NULL, NULL,
+ kNoThreshholdBeginId, kNoThresholdValue, flags);
+}
+
+template<class ARG1_TYPE>
+static inline int AddTraceEvent(char phase,
+ const unsigned char* category_enabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags,
+ const char* arg1_name,
+ const ARG1_TYPE& arg1_val) {
+ const int num_args = 1;
+ unsigned char arg_types[1];
+ unsigned long long arg_values[1];
+ SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
+ return TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, category_enabled, name, id,
+ num_args, &arg1_name, arg_types, arg_values,
+ kNoThreshholdBeginId, kNoThresholdValue, flags);
+}
+
+template<class ARG1_TYPE, class ARG2_TYPE>
+static inline int AddTraceEvent(char phase,
+ const unsigned char* category_enabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags,
+ const char* arg1_name,
+ const ARG1_TYPE& arg1_val,
+ const char* arg2_name,
+ const ARG2_TYPE& arg2_val) {
+ const int num_args = 2;
+ const char* arg_names[2] = { arg1_name, arg2_name };
+ unsigned char arg_types[2];
+ unsigned long long arg_values[2];
+ SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
+ SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
+ return TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, category_enabled, name, id,
+ num_args, arg_names, arg_types, arg_values,
+ kNoThreshholdBeginId, kNoThresholdValue, flags);
+}
// Used by TRACE_EVENTx macro. Do not use directly.
class BASE_EXPORT TraceEndOnScopeClose {
@@ -973,7 +1069,7 @@ class BASE_EXPORT TraceEndOnScopeClose {
AddEventIfEnabled();
}
- void Initialize(const TraceCategory* category,
+ void Initialize(const unsigned char* category_enabled,
const char* name);
private:
@@ -986,7 +1082,7 @@ class BASE_EXPORT TraceEndOnScopeClose {
// members of this class instead, compiler warnings occur about potential
// uninitialized accesses.
struct Data {
- const TraceCategory* category;
+ const unsigned char* category_enabled;
const char* name;
};
Data* p_data_;
@@ -1005,10 +1101,10 @@ class BASE_EXPORT TraceEndOnScopeCloseThreshold {
// Called by macros only when tracing is enabled at the point when the begin
// event is added.
- void Initialize(const TraceCategory* category,
+ void Initialize(const unsigned char* category_enabled,
const char* name,
int threshold_begin_id,
- int64 threshold);
+ long long threshold);
private:
// Add the end event if the category is still enabled.
@@ -1020,8 +1116,8 @@ class BASE_EXPORT TraceEndOnScopeCloseThreshold {
// members of this class instead, compiler warnings occur about potential
// uninitialized accesses.
struct Data {
- int64 threshold;
- const TraceCategory* category;
+ long long threshold;
+ const unsigned char* category_enabled;
const char* name;
int threshold_begin_id;
};
@@ -1029,9 +1125,6 @@ class BASE_EXPORT TraceEndOnScopeCloseThreshold {
Data data_;
};
-} // namespace internal
-
-} // namespace debug
-} // namespace base
+} // namespace trace_event_internal
#endif // BASE_DEBUG_TRACE_EVENT_H_
diff --git a/base/debug/trace_event_unittest.cc b/base/debug/trace_event_unittest.cc
index cb77fee..8486f90 100644
--- a/base/debug/trace_event_unittest.cc
+++ b/base/debug/trace_event_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -99,6 +99,10 @@ void TraceEventTestFixture::OnTraceDataCollected(
scoped_ptr<Value> root;
root.reset(base::JSONReader::Read(json_output_.json_output, false));
+ if (!root.get()) {
+ LOG(ERROR) << json_output_.json_output;
+ }
+
ListValue* root_list = NULL;
ASSERT_TRUE(root.get());
ASSERT_TRUE(root->GetAsList(&root_list));
@@ -310,6 +314,34 @@ void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
"name1", "value1",
"name2", "value2");
+ TRACE_EVENT_IF_LONGER_THAN0(0, "all", "TRACE_EVENT_IF_LONGER_THAN0 call");
+ TRACE_EVENT_IF_LONGER_THAN1(0, "all", "TRACE_EVENT_IF_LONGER_THAN1 call",
+ "name1", "value1");
+ TRACE_EVENT_IF_LONGER_THAN2(0, "all", "TRACE_EVENT_IF_LONGER_THAN2 call",
+ "name1", "value1",
+ "name2", "value2");
+
+ TRACE_EVENT_START0("all", "TRACE_EVENT_START0 call", 5);
+ TRACE_EVENT_START1("all", "TRACE_EVENT_START1 call", 5,
+ "name1", "value1");
+ TRACE_EVENT_START2("all", "TRACE_EVENT_START2 call", 5,
+ "name1", "value1",
+ "name2", "value2");
+
+ TRACE_EVENT_FINISH0("all", "TRACE_EVENT_FINISH0 call", 5);
+ TRACE_EVENT_FINISH1("all", "TRACE_EVENT_FINISH1 call", 5,
+ "name1", "value1");
+ TRACE_EVENT_FINISH2("all", "TRACE_EVENT_FINISH2 call", 5,
+ "name1", "value1",
+ "name2", "value2");
+
+ TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW0 call", 5, NULL);
+ TRACE_EVENT_BEGIN_ETW("TRACE_EVENT_BEGIN_ETW1 call", 5, "value");
+ TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW0 call", 5, NULL);
+ TRACE_EVENT_END_ETW("TRACE_EVENT_END_ETW1 call", 5, "value");
+ TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW0 call", 5, NULL);
+ TRACE_EVENT_INSTANT_ETW("TRACE_EVENT_INSTANT_ETW1 call", 5, "value");
+
TRACE_COUNTER1("all", "TRACE_COUNTER1 call", 31415);
TRACE_COUNTER2("all", "TRACE_COUNTER2 call",
"a", 30000,
@@ -358,33 +390,117 @@ void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) {
EXPECT_EQ("E", ph_end);
}
EXPECT_FIND_("TRACE_EVENT1 call");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
EXPECT_FIND_("TRACE_EVENT2 call");
EXPECT_SUB_FIND_("name1");
EXPECT_SUB_FIND_("\"value1\"");
EXPECT_SUB_FIND_("name2");
EXPECT_SUB_FIND_("value\\2");
+
EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
EXPECT_SUB_FIND_("name1");
EXPECT_SUB_FIND_("value1");
EXPECT_SUB_FIND_("name2");
EXPECT_SUB_FIND_("value2");
+
EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
EXPECT_SUB_FIND_("name1");
EXPECT_SUB_FIND_("value1");
EXPECT_SUB_FIND_("name2");
EXPECT_SUB_FIND_("value2");
+
EXPECT_FIND_("TRACE_EVENT_END0 call");
EXPECT_FIND_("TRACE_EVENT_END1 call");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
EXPECT_FIND_("TRACE_EVENT_END2 call");
EXPECT_SUB_FIND_("name1");
EXPECT_SUB_FIND_("value1");
EXPECT_SUB_FIND_("name2");
EXPECT_SUB_FIND_("value2");
+ EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN0 call");
+ EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN1 call");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
+ EXPECT_FIND_("TRACE_EVENT_IF_LONGER_THAN2 call");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
+ EXPECT_SUB_FIND_("name2");
+ EXPECT_SUB_FIND_("value2");
+
+ EXPECT_FIND_("TRACE_EVENT_START0 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_FIND_("TRACE_EVENT_START1 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
+ EXPECT_FIND_("TRACE_EVENT_START2 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
+ EXPECT_SUB_FIND_("name2");
+ EXPECT_SUB_FIND_("value2");
+
+ EXPECT_FIND_("TRACE_EVENT_FINISH0 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_FIND_("TRACE_EVENT_FINISH1 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
+ EXPECT_FIND_("TRACE_EVENT_FINISH2 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("name1");
+ EXPECT_SUB_FIND_("value1");
+ EXPECT_SUB_FIND_("name2");
+ EXPECT_SUB_FIND_("value2");
+
+ EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW0 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("extra");
+ EXPECT_SUB_FIND_("NULL");
+ EXPECT_FIND_("TRACE_EVENT_BEGIN_ETW1 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("extra");
+ EXPECT_SUB_FIND_("value");
+ EXPECT_FIND_("TRACE_EVENT_END_ETW0 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("extra");
+ EXPECT_SUB_FIND_("NULL");
+ EXPECT_FIND_("TRACE_EVENT_END_ETW1 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("extra");
+ EXPECT_SUB_FIND_("value");
+ EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW0 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("extra");
+ EXPECT_SUB_FIND_("NULL");
+ EXPECT_FIND_("TRACE_EVENT_INSTANT_ETW1 call");
+ EXPECT_SUB_FIND_("id");
+ EXPECT_SUB_FIND_("5");
+ EXPECT_SUB_FIND_("extra");
+ EXPECT_SUB_FIND_("value");
+
EXPECT_FIND_("TRACE_COUNTER1 call");
{
std::string ph;
diff --git a/base/debug/trace_event_win.cc b/base/debug/trace_event_win.cc
index bba4713..d5a21f4 100644
--- a/base/debug/trace_event_win.cc
+++ b/base/debug/trace_event_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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_win.h"
@@ -42,7 +42,7 @@ bool TraceEventETWProvider::StartTracing() {
void TraceEventETWProvider::TraceEvent(const char* name,
size_t name_len,
- TraceEventPhase type,
+ char type,
const void* id,
const char* extra,
size_t extra_len) {
@@ -96,7 +96,7 @@ void TraceEventETWProvider::TraceEvent(const char* name,
void TraceEventETWProvider::Trace(const char* name,
size_t name_len,
- TraceEventPhase type,
+ char type,
const void* id,
const char* extra,
size_t extra_len) {
diff --git a/base/debug/trace_event_win.h b/base/debug/trace_event_win.h
index 7d66393..3da95ea 100644
--- a/base/debug/trace_event_win.h
+++ b/base/debug/trace_event_win.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -37,14 +37,14 @@ class BASE_EXPORT TraceEventETWProvider : public base::win::EtwTraceProvider {
// be used for length.
static void Trace(const char* name,
size_t name_len,
- TraceEventPhase type,
+ char type,
const void* id,
const char* extra,
size_t extra_len);
// Allows passing extra as a std::string for convenience.
static void Trace(const char* name,
- TraceEventPhase type,
+ char type,
const void* id,
const std::string& extra) {
return Trace(name, -1, type, id, extra.c_str(), extra.length());
@@ -53,7 +53,7 @@ class BASE_EXPORT TraceEventETWProvider : public base::win::EtwTraceProvider {
// Allows passing extra as a const char* to avoid constructing temporary
// std::string instances where not needed.
static void Trace(const char* name,
- TraceEventPhase type,
+ char type,
const void* id,
const char* extra) {
return Trace(name, -1, type, id, extra, -1);
@@ -75,7 +75,7 @@ class BASE_EXPORT TraceEventETWProvider : public base::win::EtwTraceProvider {
// string will be used.
void TraceEvent(const char* name,
size_t name_len,
- TraceEventPhase type,
+ char type,
const void* id,
const char* extra,
size_t extra_len);
diff --git a/base/test/trace_event_analyzer.cc b/base/test/trace_event_analyzer.cc
index 1341cc0..7aba0be 100644
--- a/base/test/trace_event_analyzer.cc
+++ b/base/test/trace_event_analyzer.cc
@@ -41,7 +41,7 @@ bool TraceEvent::SetFromJSON(const base::Value* event_value) {
return false;
}
- phase = base::debug::TraceEvent::GetPhase(phase_str.c_str());
+ phase = *phase_str.data();
bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA);
bool require_id = (phase == TRACE_EVENT_PHASE_START ||
@@ -229,7 +229,7 @@ Query Query::Bool(bool boolean) {
return Query(boolean ? 1.0 : 0.0);
}
-Query Query::Phase(base::debug::TraceEventPhase phase) {
+Query Query::Phase(char phase) {
return Query(static_cast<double>(phase));
}
@@ -268,17 +268,17 @@ bool Query::Evaluate(const TraceEvent& event) const {
else if (CompareAsString(event, &compare_result))
return compare_result;
return false;
- } else {
- switch (operator_) {
- case OP_AND:
- return left().Evaluate(event) && right().Evaluate(event);
- case OP_OR:
- return left().Evaluate(event) || right().Evaluate(event);
- case OP_NOT:
- return !left().Evaluate(event);
- default:
- NOTREACHED();
- }
+ }
+ // It's a logical operator.
+ switch (operator_) {
+ case OP_AND:
+ return left().Evaluate(event) && right().Evaluate(event);
+ case OP_OR:
+ return left().Evaluate(event) || right().Evaluate(event);
+ case OP_NOT:
+ return !left().Evaluate(event);
+ default:
+ NOTREACHED();
}
NOTREACHED();
@@ -393,17 +393,11 @@ bool Query::EvaluateArithmeticOperator(const TraceEvent& event,
}
bool Query::GetAsDouble(const TraceEvent& event, double* num) const {
- base::debug::TraceValue value;
switch (type_) {
case QUERY_ARITHMETIC_OPERATOR:
return EvaluateArithmeticOperator(event, num);
case QUERY_EVENT_MEMBER:
- value = GetMemberValue(event);
- if (value.type() == base::debug::TraceValue::TRACE_TYPE_DOUBLE) {
- *num = value.as_double();
- return true;
- }
- return false;
+ return GetMemberValueAsDouble(event, num);
case QUERY_NUMBER:
*num = number_;
return true;
@@ -413,15 +407,9 @@ bool Query::GetAsDouble(const TraceEvent& event, double* num) const {
}
bool Query::GetAsString(const TraceEvent& event, std::string* str) const {
- base::debug::TraceValue value;
switch (type_) {
case QUERY_EVENT_MEMBER:
- value = GetMemberValue(event);
- if (value.is_string()) {
- *str = value.as_string();
- return true;
- }
- return false;
+ return GetMemberValueAsString(event, str);
case QUERY_STRING:
*str = string_;
return true;
@@ -430,7 +418,8 @@ bool Query::GetAsString(const TraceEvent& event, std::string* str) const {
}
}
-base::debug::TraceValue Query::GetMemberValue(const TraceEvent& event) const {
+bool Query::GetMemberValueAsDouble(const TraceEvent& event,
+ double* num) const {
DCHECK(type_ == QUERY_EVENT_MEMBER);
// This could be a request for a member of |event| or a member of |event|'s
@@ -440,69 +429,96 @@ base::debug::TraceValue Query::GetMemberValue(const TraceEvent& event) const {
// Request for member of associated event, but there is no associated event.
if (!the_event)
- return base::debug::TraceValue();
+ return false;
switch (member_) {
case EVENT_PID:
case OTHER_PID:
- return static_cast<double>(the_event->thread.process_id);
+ *num = static_cast<double>(the_event->thread.process_id);
+ return true;
case EVENT_TID:
case OTHER_TID:
- return static_cast<double>(the_event->thread.thread_id);
+ *num = static_cast<double>(the_event->thread.thread_id);
+ return true;
case EVENT_TIME:
case OTHER_TIME:
- return the_event->timestamp;
+ *num = the_event->timestamp;
+ return true;
case EVENT_DURATION:
- {
- if (the_event->has_other_event())
- return the_event->GetAbsTimeToOtherEvent();
- else
- return base::debug::TraceValue();
+ if (the_event->has_other_event()) {
+ *num = the_event->GetAbsTimeToOtherEvent();
+ return true;
}
+ return false;
case EVENT_PHASE:
case OTHER_PHASE:
- return static_cast<double>(the_event->phase);
- case EVENT_CATEGORY:
- case OTHER_CATEGORY:
- return the_event->category;
- case EVENT_NAME:
- case OTHER_NAME:
- return the_event->name;
- case EVENT_ID:
- case OTHER_ID:
- return the_event->id;
+ *num = static_cast<double>(the_event->phase);
+ return true;
case EVENT_HAS_STRING_ARG:
case OTHER_HAS_STRING_ARG:
- return (the_event->HasStringArg(string_) ? 1.0 : 0.0);
+ *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0);
+ return true;
case EVENT_HAS_NUMBER_ARG:
case OTHER_HAS_NUMBER_ARG:
- return (the_event->HasNumberArg(string_) ? 1.0 : 0.0);
+ *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0);
+ return true;
case EVENT_ARG:
- case OTHER_ARG:
- {
- // Search for the argument name and return its value if found.
+ case OTHER_ARG: {
+ // Search for the argument name and return its value if found.
+ std::map<std::string, double>::const_iterator num_i =
+ the_event->arg_numbers.find(string_);
+ if (num_i == the_event->arg_numbers.end())
+ return false;
+ *num = num_i->second;
+ return true;
+ }
+ case EVENT_HAS_OTHER:
+ // return 1.0 (true) if the other event exists
+ *num = event.other_event ? 1.0 : 0.0;
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Query::GetMemberValueAsString(const TraceEvent& event,
+ std::string* str) const {
+ DCHECK(type_ == QUERY_EVENT_MEMBER);
- std::map<std::string, std::string>::const_iterator str_i =
- the_event->arg_strings.find(string_);
- if (str_i != the_event->arg_strings.end())
- return str_i->second;
+ // This could be a request for a member of |event| or a member of |event|'s
+ // associated event. Store the target event in the_event:
+ const TraceEvent* the_event = (member_ < OTHER_PID) ?
+ &event : event.other_event;
- std::map<std::string, double>::const_iterator num_i =
- the_event->arg_numbers.find(string_);
- if (num_i != the_event->arg_numbers.end())
- return num_i->second;
+ // Request for member of associated event, but there is no associated event.
+ if (!the_event)
+ return false;
- return base::debug::TraceValue();
- }
- case EVENT_HAS_OTHER:
- {
- // return 1.0 (true) if the other event exists
- double result = event.other_event ? 1.0 : 0.0;
- return result;
- }
+ switch (member_) {
+ case EVENT_CATEGORY:
+ case OTHER_CATEGORY:
+ *str = the_event->category;
+ return true;
+ case EVENT_NAME:
+ case OTHER_NAME:
+ *str = the_event->name;
+ return true;
+ case EVENT_ID:
+ case OTHER_ID:
+ *str = the_event->id;
+ return true;
+ case EVENT_ARG:
+ case OTHER_ARG: {
+ // Search for the argument name and return its value if found.
+ std::map<std::string, std::string>::const_iterator str_i =
+ the_event->arg_strings.find(string_);
+ if (str_i == the_event->arg_strings.end())
+ return false;
+ *str = str_i->second;
+ return true;
+ }
default:
- NOTREACHED();
- return base::debug::TraceValue();
+ return false;
}
}
diff --git a/base/test/trace_event_analyzer.h b/base/test/trace_event_analyzer.h
index 949721b..4817ec8 100644
--- a/base/test/trace_event_analyzer.h
+++ b/base/test/trace_event_analyzer.h
@@ -152,7 +152,7 @@ struct TraceEvent {
// Stored as double to match its JSON representation.
double timestamp;
- base::debug::TraceEventPhase phase;
+ char phase;
std::string category;
@@ -193,7 +193,7 @@ class Query {
static Query Bool(bool boolean);
// Compare with the given phase.
- static Query Phase(base::debug::TraceEventPhase phase);
+ static Query Phase(char phase);
// Compare with the given string pattern. Only works with == and != operators.
// Example: Query(EVENT_NAME) == Query::Pattern("MyEvent*")
@@ -424,10 +424,11 @@ class Query {
bool EvaluateArithmeticOperator(const TraceEvent& event,
double* num) const;
- // For QUERY_EVENT_MEMBER Query: attempt to get the value of the Query.
- // The TraceValue will either be TRACE_TYPE_DOUBLE, TRACE_TYPE_STRING,
- // or if requested member does not exist, it will be TRACE_TYPE_UNDEFINED.
- base::debug::TraceValue GetMemberValue(const TraceEvent& event) const;
+ // For QUERY_EVENT_MEMBER Query: attempt to get the double value of the Query.
+ bool GetMemberValueAsDouble(const TraceEvent& event, double* num) const;
+
+ // For QUERY_EVENT_MEMBER Query: attempt to get the string value of the Query.
+ bool GetMemberValueAsString(const TraceEvent& event, std::string* num) const;
// Does this Query represent a value?
bool is_value() const { return type_ != QUERY_BOOLEAN_OPERATOR; }