| Index: base/debug/trace_event.h
|
| diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
|
| index 0fcdaff165927c405a33d1dd012cc8d2680bf86f..380f5e7e4e1c1d7cb3d99e065665f895cc6d3ca4 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_)
|
|
|