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 #ifndef BASE_TRACE_EVENT_BLAME_CONTEXT_H_
6 #define BASE_TRACE_EVENT_BLAME_CONTEXT_H_
7 
8 #include <inttypes.h>
9 
10 #include "base/base_export.h"
11 #include "base/macros.h"
12 #include "base/threading/thread_checker.h"
13 #include "base/trace_event/trace_log.h"
14 
15 namespace base {
16 namespace trace_event {
17 class TracedValue;
18 }
19 
20 namespace trace_event {
21 
22 // A blame context represents a logical unit to which we want to attribute
23 // different costs (e.g., CPU, network, or memory usage). An example of a blame
24 // context is an <iframe> element on a web page. Different subsystems can
25 // "enter" and "leave" blame contexts to indicate that they are doing work which
26 // should be accounted against this blame context.
27 //
28 // A blame context can optionally have a parent context, forming a blame context
29 // tree. When work is attributed to a particular blame context, it is considered
30 // to count against all of that context's children too. This is useful when work
31 // cannot be exactly attributed into a more specific context. For example,
32 // Javascript garbage collection generally needs to inspect all objects on a
33 // page instead looking at each <iframe> individually. In this case the work
34 // should be attributed to a blame context which is the parent of all <iframe>
35 // blame contexts.
36 class BASE_EXPORT BlameContext
37     : public trace_event::TraceLog::AsyncEnabledStateObserver {
38  public:
39   // Construct a blame context belonging to the blame context tree |name|, using
40   // the tracing category |category|, identified by |id| from the |scope|
41   // namespace. |type| identifies the type of this object snapshot in the blame
42   // context tree. |parent_context| is the parent of this blame context or
43   // null. Note that all strings must have application lifetime.
44   //
45   // For example, a blame context which represents a specific <iframe> in a
46   // browser frame tree could be specified with:
47   //
48   //   category="blink",
49   //   name="FrameTree",
50   //   type="IFrame",
51   //   scope="IFrameIdentifier",
52   //   id=1234.
53   //
54   // Each <iframe> blame context could have another <iframe> context as a
55   // parent, or a top-level context which represents the entire browser:
56   //
57   //   category="blink",
58   //   name="FrameTree",
59   //   type="Browser",
60   //   scope="BrowserIdentifier",
61   //   id=1.
62   //
63   // Note that the |name| property is identical, signifying that both context
64   // types are part of the same tree.
65   //
66   BlameContext(const char* category,
67                const char* name,
68                const char* type,
69                const char* scope,
70                int64_t id,
71                const BlameContext* parent_context);
72   ~BlameContext() override;
73 
74   // Initialize the blame context, automatically taking a snapshot if tracing is
75   // enabled. Must be called before any other methods on this class.
76   void Initialize();
77 
78   // Indicate that the current thread is now doing work which should count
79   // against this blame context.  This function is allowed to be called in a
80   // thread different from where the blame context was created; However, any
81   // client doing that must be fully responsible for ensuring thready safety.
82   void Enter();
83 
84   // Leave and stop doing work for a previously entered blame context. If
85   // another blame context belonging to the same tree was entered prior to this
86   // one, it becomes the active blame context for this thread again.  Similar
87   // to Enter(), this function can be called in a thread different from where
88   // the blame context was created, and the same requirement on thread safety
89   // must be satisfied.
90   void Leave();
91 
92   // Record a snapshot of the blame context. This is normally only needed if a
93   // blame context subclass defines custom properties (see AsValueInto) and one
94   // or more of those properties have changed.
95   void TakeSnapshot();
96 
category()97   const char* category() const { return category_; }
name()98   const char* name() const { return name_; }
type()99   const char* type() const { return type_; }
scope()100   const char* scope() const { return scope_; }
id()101   int64_t id() const { return id_; }
102 
103   // trace_event::TraceLog::EnabledStateObserver implementation:
104   void OnTraceLogEnabled() override;
105   void OnTraceLogDisabled() override;
106 
107  protected:
108   // Serialize the properties of this blame context into |state|. Subclasses can
109   // override this method to record additional properties (e.g, the URL for an
110   // <iframe> blame context). Note that an overridden implementation must still
111   // call this base method.
112   virtual void AsValueInto(trace_event::TracedValue* state);
113 
114  private:
115   bool WasInitialized() const;
116 
117   // The following string pointers have application lifetime.
118   const char* category_;
119   const char* name_;
120   const char* type_;
121   const char* scope_;
122   const int64_t id_;
123 
124   const char* parent_scope_;
125   const int64_t parent_id_;
126 
127   const unsigned char* category_group_enabled_;
128 
129   ThreadChecker thread_checker_;
130   WeakPtrFactory<BlameContext> weak_factory_{this};
131 
132   DISALLOW_COPY_AND_ASSIGN(BlameContext);
133 };
134 
135 }  // namespace trace_event
136 }  // namespace base
137 
138 #endif  // BASE_TRACE_EVENT_BLAME_CONTEXT_H_
139