Skip to content

Commit

Permalink
Added a new CompressedStringDataSink for compressing traces via the t…
Browse files Browse the repository at this point in the history
…race controller.

Also added a TraceDataEndpoint class that I'm thinking can be used to decouple the creation of the final trace (since there's some special logic in there for adding '{}'s and some specific names like 'traceEvent') from where it gets written. This is used right now by the new BackgroundTracingManager for Slow Reports and Deep Reports, but we could also refactor the existing String and File sinks this way as a follow up CL (WIP here: https://codereview.chromium.org/1002103004/).

Then for Deep Reports we can specify the data sink like so:

TraceController::DisableRecording(
  TraceController::CreateCompressedStringSink(
    TraceController::CreateFileEndpoint(...)));

Review URL: https://codereview.chromium.org/1088673003

Cr-Commit-Position: refs/heads/master@{#326783}
  • Loading branch information
simonhatch authored and Commit bot committed Apr 24, 2015
1 parent 8c1791c commit 329f14f
Show file tree
Hide file tree
Showing 5 changed files with 368 additions and 133 deletions.
68 changes: 68 additions & 0 deletions content/browser/tracing/tracing_controller_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "base/files/file_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
Expand All @@ -18,6 +19,37 @@ using base::trace_event::RECORD_UNTIL_FULL;

namespace content {

class TracingControllerTestEndpoint
: public TracingController::TraceDataEndpoint {
public:
TracingControllerTestEndpoint(
base::Callback<void(base::RefCountedString*)> done_callback)
: done_callback_(done_callback) {}

void ReceiveTraceChunk(const std::string& chunk) override {
EXPECT_FALSE(chunk.empty());
trace_ += chunk;
}

void ReceiveTraceFinalContents(const std::string& contents) override {
EXPECT_EQ(trace_, contents);

std::string tmp = contents;
scoped_refptr<base::RefCountedString> chunk_ptr =
base::RefCountedString::TakeString(&tmp);

BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(done_callback_, chunk_ptr));
}

protected:
~TracingControllerTestEndpoint() override {}

std::string trace_;
base::Callback<void(base::RefCountedString*)> done_callback_;
};

class TracingControllerTest : public ContentBrowserTest {
public:
TracingControllerTest() {}
Expand Down Expand Up @@ -153,6 +185,37 @@ class TracingControllerTest : public ContentBrowserTest {
}
}

void TestEnableAndDisableRecordingCompressed() {
Navigate(shell());

TracingController* controller = TracingController::GetInstance();

{
base::RunLoop run_loop;
TracingController::EnableRecordingDoneCallback callback =
base::Bind(&TracingControllerTest::EnableRecordingDoneCallbackTest,
base::Unretained(this), run_loop.QuitClosure());
bool result = controller->EnableRecording(CategoryFilter(),
TraceOptions(), callback);
ASSERT_TRUE(result);
run_loop.Run();
EXPECT_EQ(enable_recording_done_callback_count(), 1);
}

{
base::RunLoop run_loop;
base::Callback<void(base::RefCountedString*)> callback = base::Bind(
&TracingControllerTest::DisableRecordingStringDoneCallbackTest,
base::Unretained(this), run_loop.QuitClosure());
bool result = controller->DisableRecording(
TracingController::CreateCompressedStringSink(
new TracingControllerTestEndpoint(callback)));
ASSERT_TRUE(result);
run_loop.Run();
EXPECT_EQ(disable_recording_done_callback_count(), 1);
}
}

void TestEnableAndDisableRecordingFile(
const base::FilePath& result_file_path) {
Navigate(shell());
Expand Down Expand Up @@ -316,6 +379,11 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest,
EXPECT_EQ(file_path.value(), last_actual_recording_file_path().value());
}

IN_PROC_BROWSER_TEST_F(TracingControllerTest,
EnableAndDisableRecordingWithCompression) {
TestEnableAndDisableRecordingCompressed();
}

IN_PROC_BROWSER_TEST_F(TracingControllerTest,
EnableAndDisableRecordingWithEmptyFileAndNullCallback) {
Navigate(shell());
Expand Down
133 changes: 0 additions & 133 deletions content/browser/tracing/tracing_controller_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,127 +35,6 @@ namespace {
base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
LAZY_INSTANCE_INITIALIZER;

class FileTraceDataSink : public TracingController::TraceDataSink {
public:
explicit FileTraceDataSink(const base::FilePath& trace_file_path,
const base::Closure& callback)
: file_path_(trace_file_path),
completion_callback_(callback),
file_(NULL) {}

void AddTraceChunk(const std::string& chunk) override {
std::string tmp = chunk;
scoped_refptr<base::RefCountedString> chunk_ptr =
base::RefCountedString::TakeString(&tmp);
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(
&FileTraceDataSink::AddTraceChunkOnFileThread, this, chunk_ptr));
}
void SetSystemTrace(const std::string& data) override {
system_trace_ = data;
}
void Close() override {
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&FileTraceDataSink::CloseOnFileThread, this));
}

private:
~FileTraceDataSink() override { DCHECK(file_ == NULL); }

void AddTraceChunkOnFileThread(
const scoped_refptr<base::RefCountedString> chunk) {
if (file_ != NULL)
fputc(',', file_);
else if (!OpenFileIfNeededOnFileThread())
return;
ignore_result(fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()),
1, file_));
}

bool OpenFileIfNeededOnFileThread() {
if (file_ != NULL)
return true;
file_ = base::OpenFile(file_path_, "w");
if (file_ == NULL) {
LOG(ERROR) << "Failed to open " << file_path_.value();
return false;
}
const char preamble[] = "{\"traceEvents\": [";
ignore_result(fwrite(preamble, strlen(preamble), 1, file_));
return true;
}

void CloseOnFileThread() {
if (OpenFileIfNeededOnFileThread()) {
fputc(']', file_);
if (!system_trace_.empty()) {
const char systemTraceEvents[] = ",\"systemTraceEvents\": ";
ignore_result(fwrite(systemTraceEvents, strlen(systemTraceEvents),
1, file_));
ignore_result(fwrite(system_trace_.c_str(),
strlen(system_trace_.c_str()), 1, file_));
}
fputc('}', file_);
base::CloseFile(file_);
file_ = NULL;
}
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&FileTraceDataSink::FinalizeOnUIThread, this));
}

void FinalizeOnUIThread() { completion_callback_.Run(); }

base::FilePath file_path_;
base::Closure completion_callback_;
FILE* file_;
std::string system_trace_;

DISALLOW_COPY_AND_ASSIGN(FileTraceDataSink);
};

class StringTraceDataSink : public TracingController::TraceDataSink {
public:
typedef base::Callback<void(base::RefCountedString*)> CompletionCallback;

explicit StringTraceDataSink(CompletionCallback callback)
: completion_callback_(callback) {}

// TracingController::TraceDataSink implementation
void AddTraceChunk(const std::string& chunk) override {
if (!trace_.empty())
trace_ += ",";
trace_ += chunk;
}
void SetSystemTrace(const std::string& data) override {
system_trace_ = data;
}
void Close() override {
std::string result = "{\"traceEvents\":[" + trace_ + "]";
if (!system_trace_.empty())
result += ",\"systemTraceEvents\": " + system_trace_;
result += "}";

scoped_refptr<base::RefCountedString> str =
base::RefCountedString::TakeString(&result);
completion_callback_.Run(str.get());
}

private:
~StringTraceDataSink() override {}

std::string trace_;
std::string system_trace_;
CompletionCallback completion_callback_;

DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink);
};

} // namespace

TracingController* TracingController::GetInstance() {
Expand Down Expand Up @@ -427,18 +306,6 @@ bool TracingControllerImpl::DisableMonitoring(
return true;
}

scoped_refptr<TracingController::TraceDataSink>
TracingController::CreateStringSink(
const base::Callback<void(base::RefCountedString*)>& callback) {
return new StringTraceDataSink(callback);
}

scoped_refptr<TracingController::TraceDataSink>
TracingController::CreateFileSink(const base::FilePath& file_path,
const base::Closure& callback) {
return new FileTraceDataSink(file_path, callback);
}

void TracingControllerImpl::OnDisableMonitoringDone(
const DisableMonitoringDoneCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
Expand Down
Loading

0 comments on commit 329f14f

Please sign in to comment.