1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/trace_event/blame_context.h"
6
7 #include "base/strings/stringprintf.h"
8 #include "base/trace_event/trace_event.h"
9 #include "base/trace_event/traced_value.h"
10
11 namespace base {
12 namespace trace_event {
13
BlameContext(const char * category,const char * name,const char * type,const char * scope,int64_t id,const BlameContext * parent_context)14 BlameContext::BlameContext(const char* category,
15 const char* name,
16 const char* type,
17 const char* scope,
18 int64_t id,
19 const BlameContext* parent_context)
20 : category_(category),
21 name_(name),
22 type_(type),
23 scope_(scope),
24 id_(id),
25 parent_scope_(parent_context ? parent_context->scope() : nullptr),
26 parent_id_(parent_context ? parent_context->id() : 0),
27 category_group_enabled_(nullptr) {
28 DCHECK(!parent_context || !std::strcmp(name_, parent_context->name()))
29 << "Parent blame context must have the same name";
30 }
31
~BlameContext()32 BlameContext::~BlameContext() {
33 DCHECK(thread_checker_.CalledOnValidThread());
34 DCHECK(WasInitialized());
35 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_DELETE_OBJECT,
36 category_group_enabled_, type_, scope_, id_,
37 nullptr, TRACE_EVENT_FLAG_HAS_ID);
38 trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver(this);
39 }
40
Enter()41 void BlameContext::Enter() {
42 DCHECK(WasInitialized());
43 if (LIKELY(!*category_group_enabled_))
44 return;
45 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_ENTER_CONTEXT,
46 category_group_enabled_, name_, scope_, id_,
47 nullptr, TRACE_EVENT_FLAG_HAS_ID);
48 }
49
Leave()50 void BlameContext::Leave() {
51 DCHECK(WasInitialized());
52 if (LIKELY(!*category_group_enabled_))
53 return;
54 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_LEAVE_CONTEXT,
55 category_group_enabled_, name_, scope_, id_,
56 nullptr, TRACE_EVENT_FLAG_HAS_ID);
57 }
58
TakeSnapshot()59 void BlameContext::TakeSnapshot() {
60 DCHECK(thread_checker_.CalledOnValidThread());
61 DCHECK(WasInitialized());
62 if (LIKELY(!*category_group_enabled_))
63 return;
64 std::unique_ptr<trace_event::TracedValue> snapshot(
65 new trace_event::TracedValue);
66 AsValueInto(snapshot.get());
67 TraceArguments args("snapshot", std::move(snapshot));
68 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT,
69 category_group_enabled_, type_, scope_, id_,
70 &args, TRACE_EVENT_FLAG_HAS_ID);
71 }
72
OnTraceLogEnabled()73 void BlameContext::OnTraceLogEnabled() {
74 DCHECK(WasInitialized());
75 TakeSnapshot();
76 }
77
OnTraceLogDisabled()78 void BlameContext::OnTraceLogDisabled() {}
79
AsValueInto(trace_event::TracedValue * state)80 void BlameContext::AsValueInto(trace_event::TracedValue* state) {
81 DCHECK(WasInitialized());
82 if (!parent_id_)
83 return;
84 state->BeginDictionary("parent");
85 state->SetString("id_ref", StringPrintf("0x%" PRIx64, parent_id_));
86 state->SetString("scope", parent_scope_);
87 state->EndDictionary();
88 }
89
Initialize()90 void BlameContext::Initialize() {
91 DCHECK(thread_checker_.CalledOnValidThread());
92 category_group_enabled_ =
93 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_);
94 TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_CREATE_OBJECT,
95 category_group_enabled_, type_, scope_, id_,
96 nullptr, TRACE_EVENT_FLAG_HAS_ID);
97 trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver(
98 weak_factory_.GetWeakPtr());
99 TakeSnapshot();
100 }
101
WasInitialized() const102 bool BlameContext::WasInitialized() const {
103 return category_group_enabled_ != nullptr;
104 }
105
106 } // namespace trace_event
107 } // namespace base
108