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