summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-24 16:34:08 +0000
committerjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-24 16:34:08 +0000
commit91ea6343d74a2cd7457d2a8b1521e3fd4724d7f5 (patch)
treec28b5e27b1d369c35405b53f603e7a9796089ac8 /base
parent7d1208ce239e0298f016e6839f25551975de2269 (diff)
downloadchromium_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.cc45
-rw-r--r--base/debug/trace_event.h48
-rw-r--r--base/debug/trace_event_unittest.cc54
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