1 //
2 // Copyright 2018 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef PXR_BASE_TRACE_REPORTER_H
26 #define PXR_BASE_TRACE_REPORTER_H
27 
28 #include "pxr/pxr.h"
29 
30 #include "pxr/base/trace/api.h"
31 #include "pxr/base/trace/event.h"
32 #include "pxr/base/trace/aggregateNode.h"
33 #include "pxr/base/trace/reporterBase.h"
34 
35 #include "pxr/base/tf/declarePtrs.h"
36 #include "pxr/base/tf/mallocTag.h"
37 #include "pxr/base/tf/staticTokens.h"
38 
39 #include <iosfwd>
40 #include <string>
41 
42 PXR_NAMESPACE_OPEN_SCOPE
43 
44 #define TRACE_REPORTER_TOKENS       \
45     ((warningString, "WARNING:"))
46 
47 TF_DECLARE_PUBLIC_TOKENS(TraceReporterTokens, TRACE_API, TRACE_REPORTER_TOKENS);
48 
49 
50 TF_DECLARE_WEAK_AND_REF_PTRS(TraceAggregateTree);
51 TF_DECLARE_WEAK_AND_REF_PTRS(TraceEventNode);
52 TF_DECLARE_WEAK_AND_REF_PTRS(TraceEventTree);
53 
54 TF_DECLARE_WEAK_AND_REF_PTRS(TraceReporter);
55 
56 class TraceCollectionAvailable;
57 
58 ////////////////////////////////////////////////////////////////////////////////
59 /// \class TraceReporter
60 ///
61 /// This class converts streams of TraceEvent objects into call trees which
62 /// can then be used as a data source to a GUI or written out to a file.
63 ///
64 class TraceReporter :
65     public TraceReporterBase {
66 public:
67 
68     TF_MALLOC_TAG_NEW("Trace", "TraceReporter");
69 
70     using This = TraceReporter;
71     using ThisPtr = TraceReporterPtr;
72     using ThisRefPtr = TraceReporterRefPtr;
73 
74     using Event = TraceEvent;
75     using TimeStamp = TraceEvent::TimeStamp;
76     using CounterMap = TfHashMap<TfToken, double, TfToken::HashFunctor>;
77 
78     /// Create a new reporter with \a label and \a dataSource.
New(const std::string & label,DataSourcePtr dataSource)79     static ThisRefPtr New(const std::string& label,
80                           DataSourcePtr dataSource) {
81         return TfCreateRefPtr(new This(label, std::move(dataSource)));
82     }
83 
84     /// Create a new reporter with \a label and no data source.
New(const std::string & label)85     static ThisRefPtr New(const std::string& label) {
86         return TfCreateRefPtr(new This(label, nullptr));
87     }
88 
89     /// Returns the global reporter.
90     TRACE_API static TraceReporterPtr GetGlobalReporter();
91 
92     /// Destructor.
93     TRACE_API virtual ~TraceReporter();
94 
95     /// Return the label associated with this reporter.
GetLabel()96     const std::string& GetLabel() {
97         return _label;
98     }
99 
100     /// \name Report Generation.
101     /// @{
102 
103     /// Generates a report to the ostream \a s, dividing all times by
104     /// \a iterationCount.
105     TRACE_API void Report(
106         std::ostream &s,
107         int iterationCount=1);
108 
109     /// Generates a report of the times to the ostream \a s.
110     TRACE_API void ReportTimes(std::ostream &s);
111 
112     /// Generates a timeline trace report suitable for viewing in
113     /// Chrome's trace viewer.
114     TRACE_API void ReportChromeTracing(std::ostream &s);
115 
116     /// @}
117 
118     /// Returns the root node of the aggregated call tree.
119     TRACE_API TraceAggregateNodePtr GetAggregateTreeRoot();
120 
121     /// Returns the root node of the call tree.
122     TRACE_API TraceEventNodeRefPtr GetEventRoot();
123 
124     /// Returns the event call tree
125     TRACE_API TraceEventTreeRefPtr GetEventTree();
126 
127     /// \name Counters
128     /// @{
129 
130     /// Returns a map of counters (counter keys), associated with their total
131     /// accumulated value. Each individual event node in the tree may also hold
132     /// on to an inclusive and exclusive value for the given counter.
133     TRACE_API const CounterMap & GetCounters() const;
134 
135     /// Returns the numeric index associated with a counter key. Counter values
136     /// on the event nodes will have to be looked up by the numeric index.
137     TRACE_API int GetCounterIndex(const TfToken &key) const;
138 
139     /// Add a counter to the reporter. This method can be used to restore a
140     /// previous trace state and tree. Note, that the counter being added must
141     /// have a unique key and index. The method will return false if a key or
142     /// index already exists.
143     TRACE_API bool AddCounter(const TfToken &key, int index, double totalValue);
144 
145     /// @}
146 
147     /// This fully re-builds the event and aggregate trees from whatever the
148     /// current collection holds.  It is ok to call this multiple times in case
149     /// the collection gets appended on inbetween.
150     ///
151     /// If we want to have multiple reporters per collector, this will need to
152     /// be changed so that all reporters reporting on a collector update their
153     /// respective trees.
154     TRACE_API void UpdateTraceTrees();
155 
156     /// Clears event tree and counters.
157     TRACE_API void ClearTree();
158 
159     /// \name Report options.
160     /// @{
161 
162     /// This affects only stack trace event reporting.  If \c true then all
163     /// events in a function are grouped together otherwise events are split
164     /// out by address.
165     TRACE_API void SetGroupByFunction(bool);
166 
167     /// Returns the current group-by-function state.
168     TRACE_API bool GetGroupByFunction() const;
169 
170     /// When stack trace event reporting, this sets whether or not recursive
171     /// calls are folded in the output.  Recursion folding is useful when
172     /// the stacks contain deep recursive structures.
173     TRACE_API void SetFoldRecursiveCalls(bool);
174 
175     /// Returns the current setting for recursion folding for stack trace
176     /// event reporting.
177     TRACE_API bool GetFoldRecursiveCalls() const;
178 
179     /// @}
180 
181     /// Creates a valid TraceAggregateNode::Id object.
182     /// This should be used by very few clients for certain special cases.
183     /// For most cases, the TraceAggregateNode::Id object should be created and
184     /// populated internally within the Reporter object itself.
185     TRACE_API static TraceAggregateNode::Id CreateValidEventId();
186 
187 protected:
188 
189     TRACE_API TraceReporter(const std::string& label,
190                    DataSourcePtr dataSource);
191 
192 private:
193     void _ProcessCollection(const TraceReporterBase::CollectionPtr&) override;
194     void _RebuildEventAndAggregateTrees();
195     void _PrintTimes(std::ostream &s);
196 
197 private:
198     std::string _label;
199 
200     bool _groupByFunction;
201     bool _foldRecursiveCalls;
202 
203     TraceAggregateTreeRefPtr _aggregateTree;
204     TraceEventTreeRefPtr _eventTree;
205 };
206 
207 PXR_NAMESPACE_CLOSE_SCOPE
208 
209 #endif // PXR_BASE_TRACE_REPORTER_H
210