diff options
author | jbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-12 22:03:41 +0000 |
---|---|---|
committer | jbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-12 22:03:41 +0000 |
commit | 434b02a20e5194548f6ab5868b78f14215e3614d (patch) | |
tree | 1003e850e6fce0d84697c600e78186b09029f0fd /content/browser | |
parent | 8665da83c740dbcf8bd260f4759ca7b5b283b995 (diff) | |
download | chromium_src-434b02a20e5194548f6ab5868b78f14215e3614d.zip chromium_src-434b02a20e5194548f6ab5868b78f14215e3614d.tar.gz chromium_src-434b02a20e5194548f6ab5868b78f14215e3614d.tar.bz2 |
Add support for filtering traces by categories. The TraceLog API is updated to support included and excluded categories. This API is then plumbed through to the TraceController so that it can be used across all processes.
BUG=96122
TEST=base_unittests
Review URL: http://codereview.chromium.org/7867013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100777 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r-- | content/browser/trace_controller.cc | 61 | ||||
-rw-r--r-- | content/browser/trace_controller.h | 28 | ||||
-rw-r--r-- | content/browser/trace_message_filter.cc | 14 | ||||
-rw-r--r-- | content/browser/trace_message_filter.h | 6 |
4 files changed, 91 insertions, 18 deletions
diff --git a/content/browser/trace_controller.cc b/content/browser/trace_controller.cc index f04f4b2..78e5870 100644 --- a/content/browser/trace_controller.cc +++ b/content/browser/trace_controller.cc @@ -17,7 +17,8 @@ TraceController::TraceController() : pending_end_ack_count_(0), pending_bpf_ack_count_(0), maximum_bpf_(0.0f), - is_tracing_(false) { + is_tracing_(false), + is_get_categories_(false) { base::debug::TraceLog::GetInstance()->SetOutputCallback( base::Bind(&TraceController::OnTraceDataCollected, base::Unretained(this))); @@ -33,7 +34,29 @@ TraceController* TraceController::GetInstance() { return Singleton<TraceController>::get(); } +bool TraceController::GetKnownCategoriesAsync(TraceSubscriber* subscriber) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // Known categories come back from child processes with the EndTracingAck + // message. So to get known categories, just begin and end tracing immediately + // afterwards. This will ping all the child processes for categories. + is_get_categories_ = true; + bool success = BeginTracing(subscriber) && EndTracingAsync(subscriber); + is_get_categories_ = success; + return success; +} + bool TraceController::BeginTracing(TraceSubscriber* subscriber) { + std::vector<std::string> include, exclude; + // By default, exclude all categories that begin with test_ + exclude.push_back("test_*"); + return BeginTracing(subscriber, include, exclude); +} + +bool TraceController::BeginTracing( + TraceSubscriber* subscriber, + const std::vector<std::string>& included_categories, + const std::vector<std::string>& excluded_categories) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!can_begin_tracing() || @@ -41,14 +64,17 @@ bool TraceController::BeginTracing(TraceSubscriber* subscriber) { return false; subscriber_ = subscriber; + included_categories_ = included_categories; + excluded_categories_ = excluded_categories; // Enable tracing is_tracing_ = true; - base::debug::TraceLog::GetInstance()->SetEnabled(true); + base::debug::TraceLog::GetInstance()->SetEnabled(included_categories, + excluded_categories); // Notify all child processes. for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { - it->get()->SendBeginTracing(); + it->get()->SendBeginTracing(included_categories, excluded_categories); } return true; @@ -70,8 +96,10 @@ bool TraceController::EndTracingAsync(TraceSubscriber* subscriber) { // Handle special case of zero child processes. if (pending_end_ack_count_ == 1) { // Ack asynchronously now, because we don't have any children to wait for. + std::vector<std::string> categories; + base::debug::TraceLog::GetInstance()->GetKnownCategories(&categories); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - NewRunnableMethod(this, &TraceController::OnEndTracingAck)); + NewRunnableMethod(this, &TraceController::OnEndTracingAck, categories)); } // Notify all child processes. @@ -131,7 +159,7 @@ void TraceController::AddFilter(TraceMessageFilter* filter) { filters_.insert(filter); if (is_tracing_enabled()) { - filter->SendBeginTracing(); + filter->SendBeginTracing(included_categories_, excluded_categories_); } } @@ -146,13 +174,18 @@ void TraceController::RemoveFilter(TraceMessageFilter* filter) { filters_.erase(filter); } -void TraceController::OnEndTracingAck() { +void TraceController::OnEndTracingAck( + const std::vector<std::string>& known_categories) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - NewRunnableMethod(this, &TraceController::OnEndTracingAck)); + NewRunnableMethod(this, &TraceController::OnEndTracingAck, + known_categories)); return; } + // Merge known_categories with known_categories_ + known_categories_.insert(known_categories.begin(), known_categories.end()); + if (pending_end_ack_count_ == 0) return; @@ -168,17 +201,24 @@ void TraceController::OnEndTracingAck() { // Trigger callback if one is set. if (subscriber_) { - subscriber_->OnEndTracingComplete(); + if (is_get_categories_) + subscriber_->OnKnownCategoriesCollected(known_categories_); + else + subscriber_->OnEndTracingComplete(); // Clear subscriber so that others can use TraceController. subscriber_ = NULL; } + + is_get_categories_ = false; } if (pending_end_ack_count_ == 1) { // The last ack represents local trace, so we need to ack it now. Note that // this code only executes if there were child processes. + std::vector<std::string> categories; + base::debug::TraceLog::GetInstance()->GetKnownCategories(&categories); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - NewRunnableMethod(this, &TraceController::OnEndTracingAck)); + NewRunnableMethod(this, &TraceController::OnEndTracingAck, categories)); } } @@ -195,7 +235,8 @@ void TraceController::OnTraceDataCollected( return; } - if (subscriber_) + // Drop trace events if we are just getting categories. + if (subscriber_ && !is_get_categories_) subscriber_->OnTraceDataCollected(json_events_str_ptr->data); } diff --git a/content/browser/trace_controller.h b/content/browser/trace_controller.h index 33e14c6..4c3d9f3 100644 --- a/content/browser/trace_controller.h +++ b/content/browser/trace_controller.h @@ -7,6 +7,7 @@ #include <set> #include <string> +#include <vector> #include "base/debug/trace_event.h" #include "base/memory/ref_counted.h" @@ -20,8 +21,14 @@ class TraceMessageFilter; // See also: child_trace_message_filter.h class TraceSubscriber { public: + // Called once after TraceController::EndTracingAsync. virtual void OnEndTracingComplete() = 0; + // Called 0 or more times between TraceController::BeginTracing and + // OnEndTracingComplete. virtual void OnTraceDataCollected(const std::string& json_events) = 0; + // Called once after TraceController::GetKnownCategoriesAsync. + virtual void OnKnownCategoriesCollected( + const std::set<std::string>& known_categories) {} virtual void OnTraceBufferPercentFullReply(float percent_full) {} }; @@ -33,11 +40,17 @@ class TraceController { public: static TraceController* GetInstance(); + // Get set of known categories. This can change as new code paths are reached. + // If true is returned, subscriber->OnKnownCategoriesCollected will be called + // when once the categories are retrieved from child processes. + bool GetKnownCategoriesAsync(TraceSubscriber* subscriber); + // Called by browser process to start tracing events on all processes. // // Currently only one subscriber is allowed at a time. // Tracing begins immediately locally, and asynchronously on child processes // as soon as they receive the BeginTracing request. + // By default, all categories are traced except those matching "test_*". // // If BeginTracing was already called previously, // or if an EndTracingAsync is pending, @@ -45,6 +58,15 @@ class TraceController { // BeginTracing will return false meaning it failed. bool BeginTracing(TraceSubscriber* subscriber); + // Same as above, but specifies which categories to trace. + // If both included_categories and excluded_categories are empty, + // all categories are traced. + // Else if included_categories is non-empty, only those are traced. + // Else if excluded_categories is non-empty, everything but those are traced. + bool BeginTracing(TraceSubscriber* subscriber, + const std::vector<std::string>& included_categories, + const std::vector<std::string>& excluded_categories); + // Called by browser process to stop tracing events on all processes. // // Child processes typically are caching trace data and only rarely flush @@ -110,7 +132,7 @@ class TraceController { // a task safely (otherwise the TraceMessageFilter could be destructed). void AddFilter(TraceMessageFilter* filter); void RemoveFilter(TraceMessageFilter* filter); - void OnEndTracingAck(); + void OnEndTracingAck(const std::vector<std::string>& known_categories); void OnTraceDataCollected( const scoped_refptr<base::debug::TraceLog::RefCountedString>& json_events_str_ptr); @@ -125,6 +147,10 @@ class TraceController { int pending_bpf_ack_count_; float maximum_bpf_; bool is_tracing_; + bool is_get_categories_; + std::set<std::string> known_categories_; + std::vector<std::string> included_categories_; + std::vector<std::string> excluded_categories_; DISALLOW_COPY_AND_ASSIGN(TraceController); }; diff --git a/content/browser/trace_message_filter.cc b/content/browser/trace_message_filter.cc index a1bd1d0..fcefc94 100644 --- a/content/browser/trace_message_filter.cc +++ b/content/browser/trace_message_filter.cc @@ -28,7 +28,7 @@ void TraceMessageFilter::OnChannelClosing() { BrowserMessageFilter::OnChannelClosing(); if (is_awaiting_bpf_ack_) - OnEndTracingAck(); + OnEndTracingAck(std::vector<std::string>()); if (is_awaiting_end_ack_) OnTraceBufferPercentFullReply(0.0f); @@ -53,9 +53,12 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message, return handled; } -void TraceMessageFilter::SendBeginTracing() { +void TraceMessageFilter::SendBeginTracing( + const std::vector<std::string>& included_categories, + const std::vector<std::string>& excluded_categories) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - Send(new ChildProcessMsg_BeginTracing); + Send(new ChildProcessMsg_BeginTracing(included_categories, + excluded_categories)); } void TraceMessageFilter::SendEndTracing() { @@ -72,12 +75,13 @@ void TraceMessageFilter::SendGetTraceBufferPercentFull() { Send(new ChildProcessMsg_GetTraceBufferPercentFull); } -void TraceMessageFilter::OnEndTracingAck() { +void TraceMessageFilter::OnEndTracingAck( + const std::vector<std::string>& known_categories) { // is_awaiting_end_ack_ should always be true here, but check in case the // child process is compromised. if (is_awaiting_end_ack_) { is_awaiting_end_ack_ = false; - TraceController::GetInstance()->OnEndTracingAck(); + TraceController::GetInstance()->OnEndTracingAck(known_categories); } } diff --git a/content/browser/trace_message_filter.h b/content/browser/trace_message_filter.h index 31a62db..c2d5d93 100644 --- a/content/browser/trace_message_filter.h +++ b/content/browser/trace_message_filter.h @@ -6,6 +6,7 @@ #define CONTENT_BROWSER_TRACE_MESSAGE_FILTER_H_ #include <string> +#include <vector> #include "content/browser/browser_message_filter.h" @@ -25,13 +26,14 @@ class TraceMessageFilter : public BrowserMessageFilter { virtual bool OnMessageReceived(const IPC::Message& message, bool* message_was_ok); - void SendBeginTracing(); + void SendBeginTracing(const std::vector<std::string>& included_categories, + const std::vector<std::string>& excluded_categories); void SendEndTracing(); void SendGetTraceBufferPercentFull(); private: // Message handlers. - void OnEndTracingAck(); + void OnEndTracingAck(const std::vector<std::string>& known_categories); void OnTraceBufferFull(); void OnTraceBufferPercentFullReply(float percent_full); void OnTraceDataCollected(const std::string& data); |