summaryrefslogtreecommitdiffstats
path: root/base/debug
diff options
context:
space:
mode:
authortonyg@chromium.org <tonyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-27 00:47:55 +0000
committertonyg@chromium.org <tonyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-27 00:47:55 +0000
commit6aa58b8599840160df945afa89e7482d14d1c4d4 (patch)
tree7da568401c9497ac63894493ca5dd2e68230e35f /base/debug
parent7b05498220a28e7a351c28e75ce1dc68abc746f3 (diff)
downloadchromium_src-6aa58b8599840160df945afa89e7482d14d1c4d4.zip
chromium_src-6aa58b8599840160df945afa89e7482d14d1c4d4.tar.gz
chromium_src-6aa58b8599840160df945afa89e7482d14d1c4d4.tar.bz2
Revert 237280 "Remove TraceController"
Seems to have broken trace-based telemetry benchmarks on android. BUG=323749 > Remove TraceController > > TraceController is obsoleted by TracingController. > Changed all remaining clients to use TracingController. > > BUG=none > > Review URL: https://codereview.chromium.org/67683003 TBR=wangxianzhu@chromium.org Review URL: https://codereview.chromium.org/89753004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@237452 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/debug')
-rw-r--r--base/debug/trace_event_impl.cc216
-rw-r--r--base/debug/trace_event_impl.h67
-rw-r--r--base/debug/trace_event_unittest.cc48
3 files changed, 231 insertions, 100 deletions
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc
index e4d20a5..8f08a1c 100644
--- a/base/debug/trace_event_impl.cc
+++ b/base/debug/trace_event_impl.cc
@@ -99,6 +99,11 @@ int g_category_index = g_num_builtin_categories; // Skip default categories.
LazyInstance<ThreadLocalPointer<const char> >::Leaky
g_current_thread_name = LAZY_INSTANCE_INITIALIZER;
+const char kRecordUntilFull[] = "record-until-full";
+const char kRecordContinuously[] = "record-continuously";
+const char kEnableSampling[] = "enable-sampling";
+const char kMonitorSampling[] = "monitor-sampling";
+
TimeTicks ThreadNow() {
return TimeTicks::IsThreadNowSupported() ?
TimeTicks::ThreadNow() : TimeTicks();
@@ -939,10 +944,12 @@ class TraceLog::ThreadLocalEventBuffer
ThreadLocalEventBuffer(TraceLog* trace_log);
virtual ~ThreadLocalEventBuffer();
- TraceEvent* AddTraceEvent(TraceEventHandle* handle);
+ TraceEvent* AddTraceEvent(NotificationHelper* notifier,
+ TraceEventHandle* handle);
void ReportOverhead(const TimeTicks& event_timestamp,
- const TimeTicks& event_thread_timestamp);
+ const TimeTicks& event_thread_timestamp,
+ NotificationHelper* notifier);
TraceEvent* GetEventByHandle(TraceEventHandle handle) {
if (!chunk_ || handle.chunk_seq != chunk_->seq() ||
@@ -999,10 +1006,12 @@ TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() {
// - the thread has no message loop;
// - trace_event_overhead is disabled.
if (event_count_) {
- InitializeMetadataEvent(AddTraceEvent(NULL),
+ NotificationHelper notifier(trace_log_);
+ InitializeMetadataEvent(AddTraceEvent(&notifier, NULL),
static_cast<int>(base::PlatformThread::CurrentId()),
"overhead", "average_overhead",
overhead_.InMillisecondsF() / event_count_);
+ notifier.SendNotificationIfAny();
}
{
@@ -1014,6 +1023,7 @@ TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() {
}
TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent(
+ NotificationHelper* notifier,
TraceEventHandle* handle) {
CheckThisIsCurrentBuffer();
@@ -1025,7 +1035,7 @@ TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent(
if (!chunk_) {
AutoLock lock(trace_log_->lock_);
chunk_ = trace_log_->logged_events_->GetChunk(&chunk_index_);
- trace_log_->CheckIfBufferIsFullWhileLocked();
+ trace_log_->CheckIfBufferIsFullWhileLocked(notifier);
}
if (!chunk_)
return NULL;
@@ -1040,7 +1050,8 @@ TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent(
void TraceLog::ThreadLocalEventBuffer::ReportOverhead(
const TimeTicks& event_timestamp,
- const TimeTicks& event_thread_timestamp) {
+ const TimeTicks& event_thread_timestamp,
+ NotificationHelper* notifier) {
if (!g_category_group_enabled[g_category_trace_event_overhead])
return;
@@ -1050,7 +1061,7 @@ void TraceLog::ThreadLocalEventBuffer::ReportOverhead(
TimeTicks now = trace_log_->OffsetNow();
TimeDelta overhead = now - event_timestamp;
if (overhead.InMicroseconds() >= kOverheadReportThresholdInMicroseconds) {
- TraceEvent* trace_event = AddTraceEvent(NULL);
+ TraceEvent* trace_event = AddTraceEvent(notifier, NULL);
if (trace_event) {
trace_event->Initialize(
static_cast<int>(PlatformThread::CurrentId()),
@@ -1081,14 +1092,66 @@ void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() {
// find the generation mismatch and delete this buffer soon.
}
+TraceLog::NotificationHelper::NotificationHelper(TraceLog* trace_log)
+ : trace_log_(trace_log),
+ notification_(0) {
+}
+
+TraceLog::NotificationHelper::~NotificationHelper() {
+}
+
+void TraceLog::NotificationHelper::AddNotificationWhileLocked(
+ int notification) {
+ trace_log_->lock_.AssertAcquired();
+ if (trace_log_->notification_callback_.is_null())
+ return;
+ if (notification_ == 0)
+ callback_copy_ = trace_log_->notification_callback_;
+ notification_ |= notification;
+}
+
+void TraceLog::NotificationHelper::SendNotificationIfAny() {
+ if (notification_)
+ callback_copy_.Run(notification_);
+}
+
// static
TraceLog* TraceLog::GetInstance() {
return Singleton<TraceLog, LeakySingletonTraits<TraceLog> >::get();
}
+// static
+// Note, if you add more options here you also need to update:
+// content/browser/devtools/devtools_tracing_handler:TraceOptionsFromString
+TraceLog::Options TraceLog::TraceOptionsFromString(const std::string& options) {
+ std::vector<std::string> split;
+ base::SplitString(options, ',', &split);
+ int ret = 0;
+ for (std::vector<std::string>::iterator iter = split.begin();
+ iter != split.end();
+ ++iter) {
+ if (*iter == kRecordUntilFull) {
+ ret |= RECORD_UNTIL_FULL;
+ } else if (*iter == kRecordContinuously) {
+ ret |= RECORD_CONTINUOUSLY;
+ } else if (*iter == kEnableSampling) {
+ ret |= ENABLE_SAMPLING;
+ } else if (*iter == kMonitorSampling) {
+ ret |= MONITOR_SAMPLING;
+ } else {
+ NOTREACHED(); // Unknown option provided.
+ }
+ }
+ if (!(ret & RECORD_UNTIL_FULL) && !(ret & RECORD_CONTINUOUSLY))
+ ret |= RECORD_UNTIL_FULL; // Default when no options are specified.
+
+ return static_cast<Options>(ret);
+}
+
TraceLog::TraceLog()
: enabled_(false),
num_traces_recorded_(0),
+ buffer_is_full_(0),
event_callback_(0),
dispatching_to_observer_list_(false),
process_sort_index_(0),
@@ -1265,6 +1328,7 @@ void TraceLog::SetEnabled(const CategoryFilter& category_filter,
subtle::NoBarrier_Store(&trace_options_, options);
logged_events_.reset(CreateTraceBuffer());
NextGeneration();
+ subtle::NoBarrier_Store(&buffer_is_full_, 0);
}
num_traces_recorded_++;
@@ -1311,52 +1375,49 @@ CategoryFilter TraceLog::GetCurrentCategoryFilter() {
}
void TraceLog::SetDisabled() {
- AutoLock lock(lock_);
- SetDisabledWhileLocked();
-}
+ std::vector<EnabledStateObserver*> observer_list;
+ {
+ AutoLock lock(lock_);
+ if (!enabled_)
+ return;
-void TraceLog::SetDisabledWhileLocked() {
- lock_.AssertAcquired();
+ if (dispatching_to_observer_list_) {
+ DLOG(ERROR)
+ << "Cannot manipulate TraceLog::Enabled state from an observer.";
+ return;
+ }
- if (!enabled_)
- return;
+ enabled_ = false;
- if (dispatching_to_observer_list_) {
- DLOG(ERROR)
- << "Cannot manipulate TraceLog::Enabled state from an observer.";
- return;
- }
+ if (sampling_thread_.get()) {
+ // Stop the sampling thread.
+ sampling_thread_->Stop();
+ lock_.Release();
+ PlatformThread::Join(sampling_thread_handle_);
+ lock_.Acquire();
+ sampling_thread_handle_ = PlatformThreadHandle();
+ sampling_thread_.reset();
+ }
- enabled_ = false;
+ category_filter_.Clear();
+ subtle::NoBarrier_Store(&watch_category_, 0);
+ watch_event_name_ = "";
+ UpdateCategoryGroupEnabledFlags();
+ AddMetadataEventsWhileLocked();
- if (sampling_thread_.get()) {
- // Stop the sampling thread.
- sampling_thread_->Stop();
- lock_.Release();
- PlatformThread::Join(sampling_thread_handle_);
- lock_.Acquire();
- sampling_thread_handle_ = PlatformThreadHandle();
- sampling_thread_.reset();
+ dispatching_to_observer_list_ = true;
+ observer_list = enabled_state_observer_list_;
}
- category_filter_.Clear();
- subtle::NoBarrier_Store(&watch_category_, 0);
- watch_event_name_ = "";
- UpdateCategoryGroupEnabledFlags();
- AddMetadataEventsWhileLocked();
-
- dispatching_to_observer_list_ = true;
- std::vector<EnabledStateObserver*> observer_list =
- enabled_state_observer_list_;
+ // Dispatch to observers outside the lock in case the observer triggers a
+ // trace event.
+ for (size_t i = 0; i < observer_list.size(); ++i)
+ observer_list[i]->OnTraceLogDisabled();
{
- // Dispatch to observers outside the lock in case the observer triggers a
- // trace event.
- AutoUnlock unlock(lock_);
- for (size_t i = 0; i < observer_list.size(); ++i)
- observer_list[i]->OnTraceLogDisabled();
+ AutoLock lock(lock_);
+ dispatching_to_observer_list_ = false;
}
- dispatching_to_observer_list_ = false;
}
int TraceLog::GetNumTracesRecorded() {
@@ -1388,14 +1449,14 @@ bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const {
}
float TraceLog::GetBufferPercentFull() const {
- AutoLock lock(lock_);
return static_cast<float>(static_cast<double>(logged_events_->Size()) /
logged_events_->Capacity());
}
-bool TraceLog::BufferIsFull() const {
+void TraceLog::SetNotificationCallback(
+ const TraceLog::NotificationCallback& cb) {
AutoLock lock(lock_);
- return logged_events_->IsFull();
+ notification_callback_ = cb;
}
TraceBuffer* TraceLog::CreateTraceBuffer() {
@@ -1410,7 +1471,7 @@ TraceBuffer* TraceLog::CreateTraceBuffer() {
}
TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
- TraceEventHandle* handle, bool check_buffer_is_full) {
+ NotificationHelper* notifier, TraceEventHandle* handle) {
lock_.AssertAcquired();
if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) {
@@ -1421,8 +1482,8 @@ TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
if (!thread_shared_chunk_) {
thread_shared_chunk_ = logged_events_->GetChunk(
&thread_shared_chunk_index_);
- if (check_buffer_is_full)
- CheckIfBufferIsFullWhileLocked();
+ if (notifier)
+ CheckIfBufferIsFullWhileLocked(notifier);
}
if (!thread_shared_chunk_)
return NULL;
@@ -1436,10 +1497,13 @@ TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
return trace_event;
}
-void TraceLog::CheckIfBufferIsFullWhileLocked() {
+void TraceLog::CheckIfBufferIsFullWhileLocked(NotificationHelper* notifier) {
lock_.AssertAcquired();
- if (logged_events_->IsFull())
- SetDisabledWhileLocked();
+ if (!subtle::NoBarrier_Load(&buffer_is_full_) && logged_events_->IsFull()) {
+ subtle::NoBarrier_Store(&buffer_is_full_,
+ static_cast<subtle::AtomicWord>(1));
+ notifier->AddNotificationWhileLocked(TRACE_BUFFER_FULL);
+ }
}
void TraceLog::SetEventCallbackEnabled(const CategoryFilter& category_filter,
@@ -1556,6 +1620,7 @@ void TraceLog::FinishFlush(int generation) {
previous_logged_events.swap(logged_events_);
logged_events_.reset(CreateTraceBuffer());
NextGeneration();
+ subtle::NoBarrier_Store(&buffer_is_full_, 0);
thread_message_loops_.clear();
flush_message_loop_proxy_ = NULL;
@@ -1675,6 +1740,8 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
TimeTicks now = OffsetTimestamp(timestamp);
TimeTicks thread_now = ThreadNow();
+ NotificationHelper notifier(this);
+
ThreadLocalEventBuffer* thread_local_event_buffer = NULL;
// A ThreadLocalEventBuffer needs the message loop
// - to know when the thread exits;
@@ -1731,13 +1798,15 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
}
TraceEvent* trace_event = NULL;
- if ((*category_group_enabled & ENABLED_FOR_RECORDING)) {
+ if ((*category_group_enabled & ENABLED_FOR_RECORDING) &&
+ !subtle::NoBarrier_Load(&buffer_is_full_)) {
if (thread_local_event_buffer) {
lock.EnsureReleased();
- trace_event = thread_local_event_buffer->AddTraceEvent(&handle);
+ trace_event = thread_local_event_buffer->AddTraceEvent(&notifier,
+ &handle);
} else {
lock.EnsureAcquired();
- trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true);
+ trace_event = AddEventToThreadSharedChunkWhileLocked(&notifier, &handle);
}
if (trace_event) {
@@ -1750,24 +1819,20 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
trace_event->SendToATrace();
#endif
}
+ }
- if (trace_options() & ECHO_TO_CONSOLE) {
- lock.EnsureAcquired();
- OutputEventToConsoleWhileLocked(
- phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase,
- timestamp, trace_event);
- }
+ if (trace_options() & ECHO_TO_CONSOLE) {
+ lock.EnsureAcquired();
+ OutputEventToConsoleWhileLocked(
+ phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase,
+ timestamp, trace_event);
}
if (reinterpret_cast<const unsigned char*>(subtle::NoBarrier_Load(
&watch_category_)) == category_group_enabled) {
lock.EnsureAcquired();
- if (watch_event_name_ == name) {
- WatchEventCallback watch_event_callback_copy = watch_event_callback_;
- lock.EnsureReleased();
- if (!watch_event_callback_copy.is_null())
- watch_event_callback_copy.Run();
- }
+ if (watch_event_name_ == name)
+ notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
}
lock.EnsureReleased();
@@ -1785,7 +1850,9 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
}
if (thread_local_event_buffer)
- thread_local_event_buffer->ReportOverhead(now, thread_now);
+ thread_local_event_buffer->ReportOverhead(now, thread_now, &notifier);
+
+ notifier.SendNotificationIfAny();
return handle;
}
@@ -1895,22 +1962,19 @@ void TraceLog::UpdateTraceEventDuration(
}
void TraceLog::SetWatchEvent(const std::string& category_name,
- const std::string& event_name,
- const WatchEventCallback& callback) {
+ const std::string& event_name) {
const unsigned char* category = GetCategoryGroupEnabled(
category_name.c_str());
AutoLock lock(lock_);
subtle::NoBarrier_Store(&watch_category_,
reinterpret_cast<subtle::AtomicWord>(category));
watch_event_name_ = event_name;
- watch_event_callback_ = callback;
}
void TraceLog::CancelWatchEvent() {
AutoLock lock(lock_);
subtle::NoBarrier_Store(&watch_category_, 0);
watch_event_name_ = "";
- watch_event_callback_.Reset();
}
void TraceLog::AddMetadataEventsWhileLocked() {
@@ -1918,14 +1982,14 @@ void TraceLog::AddMetadataEventsWhileLocked() {
int current_thread_id = static_cast<int>(base::PlatformThread::CurrentId());
if (process_sort_index_ != 0) {
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL),
current_thread_id,
"process_sort_index", "sort_index",
process_sort_index_);
}
if (process_name_.size()) {
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL),
current_thread_id,
"process_name", "name",
process_name_);
@@ -1938,7 +2002,7 @@ void TraceLog::AddMetadataEventsWhileLocked() {
it++) {
labels.push_back(it->second);
}
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL),
current_thread_id,
"process_labels", "labels",
JoinString(labels, ','));
@@ -1950,7 +2014,7 @@ void TraceLog::AddMetadataEventsWhileLocked() {
it++) {
if (it->second == 0)
continue;
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL),
it->first,
"thread_sort_index", "sort_index",
it->second);
@@ -1962,7 +2026,7 @@ void TraceLog::AddMetadataEventsWhileLocked() {
it++) {
if (it->second.empty())
continue;
- InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
+ InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, NULL),
it->first,
"thread_name", "name",
it->second);
diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h
index 31a5f94..9e0ece9 100644
--- a/base/debug/trace_event_impl.h
+++ b/base/debug/trace_event_impl.h
@@ -352,6 +352,16 @@ class TraceSamplingThread;
class BASE_EXPORT TraceLog {
public:
+ // Notification is a mask of one or more of the following events.
+ enum Notification {
+ // The trace buffer does not flush dynamically, so when it fills up,
+ // subsequent trace events will be dropped. This callback is generated when
+ // the trace buffer is full. The callback must be thread safe.
+ TRACE_BUFFER_FULL = 1 << 0,
+ // A subscribed trace-event occurred.
+ EVENT_WATCH_NOTIFICATION = 1 << 1
+ };
+
// Options determines how the trace buffer stores data.
enum Options {
// Record until the trace buffer is full.
@@ -383,6 +393,10 @@ class BASE_EXPORT TraceLog {
static TraceLog* GetInstance();
+ // Convert the given string to trace options. Defaults to RECORD_UNTIL_FULL if
+ // the string does not provide valid options.
+ static Options TraceOptionsFromString(const std::string& str);
+
// Get set of known category groups. This can change as new code paths are
// reached. The known category groups are inserted into |category_groups|.
void GetKnownCategoryGroups(std::vector<std::string>* category_groups);
@@ -436,7 +450,14 @@ class BASE_EXPORT TraceLog {
bool HasEnabledStateObserver(EnabledStateObserver* listener) const;
float GetBufferPercentFull() const;
- bool BufferIsFull() const;
+
+ // Set the thread-safe notification callback. The callback can occur at any
+ // time and from any thread. WARNING: It is possible for the previously set
+ // callback to be called during OR AFTER a call to SetNotificationCallback.
+ // Therefore, the target of the callback must either be a global function,
+ // ref-counted object or a LazyInstance with Leaky traits (or equivalent).
+ typedef base::Callback<void(int)> NotificationCallback;
+ void SetNotificationCallback(const NotificationCallback& cb);
// Not using base::Callback because of its limited by 7 parameters.
// Also, using primitive type allows directly passing callback from WebCore.
@@ -524,11 +545,12 @@ class BASE_EXPORT TraceLog {
const char* name,
TraceEventHandle handle);
- // For every matching event, the callback will be called.
- typedef base::Callback<void()> WatchEventCallback;
+ // For every matching event, a notification will be fired. NOTE: the
+ // notification will fire for each matching event that has already occurred
+ // since tracing was started (including before tracing if the process was
+ // started with tracing turned on).
void SetWatchEvent(const std::string& category_name,
- const std::string& event_name,
- const WatchEventCallback& callback);
+ const std::string& event_name);
// Cancel the watch event. If tracing is enabled, this may race with the
// watch event notification firing.
void CancelWatchEvent();
@@ -597,6 +619,29 @@ class BASE_EXPORT TraceLog {
void UpdateCategoryGroupEnabledFlags();
void UpdateCategoryGroupEnabledFlag(int category_index);
+ // Helper class for managing notification_thread_count_ and running
+ // notification callbacks. This is very similar to a reader-writer lock, but
+ // shares the lock with TraceLog and manages the notification flags.
+ class NotificationHelper {
+ public:
+ inline explicit NotificationHelper(TraceLog* trace_log);
+ inline ~NotificationHelper();
+
+ // Called only while TraceLog::lock_ is held. This ORs the given
+ // notification with any existing notifications.
+ inline void AddNotificationWhileLocked(int notification);
+
+ // Called only while TraceLog::lock_ is NOT held. If there are any pending
+ // notifications from previous calls to AddNotificationWhileLocked, this
+ // will call the NotificationCallback.
+ inline void SendNotificationIfAny();
+
+ private:
+ TraceLog* trace_log_;
+ NotificationCallback callback_copy_;
+ int notification_;
+ };
+
class ThreadLocalEventBuffer;
class OptionalAutoLock;
@@ -612,10 +657,9 @@ class BASE_EXPORT TraceLog {
const TimeTicks& timestamp,
TraceEvent* trace_event);
- TraceEvent* AddEventToThreadSharedChunkWhileLocked(TraceEventHandle* handle,
- bool check_buffer_is_full);
- void CheckIfBufferIsFullWhileLocked();
- void SetDisabledWhileLocked();
+ TraceEvent* AddEventToThreadSharedChunkWhileLocked(
+ NotificationHelper* notifier, TraceEventHandle* handle);
+ void CheckIfBufferIsFullWhileLocked(NotificationHelper* notifier);
TraceEvent* GetEventByHandleInternal(TraceEventHandle handle,
OptionalAutoLock* lock);
@@ -646,10 +690,12 @@ class BASE_EXPORT TraceLog {
}
// This lock protects TraceLog member accesses from arbitrary threads.
- mutable Lock lock_;
+ Lock lock_;
int locked_line_;
bool enabled_;
int num_traces_recorded_;
+ subtle::AtomicWord /* bool */ buffer_is_full_;
+ NotificationCallback notification_callback_;
scoped_ptr<TraceBuffer> logged_events_;
subtle::AtomicWord /* EventCallback */ event_callback_;
bool dispatching_to_observer_list_;
@@ -673,7 +719,6 @@ class BASE_EXPORT TraceLog {
TimeDelta time_offset_;
// Allow tests to wake up when certain events occur.
- WatchEventCallback watch_event_callback_;
subtle::AtomicWord /* const unsigned char* */ watch_category_;
std::string watch_event_name_;
diff --git a/base/debug/trace_event_unittest.cc b/base/debug/trace_event_unittest.cc
index 0849c08..4aca180 100644
--- a/base/debug/trace_event_unittest.cc
+++ b/base/debug/trace_event_unittest.cc
@@ -53,8 +53,10 @@ class TraceEventTestFixture : public testing::Test {
WaitableEvent* flush_complete_event,
const scoped_refptr<base::RefCountedString>& events_str,
bool has_more_events);
- void OnWatchEventMatched() {
- ++event_watch_notification_;
+ void OnTraceNotification(int notification) {
+ if (notification & TraceLog::EVENT_WATCH_NOTIFICATION)
+ ++event_watch_notification_;
+ notifications_received_ |= notification;
}
DictionaryValue* FindMatchingTraceEntry(const JsonKeyValue* key_values);
DictionaryValue* FindNamePhase(const char* name, const char* phase);
@@ -77,6 +79,7 @@ class TraceEventTestFixture : public testing::Test {
void BeginSpecificTrace(const std::string& filter) {
event_watch_notification_ = 0;
+ notifications_received_ = 0;
TraceLog::GetInstance()->SetEnabled(CategoryFilter(filter),
TraceLog::RECORD_UNTIL_FULL);
}
@@ -124,13 +127,16 @@ class TraceEventTestFixture : public testing::Test {
virtual void SetUp() OVERRIDE {
const char* name = PlatformThread::GetName();
old_thread_name_ = name ? strdup(name) : NULL;
+ notifications_received_ = 0;
TraceLog::DeleteForTesting();
TraceLog* tracelog = TraceLog::GetInstance();
ASSERT_TRUE(tracelog);
ASSERT_FALSE(tracelog->IsEnabled());
+ tracelog->SetNotificationCallback(
+ base::Bind(&TraceEventTestFixture::OnTraceNotification,
+ base::Unretained(this)));
trace_buffer_.SetOutputCallback(json_output_.GetCallback());
- event_watch_notification_ = 0;
}
virtual void TearDown() OVERRIDE {
if (TraceLog::GetInstance())
@@ -147,6 +153,7 @@ class TraceEventTestFixture : public testing::Test {
base::debug::TraceResultBuffer trace_buffer_;
base::debug::TraceResultBuffer::SimpleOutput json_output_;
int event_watch_notification_;
+ int notifications_received_;
private:
// We want our singleton torn down after each test.
@@ -1181,17 +1188,14 @@ TEST_F(TraceEventTestFixture, Categories) {
TEST_F(TraceEventTestFixture, EventWatchNotification) {
// Basic one occurrence.
BeginTrace();
- TraceLog::WatchEventCallback callback =
- base::Bind(&TraceEventTestFixture::OnWatchEventMatched,
- base::Unretained(this));
- TraceLog::GetInstance()->SetWatchEvent("cat", "event", callback);
+ TraceLog::GetInstance()->SetWatchEvent("cat", "event");
TRACE_EVENT_INSTANT0("cat", "event", TRACE_EVENT_SCOPE_THREAD);
EndTraceAndFlush();
EXPECT_EQ(event_watch_notification_, 1);
// Auto-reset after end trace.
BeginTrace();
- TraceLog::GetInstance()->SetWatchEvent("cat", "event", callback);
+ TraceLog::GetInstance()->SetWatchEvent("cat", "event");
EndTraceAndFlush();
BeginTrace();
TRACE_EVENT_INSTANT0("cat", "event", TRACE_EVENT_SCOPE_THREAD);
@@ -1201,7 +1205,7 @@ TEST_F(TraceEventTestFixture, EventWatchNotification) {
// Multiple occurrence.
BeginTrace();
int num_occurrences = 5;
- TraceLog::GetInstance()->SetWatchEvent("cat", "event", callback);
+ TraceLog::GetInstance()->SetWatchEvent("cat", "event");
for (int i = 0; i < num_occurrences; ++i)
TRACE_EVENT_INSTANT0("cat", "event", TRACE_EVENT_SCOPE_THREAD);
EndTraceAndFlush();
@@ -1209,21 +1213,21 @@ TEST_F(TraceEventTestFixture, EventWatchNotification) {
// Wrong category.
BeginTrace();
- TraceLog::GetInstance()->SetWatchEvent("cat", "event", callback);
+ TraceLog::GetInstance()->SetWatchEvent("cat", "event");
TRACE_EVENT_INSTANT0("wrong_cat", "event", TRACE_EVENT_SCOPE_THREAD);
EndTraceAndFlush();
EXPECT_EQ(event_watch_notification_, 0);
// Wrong name.
BeginTrace();
- TraceLog::GetInstance()->SetWatchEvent("cat", "event", callback);
+ TraceLog::GetInstance()->SetWatchEvent("cat", "event");
TRACE_EVENT_INSTANT0("cat", "wrong_event", TRACE_EVENT_SCOPE_THREAD);
EndTraceAndFlush();
EXPECT_EQ(event_watch_notification_, 0);
// Canceled.
BeginTrace();
- TraceLog::GetInstance()->SetWatchEvent("cat", "event", callback);
+ TraceLog::GetInstance()->SetWatchEvent("cat", "event");
TraceLog::GetInstance()->CancelWatchEvent();
TRACE_EVENT_INSTANT0("cat", "event", TRACE_EVENT_SCOPE_THREAD);
EndTraceAndFlush();
@@ -1730,7 +1734,23 @@ TEST_F(TraceEventTestFixture, TraceCategoriesAfterNestedEnable) {
trace_log->SetDisabled();
}
+TEST_F(TraceEventTestFixture, TraceOptionsParsing) {
+ EXPECT_EQ(TraceLog::RECORD_UNTIL_FULL,
+ TraceLog::TraceOptionsFromString(std::string()));
+
+ EXPECT_EQ(TraceLog::RECORD_UNTIL_FULL,
+ TraceLog::TraceOptionsFromString("record-until-full"));
+ EXPECT_EQ(TraceLog::RECORD_CONTINUOUSLY,
+ TraceLog::TraceOptionsFromString("record-continuously"));
+ EXPECT_EQ(TraceLog::RECORD_UNTIL_FULL | TraceLog::ENABLE_SAMPLING,
+ TraceLog::TraceOptionsFromString("enable-sampling"));
+ EXPECT_EQ(TraceLog::RECORD_CONTINUOUSLY | TraceLog::ENABLE_SAMPLING,
+ TraceLog::TraceOptionsFromString(
+ "record-continuously,enable-sampling"));
+}
+
TEST_F(TraceEventTestFixture, TraceSampling) {
+ event_watch_notification_ = 0;
TraceLog::GetInstance()->SetEnabled(
CategoryFilter("*"),
TraceLog::Options(TraceLog::RECORD_UNTIL_FULL |
@@ -1749,6 +1769,7 @@ TEST_F(TraceEventTestFixture, TraceSampling) {
}
TEST_F(TraceEventTestFixture, TraceSamplingScope) {
+ event_watch_notification_ = 0;
TraceLog::GetInstance()->SetEnabled(
CategoryFilter("*"),
TraceLog::Options(TraceLog::RECORD_UNTIL_FULL |
@@ -1783,6 +1804,7 @@ TEST_F(TraceEventTestFixture, TraceSamplingScope) {
}
TEST_F(TraceEventTestFixture, TraceContinuousSampling) {
+ event_watch_notification_ = 0;
TraceLog::GetInstance()->SetEnabled(
CategoryFilter("*"),
TraceLog::Options(TraceLog::MONITOR_SAMPLING));
@@ -2049,7 +2071,7 @@ TEST_F(TraceEventCallbackTest, TraceEventCallbackWhileFull) {
TraceLog::RECORD_UNTIL_FULL);
do {
TRACE_EVENT_INSTANT0("all", "badger badger", TRACE_EVENT_SCOPE_GLOBAL);
- } while (!TraceLog::GetInstance()->BufferIsFull());
+ } while ((notifications_received_ & TraceLog::TRACE_BUFFER_FULL) == 0);
TraceLog::GetInstance()->SetEventCallbackEnabled(CategoryFilter("*"),
Callback);
TRACE_EVENT_INSTANT0("all", "a snake", TRACE_EVENT_SCOPE_GLOBAL);