diff options
author | jbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-24 16:34:08 +0000 |
---|---|---|
committer | jbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-24 16:34:08 +0000 |
commit | 91ea6343d74a2cd7457d2a8b1521e3fd4724d7f5 (patch) | |
tree | c28b5e27b1d369c35405b53f603e7a9796089ac8 /base | |
parent | 7d1208ce239e0298f016e6839f25551975de2269 (diff) | |
download | chromium_src-91ea6343d74a2cd7457d2a8b1521e3fd4724d7f5.zip chromium_src-91ea6343d74a2cd7457d2a8b1521e3fd4724d7f5.tar.gz chromium_src-91ea6343d74a2cd7457d2a8b1521e3fd4724d7f5.tar.bz2 |
Internalize JSON chunk merging to trace_event.h API (retry).
Original review: http://codereview.chromium.org/8355024/
BUG=100291
TEST=base_unittests, content_unittests
Review URL: http://codereview.chromium.org/8373018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106924 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/debug/trace_event.cc | 45 | ||||
-rw-r--r-- | base/debug/trace_event.h | 48 | ||||
-rw-r--r-- | base/debug/trace_event_unittest.cc | 54 |
3 files changed, 130 insertions, 17 deletions
diff --git a/base/debug/trace_event.cc b/base/debug/trace_event.cc index 107e599..8b24cca 100644 --- a/base/debug/trace_event.cc +++ b/base/debug/trace_event.cc @@ -9,6 +9,7 @@ #if defined(OS_WIN) #include "base/debug/trace_event_win.h" #endif +#include "base/bind.h" #include "base/format_macros.h" #include "base/memory/ref_counted_memory.h" #include "base/process_util.h" @@ -224,13 +225,11 @@ void TraceEvent::AppendEventsAsJSON(const std::vector<TraceEvent>& events, size_t start, size_t count, std::string* out) { - *out += "["; for (size_t i = 0; i < count && start + i < events.size(); ++i) { if (i > 0) *out += ","; events[i + start].AppendAsJSON(out); } - *out += "]"; } void TraceEvent::AppendAsJSON(std::string* out) const { @@ -262,6 +261,48 @@ void TraceEvent::AppendAsJSON(std::string* out) const { //////////////////////////////////////////////////////////////////////////////// // +// TraceResultBuffer +// +//////////////////////////////////////////////////////////////////////////////// + +TraceResultBuffer::OutputCallback + TraceResultBuffer::SimpleOutput::GetCallback() { + return base::Bind(&SimpleOutput::Append, base::Unretained(this)); +} + +void TraceResultBuffer::SimpleOutput::Append( + const std::string& json_trace_output) { + json_output += json_trace_output; +} + +TraceResultBuffer::TraceResultBuffer() : append_comma_(false) { +} + +TraceResultBuffer::~TraceResultBuffer() { +} + +void TraceResultBuffer::SetOutputCallback(OutputCallback json_chunk_callback) { + output_callback_ = json_chunk_callback; +} + +void TraceResultBuffer::Start() { + append_comma_ = false; + output_callback_.Run("["); +} + +void TraceResultBuffer::AddFragment(const std::string& trace_fragment) { + if (append_comma_) + output_callback_.Run(","); + append_comma_ = true; + output_callback_.Run(trace_fragment); +} + +void TraceResultBuffer::Finish() { + output_callback_.Run("]"); +} + +//////////////////////////////////////////////////////////////////////////////// +// // TraceLog // //////////////////////////////////////////////////////////////////////////////// diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h index d5aa256..b4f7d28 100644 --- a/base/debug/trace_event.h +++ b/base/debug/trace_event.h @@ -515,6 +515,50 @@ class TraceEvent { }; +// TraceResultBuffer collects and converts trace fragments returned by TraceLog +// to JSON output. +class BASE_EXPORT TraceResultBuffer { + public: + typedef base::Callback<void(const std::string&)> OutputCallback; + + // If you don't need to stream JSON chunks out efficiently, and just want to + // get a complete JSON string after calling Finish, use this struct to collect + // JSON trace output. + struct BASE_EXPORT SimpleOutput { + OutputCallback GetCallback(); + void Append(const std::string& json_string); + + // Do what you want with the json_output_ string after calling + // TraceResultBuffer::Finish. + std::string json_output; + }; + + TraceResultBuffer(); + ~TraceResultBuffer(); + + // Set callback. The callback will be called during Start with the initial + // JSON output and during AddFragment and Finish with following JSON output + // chunks. The callback target must live past the last calls to + // TraceResultBuffer::Start/AddFragment/Finish. + void SetOutputCallback(OutputCallback json_chunk_callback); + + // Start JSON output. This resets all internal state, so you can reuse + // the TraceResultBuffer by calling Start. + void Start(); + + // Call AddFragment 0 or more times to add trace fragments from TraceLog. + void AddFragment(const std::string& trace_fragment); + + // When all fragments have been added, call Finish to complete the JSON + // formatted output. + void Finish(); + + private: + OutputCallback output_callback_; + bool append_comma_; +}; + + class BASE_EXPORT TraceLog { public: // Flags for passing to AddTraceEvent. @@ -549,7 +593,9 @@ class BASE_EXPORT TraceLog { // When enough events are collected, they are handed (in bulk) to // the output callback. If no callback is set, the output will be - // silently dropped. The callback must be thread safe. + // silently dropped. The callback must be thread safe. The string format is + // undefined. Use TraceResultBuffer to convert one or more trace strings to + // JSON. typedef RefCountedData<std::string> RefCountedString; typedef base::Callback<void(scoped_refptr<RefCountedString>)> OutputCallback; void SetOutputCallback(const OutputCallback& cb); diff --git a/base/debug/trace_event_unittest.cc b/base/debug/trace_event_unittest.cc index 0ccf440..c30c773 100644 --- a/base/debug/trace_event_unittest.cc +++ b/base/debug/trace_event_unittest.cc @@ -40,7 +40,7 @@ class TraceEventTestFixture : public testing::Test { // up multiple times when testing AtExit. Use ManualTestSetUp for this. void ManualTestSetUp(); void OnTraceDataCollected( - scoped_refptr<TraceLog::RefCountedString> json_events_str); + scoped_refptr<TraceLog::RefCountedString> events_str); bool FindMatchingTraceEntry(const JsonKeyValue* key_values); bool FindNamePhase(const char* name, const char* phase); bool FindMatchingValue(const char* key, @@ -48,12 +48,13 @@ class TraceEventTestFixture : public testing::Test { bool FindNonMatchingValue(const char* key, const char* value); void Clear() { - trace_string_.clear(); trace_parsed_.Clear(); + json_output_.json_output.clear(); } - std::string trace_string_; ListValue trace_parsed_; + base::debug::TraceResultBuffer trace_buffer_; + base::debug::TraceResultBuffer::SimpleOutput json_output_; private: // We want our singleton torn down after each test. @@ -70,15 +71,19 @@ void TraceEventTestFixture::ManualTestSetUp() { tracelog->SetOutputCallback( base::Bind(&TraceEventTestFixture::OnTraceDataCollected, base::Unretained(this))); + trace_buffer_.SetOutputCallback(json_output_.GetCallback()); } void TraceEventTestFixture::OnTraceDataCollected( - scoped_refptr<TraceLog::RefCountedString> json_events_str) { + scoped_refptr<TraceLog::RefCountedString> events_str) { AutoLock lock(lock_); - trace_string_ += json_events_str->data; + json_output_.json_output.clear(); + trace_buffer_.Start(); + trace_buffer_.AddFragment(events_str->data); + trace_buffer_.Finish(); scoped_ptr<Value> root; - root.reset(base::JSONReader::Read(json_events_str->data, false)); + root.reset(base::JSONReader::Read(json_output_.json_output, false)); ListValue* root_list = NULL; ASSERT_TRUE(root.get()); @@ -281,8 +286,7 @@ void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) { task_complete_event->Signal(); } -void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed, - const std::string& trace_string) { +void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) { DictionaryValue* item = NULL; #define EXPECT_FIND_(string) \ @@ -345,7 +349,7 @@ void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed, } void TraceManyInstantEvents(int thread_id, int num_events, - WaitableEvent* task_complete_event) { + WaitableEvent* task_complete_event) { for (int i = 0; i < num_events; i++) { TRACE_EVENT_INSTANT2("all", "multi thread event", "thread", thread_id, @@ -357,8 +361,8 @@ void TraceManyInstantEvents(int thread_id, int num_events, } void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed, - const std::string& trace_string, - int num_threads, int num_events) { + int num_threads, + int num_events) { std::map<int, std::map<int, bool> > results; size_t trace_parsed_count = trace_parsed.GetSize(); @@ -406,7 +410,7 @@ TEST_F(TraceEventTestFixture, DataCaptured) { TraceLog::GetInstance()->SetEnabled(false); - ValidateAllTraceMacrosCreatedData(trace_parsed_, trace_string_); + ValidateAllTraceMacrosCreatedData(trace_parsed_); } // Test that categories work. @@ -687,7 +691,7 @@ TEST_F(TraceEventTestFixture, DataCapturedOnThread) { thread.Stop(); TraceLog::GetInstance()->SetEnabled(false); - ValidateAllTraceMacrosCreatedData(trace_parsed_, trace_string_); + ValidateAllTraceMacrosCreatedData(trace_parsed_); } // Test that data sent from multiple threads is gathered @@ -720,7 +724,7 @@ TEST_F(TraceEventTestFixture, DataCapturedManyThreads) { TraceLog::GetInstance()->SetEnabled(false); - ValidateInstantEventPresentOnEveryThread(trace_parsed_, trace_string_, + ValidateInstantEventPresentOnEveryThread(trace_parsed_, num_threads, num_events); } @@ -925,5 +929,27 @@ TEST_F(TraceEventTestFixture, DeepCopy) { EXPECT_EQ("val2", s); } +// Test that TraceResultBuffer outputs the correct result whether it is added +// in chunks or added all at once. +TEST_F(TraceEventTestFixture, TraceResultBuffer) { + ManualTestSetUp(); + + Clear(); + + trace_buffer_.Start(); + trace_buffer_.AddFragment("bla1"); + trace_buffer_.AddFragment("bla2"); + trace_buffer_.AddFragment("bla3,bla4"); + trace_buffer_.Finish(); + EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]"); + + Clear(); + + trace_buffer_.Start(); + trace_buffer_.AddFragment("bla1,bla2,bla3,bla4"); + trace_buffer_.Finish(); + EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]"); +} + } // namespace debug } // namespace base |