Commit 9fb3fa20 authored by nednguyen@google.com's avatar nednguyen@google.com

Add metadata that report whether the buffer was full, and the timestamp when that happens.

BUG=393750

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284264 0039d316-1c4b-4281-b951-d872f2087c98
parent 350887d8
...@@ -289,10 +289,11 @@ class TraceBufferRingBuffer : public TraceBuffer { ...@@ -289,10 +289,11 @@ class TraceBufferRingBuffer : public TraceBuffer {
class TraceBufferVector : public TraceBuffer { class TraceBufferVector : public TraceBuffer {
public: public:
TraceBufferVector() TraceBufferVector(size_t max_chunks)
: in_flight_chunk_count_(0), : in_flight_chunk_count_(0),
current_iteration_index_(0) { current_iteration_index_(0),
chunks_.reserve(kTraceEventVectorBufferChunks); max_chunks_(max_chunks) {
chunks_.reserve(max_chunks_);
} }
virtual scoped_ptr<TraceBufferChunk> GetChunk(size_t* index) OVERRIDE { virtual scoped_ptr<TraceBufferChunk> GetChunk(size_t* index) OVERRIDE {
...@@ -318,7 +319,7 @@ class TraceBufferVector : public TraceBuffer { ...@@ -318,7 +319,7 @@ class TraceBufferVector : public TraceBuffer {
} }
virtual bool IsFull() const OVERRIDE { virtual bool IsFull() const OVERRIDE {
return chunks_.size() >= kTraceEventVectorBufferChunks; return chunks_.size() >= max_chunks_;
} }
virtual size_t Size() const OVERRIDE { virtual size_t Size() const OVERRIDE {
...@@ -327,7 +328,7 @@ class TraceBufferVector : public TraceBuffer { ...@@ -327,7 +328,7 @@ class TraceBufferVector : public TraceBuffer {
} }
virtual size_t Capacity() const OVERRIDE { virtual size_t Capacity() const OVERRIDE {
return kTraceEventVectorBufferChunks * kTraceBufferChunkSize; return max_chunks_ * kTraceBufferChunkSize;
} }
virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) OVERRIDE { virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) OVERRIDE {
...@@ -357,6 +358,7 @@ class TraceBufferVector : public TraceBuffer { ...@@ -357,6 +358,7 @@ class TraceBufferVector : public TraceBuffer {
private: private:
size_t in_flight_chunk_count_; size_t in_flight_chunk_count_;
size_t current_iteration_index_; size_t current_iteration_index_;
size_t max_chunks_;
ScopedVector<TraceBufferChunk> chunks_; ScopedVector<TraceBufferChunk> chunks_;
DISALLOW_COPY_AND_ASSIGN(TraceBufferVector); DISALLOW_COPY_AND_ASSIGN(TraceBufferVector);
...@@ -1501,7 +1503,11 @@ TraceBuffer* TraceLog::CreateTraceBuffer() { ...@@ -1501,7 +1503,11 @@ TraceBuffer* TraceLog::CreateTraceBuffer() {
return new TraceBufferRingBuffer(kMonitorTraceEventBufferChunks); return new TraceBufferRingBuffer(kMonitorTraceEventBufferChunks);
else if (options & ECHO_TO_CONSOLE) else if (options & ECHO_TO_CONSOLE)
return new TraceBufferRingBuffer(kEchoToConsoleTraceEventBufferChunks); return new TraceBufferRingBuffer(kEchoToConsoleTraceEventBufferChunks);
return new TraceBufferVector(); return CreateTraceBufferVectorOfSize(kTraceEventVectorBufferChunks);
}
TraceBuffer* TraceLog::CreateTraceBufferVectorOfSize(size_t max_chunks) {
return new TraceBufferVector(max_chunks);
} }
TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
...@@ -1533,8 +1539,12 @@ TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked( ...@@ -1533,8 +1539,12 @@ TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
void TraceLog::CheckIfBufferIsFullWhileLocked() { void TraceLog::CheckIfBufferIsFullWhileLocked() {
lock_.AssertAcquired(); lock_.AssertAcquired();
if (logged_events_->IsFull()) if (logged_events_->IsFull()) {
if (buffer_limit_reached_timestamp_.is_null()) {
buffer_limit_reached_timestamp_ = OffsetNow();
}
SetDisabledWhileLocked(); SetDisabledWhileLocked();
}
} }
void TraceLog::SetEventCallbackEnabled(const CategoryFilter& category_filter, void TraceLog::SetEventCallbackEnabled(const CategoryFilter& category_filter,
...@@ -2109,6 +2119,15 @@ void TraceLog::AddMetadataEventsWhileLocked() { ...@@ -2109,6 +2119,15 @@ void TraceLog::AddMetadataEventsWhileLocked() {
"thread_name", "name", "thread_name", "name",
it->second); it->second);
} }
// If buffer is full, add a metadata record to report this.
if (!buffer_limit_reached_timestamp_.is_null()) {
InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
current_thread_id,
"trace_buffer_overflowed",
"overflowed_at_ts",
buffer_limit_reached_timestamp_);
}
} }
void TraceLog::WaitSamplingEventForTesting() { void TraceLog::WaitSamplingEventForTesting() {
......
...@@ -605,6 +605,8 @@ class BASE_EXPORT TraceLog { ...@@ -605,6 +605,8 @@ class BASE_EXPORT TraceLog {
TraceBufferRingBufferHalfIteration); TraceBufferRingBufferHalfIteration);
FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
TraceBufferRingBufferFullIteration); TraceBufferRingBufferFullIteration);
FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
TraceBufferVectorReportFull);
// This allows constructor and destructor to be private and usable only // This allows constructor and destructor to be private and usable only
// by the Singleton class. // by the Singleton class.
...@@ -632,6 +634,7 @@ class BASE_EXPORT TraceLog { ...@@ -632,6 +634,7 @@ class BASE_EXPORT TraceLog {
TraceBuffer* trace_buffer() const { return logged_events_.get(); } TraceBuffer* trace_buffer() const { return logged_events_.get(); }
TraceBuffer* CreateTraceBuffer(); TraceBuffer* CreateTraceBuffer();
TraceBuffer* CreateTraceBufferVectorOfSize(size_t max_chunks);
std::string EventToConsoleMessage(unsigned char phase, std::string EventToConsoleMessage(unsigned char phase,
const TimeTicks& timestamp, const TimeTicks& timestamp,
...@@ -692,6 +695,8 @@ class BASE_EXPORT TraceLog { ...@@ -692,6 +695,8 @@ class BASE_EXPORT TraceLog {
base::hash_map<int, std::stack<TimeTicks> > thread_event_start_times_; base::hash_map<int, std::stack<TimeTicks> > thread_event_start_times_;
base::hash_map<std::string, int> thread_colors_; base::hash_map<std::string, int> thread_colors_;
TimeTicks buffer_limit_reached_timestamp_;
// XORed with TraceID to make it unlikely to collide with other processes. // XORed with TraceID to make it unlikely to collide with other processes.
unsigned long long process_id_hash_; unsigned long long process_id_hash_;
......
...@@ -2415,6 +2415,53 @@ TEST_F(TraceEventCallbackTest, TraceEventCallbackAndRecordingDuration) { ...@@ -2415,6 +2415,53 @@ TEST_F(TraceEventCallbackTest, TraceEventCallbackAndRecordingDuration) {
VerifyCollectedEvent(5, TRACE_EVENT_PHASE_END, "callback", "duration1"); VerifyCollectedEvent(5, TRACE_EVENT_PHASE_END, "callback", "duration1");
} }
TEST_F(TraceEventTestFixture, TraceBufferVectorReportFull) {
TraceLog* trace_log = TraceLog::GetInstance();
trace_log->SetEnabled(CategoryFilter("*"),
base::debug::TraceLog::RECORDING_MODE,
TraceLog::RECORD_UNTIL_FULL);
trace_log->logged_events_.reset(
trace_log->CreateTraceBufferVectorOfSize(100));
do {
TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(
"all", "with_timestamp", 0, 0,
TimeTicks::NowFromSystemTraceTime().ToInternalValue());
TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(
"all", "with_timestamp", 0, 0,
TimeTicks::NowFromSystemTraceTime().ToInternalValue());
} while (!trace_log->BufferIsFull());
EndTraceAndFlush();
const DictionaryValue* trace_full_metadata = NULL;
trace_full_metadata = FindTraceEntry(trace_parsed_,
"overflowed_at_ts");
std::string phase;
double buffer_limit_reached_timestamp = 0;
EXPECT_TRUE(trace_full_metadata);
EXPECT_TRUE(trace_full_metadata->GetString("ph", &phase));
EXPECT_EQ("M", phase);
EXPECT_TRUE(trace_full_metadata->GetDouble(
"args.overflowed_at_ts", &buffer_limit_reached_timestamp));
EXPECT_DOUBLE_EQ(
static_cast<double>(
trace_log->buffer_limit_reached_timestamp_.ToInternalValue()),
buffer_limit_reached_timestamp);
// Test that buffer_limit_reached_timestamp's value is near to the timestamp
// of the last trace event.
DropTracedMetadataRecords();
const DictionaryValue* last_trace_event = NULL;
double last_trace_event_timestamp = 0;
EXPECT_TRUE(trace_parsed_.GetDictionary(trace_parsed_.GetSize() - 1,
&last_trace_event));
EXPECT_TRUE(last_trace_event->GetDouble("ts", &last_trace_event_timestamp));
// The difference between the two timestamps should be less than 50ms.
EXPECT_NEAR(last_trace_event_timestamp, buffer_limit_reached_timestamp, 50);
}
TEST_F(TraceEventTestFixture, TraceBufferRingBufferGetReturnChunk) { TEST_F(TraceEventTestFixture, TraceBufferRingBufferGetReturnChunk) {
TraceLog::GetInstance()->SetEnabled(CategoryFilter("*"), TraceLog::GetInstance()->SetEnabled(CategoryFilter("*"),
base::debug::TraceLog::RECORDING_MODE, base::debug::TraceLog::RECORDING_MODE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment