summaryrefslogtreecommitdiffstats
path: root/base/debug/trace_event.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/debug/trace_event.h')
-rw-r--r--base/debug/trace_event.h119
1 files changed, 94 insertions, 25 deletions
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
index 0fcdaff..380f5e7 100644
--- a/base/debug/trace_event.h
+++ b/base/debug/trace_event.h
@@ -24,7 +24,7 @@
// Additional parameters can be associated with an event:
// void doSomethingCostly2(int howMuch) {
// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
-// "howMuch", StringPrintf("%i", howMuch).c_str());
+// "howMuch", howMuch);
// ...
// }
//
@@ -48,8 +48,19 @@
// To avoid this issue with the |name| and |arg_name| parameters, use the
// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
// Notes: The category must always be in a long-lived char* (i.e. static const).
-// The |arg_values|, when used, are always deep copied and so never have
-// this restriction.
+// The |arg_values|, when used, are always deep copied with the _COPY
+// macros.
+//
+// When are string argument values copied:
+// const char* arg_values are only referenced by default:
+// TRACE_EVENT1("category", "name",
+// "arg1", "literal string is only referenced");
+// Use TRACE_STR_COPY to force copying of a const char*:
+// TRACE_EVENT1("category", "name",
+// "arg1", TRACE_STR_COPY("string will be copied"));
+// std::string arg_values are always copied:
+// TRACE_EVENT1("category", "name",
+// "arg1", std::string("string will be copied"));
//
//
// Thread Safety:
@@ -96,22 +107,26 @@
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/timer.h"
+// 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)
+
// Older style trace macros with explicit id and extra data
// Only these macros result in publishing data to ETW as currently implemented.
#define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
base::debug::TraceLog::AddTraceEventEtw( \
base::debug::TRACE_EVENT_PHASE_BEGIN, \
- name, reinterpret_cast<const void*>(id), extra);
+ name, reinterpret_cast<const void*>(id), extra)
#define TRACE_EVENT_END_ETW(name, id, extra) \
base::debug::TraceLog::AddTraceEventEtw( \
base::debug::TRACE_EVENT_PHASE_END, \
- name, reinterpret_cast<const void*>(id), extra);
+ name, reinterpret_cast<const void*>(id), extra)
#define TRACE_EVENT_INSTANT_ETW(name, id, extra) \
base::debug::TraceLog::AddTraceEventEtw( \
base::debug::TRACE_EVENT_PHASE_INSTANT, \
- name, reinterpret_cast<const void*>(id), extra);
+ name, reinterpret_cast<const void*>(id), extra)
// Records a pair of begin and end events called "name" for the current
// scope, with 0, 1 or 2 associated arguments. If the category is not
@@ -138,7 +153,8 @@
#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_INSTANT, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, false)
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, \
+ base::debug::TraceLog::EVENT_FLAG_NONE)
#define TRACE_EVENT_COPY_INSTANT0(category, name) \
TRACE_EVENT_COPY_INSTANT1(category, name, NULL, 0)
#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
@@ -146,7 +162,10 @@
#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_INSTANT, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, true)
+ category, name, \
+ arg1_name, base::debug::TraceValue::ForceCopy(arg1_val), \
+ arg2_name, base::debug::TraceValue::ForceCopy(arg2_val), \
+ base::debug::TraceLog::EVENT_FLAG_COPY)
// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
// associated arguments. If the category is not enabled, then this
@@ -160,7 +179,8 @@
#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_BEGIN, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, false)
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, \
+ base::debug::TraceLog::EVENT_FLAG_NONE)
#define TRACE_EVENT_COPY_BEGIN0(category, name) \
TRACE_EVENT_COPY_BEGIN1(category, name, NULL, 0)
#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
@@ -168,7 +188,10 @@
#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_BEGIN, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, true)
+ category, name, \
+ arg1_name, base::debug::TraceValue::ForceCopy(arg1_val), \
+ arg2_name, base::debug::TraceValue::ForceCopy(arg2_val), \
+ base::debug::TraceLog::EVENT_FLAG_COPY)
// Records a single END event for "name" immediately. If the category
// is not enabled, then this does nothing.
@@ -181,7 +204,8 @@
#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_END, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, false)
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val, \
+ base::debug::TraceLog::EVENT_FLAG_NONE)
#define TRACE_EVENT_COPY_END0(category, name) \
TRACE_EVENT_COPY_END1(category, name, NULL, 0)
#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
@@ -189,7 +213,10 @@
#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(base::debug::TRACE_EVENT_PHASE_END, \
- category, name, arg1_name, arg1_val, arg2_name, arg2_val, true)
+ category, name, \
+ arg1_name, base::debug::TraceValue::ForceCopy(arg1_val), \
+ arg2_name, base::debug::TraceValue::ForceCopy(arg2_val), \
+ base::debug::TraceLog::EVENT_FLAG_COPY)
// Time threshold event:
// Only record the event if the duration is greater than the specified
@@ -235,12 +262,12 @@
// Implementation detail: internal macro to create static category and add begin
// event if the category is enabled.
#define INTERNAL_TRACE_EVENT_ADD( \
- phase, category, name, arg1_name, arg1_val, arg2_name, arg2_val, copy) \
+ phase, category, name, 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()->AddTraceEvent( \
phase, INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, copy); \
+ name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, flags); \
}
// Implementation detail: internal macro to create static category and add begin
@@ -255,7 +282,8 @@
base::debug::TraceLog::GetInstance()->AddTraceEvent( \
base::debug::TRACE_EVENT_PHASE_BEGIN, \
INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, false); \
+ name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, \
+ base::debug::TraceLog::EVENT_FLAG_NONE); \
INTERNAL_TRACE_EVENT_UID(profileScope).Initialize( \
INTERNAL_TRACE_EVENT_UID(catstatic), name); \
}
@@ -273,7 +301,8 @@
base::debug::TraceLog::GetInstance()->AddTraceEvent( \
base::debug::TRACE_EVENT_PHASE_BEGIN, \
INTERNAL_TRACE_EVENT_UID(catstatic), \
- name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, false); \
+ name, arg1_name, arg1_val, arg2_name, arg2_val, -1, 0, \
+ base::debug::TraceLog::EVENT_FLAG_NONE); \
INTERNAL_TRACE_EVENT_UID(profileScope).Initialize( \
INTERNAL_TRACE_EVENT_UID(catstatic), name, \
INTERNAL_TRACE_EVENT_UID(begin_event_id), threshold); \
@@ -313,7 +342,8 @@ class BASE_EXPORT TraceValue {
TRACE_TYPE_INT,
TRACE_TYPE_DOUBLE,
TRACE_TYPE_POINTER,
- TRACE_TYPE_STRING
+ TRACE_TYPE_STRING,
+ TRACE_TYPE_STATIC_STRING
};
TraceValue() : type_(TRACE_TYPE_UNDEFINED) {
@@ -352,10 +382,27 @@ class BASE_EXPORT TraceValue {
TraceValue(const void* rhs) : type_(TRACE_TYPE_POINTER) {
value_.as_pointer = rhs;
}
- TraceValue(const char* rhs) : type_(TRACE_TYPE_STRING) {
+ 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;
+ }
+
void AppendAsJSON(std::string* out) const;
Type type() const {
@@ -382,7 +429,7 @@ class BASE_EXPORT TraceValue {
return value_.as_pointer;
}
const char* as_string() const {
- DCHECK_EQ(TRACE_TYPE_STRING, type_);
+ DCHECK(type_ == TRACE_TYPE_STRING || type_ == TRACE_TYPE_STATIC_STRING);
return value_.as_string;
}
const char** as_assignable_string() {
@@ -431,6 +478,14 @@ class TraceEvent {
TimeTicks timestamp() const { return timestamp_; }
+ // Exposed for unittesting:
+
+ const base::RefCountedString* parameter_copy_storage() const {
+ return parameter_copy_storage_.get();
+ }
+
+ const char* name() const { return name_; }
+
private:
unsigned long process_id_;
unsigned long thread_id_;
@@ -446,6 +501,12 @@ class TraceEvent {
class BASE_EXPORT TraceLog {
public:
+ // Flags for passing to AddTraceEvent.
+ enum EventFlags {
+ EVENT_FLAG_NONE = 0,
+ EVENT_FLAG_COPY = 1<<0
+ };
+
static TraceLog* GetInstance();
// Global enable of tracing. Currently enables all categories or not.
@@ -490,7 +551,7 @@ class BASE_EXPORT TraceLog {
const char* arg2_name, TraceValue arg2_val,
int threshold_begin_id,
int64 threshold,
- bool copy);
+ EventFlags flags);
static void AddTraceEventEtw(TraceEventPhase phase,
const char* name,
const void* id,
@@ -498,14 +559,20 @@ class BASE_EXPORT TraceLog {
static void AddTraceEventEtw(TraceEventPhase phase,
const char* name,
const void* id,
- const std::string& extra) {
- AddTraceEventEtw(phase, name, id, extra.c_str());
- }
+ const std::string& extra);
+
+ // Exposed for unittesting:
- // Exposed for unittesting only, allows resurrecting our
- // singleton instance post-AtExit processing.
+ // Allows resurrecting our singleton instance post-AtExit processing.
static void Resurrect();
+ // Allow tests to inspect TraceEvents.
+ size_t GetEventsSize() const { return logged_events_.size(); }
+ const TraceEvent& GetEventAt(size_t index) const {
+ DCHECK(index < logged_events_.size());
+ return logged_events_[index];
+ }
+
private:
// This allows constructor and destructor to be private and usable only
// by the Singleton class.
@@ -534,6 +601,7 @@ namespace internal {
// Used by TRACE_EVENTx macro. Do not use directly.
class BASE_EXPORT TraceEndOnScopeClose {
public:
+ // Note: members of data_ intentionally left uninitialized. See Initialize.
TraceEndOnScopeClose() : p_data_(NULL) {}
~TraceEndOnScopeClose() {
if (p_data_)
@@ -563,6 +631,7 @@ class BASE_EXPORT TraceEndOnScopeClose {
// Used by TRACE_EVENTx macro. Do not use directly.
class BASE_EXPORT TraceEndOnScopeCloseThreshold {
public:
+ // Note: members of data_ intentionally left uninitialized. See Initialize.
TraceEndOnScopeCloseThreshold() : p_data_(NULL) {}
~TraceEndOnScopeCloseThreshold() {
if (p_data_)