This document is for a version of USD that is under development. See this page for the current release.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Trace Details

The trace library consists of two main components:

  • TraceCollector is a singleton thread-safe recorder of events.
  • TraceReporter is a class which processes events to create meaningful views of the data.

The TraceCollector class can be used as a recorder for custom events in an application without using TRACE_ macros.

Contents

Recording Events with TraceCollector

Most of the time TRACE macros are sufficient for instrumentation, however if something more specific is required, the TraceCollector class can be used directly without using TRACE_ macros. The macros simply invoke API on the TraceCollector.

Each TraceEvent contains a TraceCategoryId. These ids allow for the events to be filtered. Events recorded by TRACE_ macros have their TraceCategoryId set to TraceCategory::Default.

Trace categories consist of two parts, a TraceCategoryId, and a function to determine whether or not events for the category should be recorded.

TraceCategory::CreateTraceCategoryId can create a TraceCategoryId from hashing a string literal. This is not guaranteed to be unique.

All of the methods in the TraceCollector class which record events take an optional Category template parameter. The Category template parameter determines if the event will be recorded and the TraceCategoryId that will be stored in the event.

A valid Category template parameter must have have the following:

  • A thread-safe static method named GetId which returns a TraceCategoryId.
  • A thread-safe static method named IsEnabled which returns a bool.

If the Category template parameter is not specified, TraceCollector uses TraceCollector::DefaultCategory.

Example of recording an event with a custom category.

// Define a custom category.
struct CustomPerfCounterCategory
{
// TraceCollector function calls using this category will store events with this TraceCategoryId.
static constexpr TraceCategoryId GetId() {
return TraceCategory::CreateTraceCategoryId("CustomPerfCounter");
}
// TraceCollector function calls using this category will store events only if this function returns true.
static bool IsEnabled();
};
int main(int argc, char *argv[])
{
// Register a name with the id.
TraceCategory::GetInstance().RegisterCategory(PerfCategory::GetId(), "CustomPerfCounter");
// Record a counter delta event with the CustomPerfCounterCategory.
TraceCollector::GetInstance().RecordCounterDelta<CustomPerfCounterCategory>("A Counter", 1);
}
uint32_t TraceCategoryId
Categories that a TraceReporter can use to filter events.
Definition: category.h:27
static constexpr TraceCategoryId CreateTraceCategoryId(const char(&str)[N])
Computes an id for the given a string literal str.
Definition: category.h:41
static TRACE_API TraceCategory & GetInstance()
Singleton accessor.
TRACE_API void RegisterCategory(TraceCategoryId id, const std::string &name)
Associates the id with name.
void RecordCounterDelta(const TraceKey &key, double delta)
Record a counter delta for a name key if Category is enabled.
Definition: collector.h:337
static TRACE_API TraceCollector & GetInstance()
Returns the singleton instance.
Definition: collector.h:67

Accessing Trace Data

Access to recorded TraceEvent objects is available through the TraceCollection class and TraceCollectionAvailable notice. When the TraceCollector produces data through the TraceCollector::CreateCollection() method, it will send a TraceCollectionAvailable notice. To access individual events in a TraceCollection instance, the TraceCollection::Visitor interface can be used. The TraceReporterBase class encapsulates logic for handling TraceCollectionAvailable notices.

Example of using TraceReporterBase class and TraceCollection::Visitor interface.

class CustomTraceEventProcessor :
public:
CustomTraceEventProcessor();
// TraceCollection::Visitor interface
virtual bool AcceptsCategory(TraceCategoryId id) override
virtual void OnEvent(
const TraceThreadId&, const TfToken& k, const TraceEvent& e) override;
virtual void OnBeginCollection() override;
virtual void OnEndCollection() override;
virtual void OnBeginThread(const TraceThreadId&) override;
virtual void OnEndThread(const TraceThreadId&) override;
void Update() {
//Call base class update to get the latest data from TraceCollector.
}
protected:
// This will be called by the TraceReporterBase::_Update() for each
// TraceCollection received.
void _ProcessCollection(const CollectionPtr& collection) override {
// Iterate over the TraceCollection using the TraceCollection::Visitor
// interface.
collection->Iterate(*this);
}
};
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:71
This interface provides a way to access data a TraceCollection.
Definition: collection.h:66
virtual bool AcceptsCategory(TraceCategoryId categoryId)=0
Called before an event with categoryId is visited.
virtual void OnBeginCollection()=0
Called at the beginning of an iteration.
virtual void OnBeginThread(const TraceThreadId &threadId)=0
Called before the first event of from the thread with threadId is encountered.
virtual void OnEndThread(const TraceThreadId &threadId)=0
Called after the last event of from the thread with threadId is encountered.
virtual void OnEndCollection()=0
Called at the end of an iteration.
virtual void OnEvent(const TraceThreadId &threadId, const TfToken &key, const TraceEvent &event)=0
Called for every event event with key on thread threadId if AcceptsCategory returns true.
This represents an event recorded by a TraceCollector.
Definition: event.h:30
This class is a base class for report implementations.
Definition: reporterBase.h:36
TRACE_API void _Update()
Gets the latest data from the TraceCollector singleton and processes all collections that have been r...
virtual void _ProcessCollection(const CollectionPtr &)=0
Called once per collection from _Update()
This class represents an identifier for a thread.
Definition: threads.h:23

Example of Custom Category and Reporter

#include "pxr/base/trace/collector.h"
#include "pxr/base/trace/reporterBase.h"
#include <atomic>
#include <map>
PXR_NAMESPACE_USING_DIRECTIVE
// Custom Trace category.
struct CustomPerfCounterCategory
{
// TraceCollector function calls using this category will store events with this TraceCategoryId.
static constexpr TraceCategoryId GetId() {
return TraceCategory::CreateTraceCategoryId("CustomPerfCounter");
}
// TraceCollector function calls using this category will store events only if this function return true.
static bool IsEnabled() {
return _isEnabled.load(std::memory_order_acquire);
}
static void Enable() {
_isEnabled.store(true, std::memory_order_release);
}
static void Disable() {
_isEnabled.store(false, std::memory_order_release);
}
private:
static std::atomic<bool> _isEnabled;
};
// Helper macros
#define CUSTOM_PERF_COUNTER(name, value) \
_CUSTOM_PERF_COUNTER_INSTANCE(__LINE__, name, value)
#define _CUSTOM_PERF_COUNTER_INSTANCE(inst, name, value) \
static constexpr TraceStaticKeyData customCounterKey ## inst (name); \
TraceCollector::GetInstance().RecordCounterDelta<CustomPerfCounterCategory>(customCounterKey ## inst, value);
// Custom Trace reporter.
class CustomTraceEventProcessor :
public:
CustomTraceEventProcessor(TraceReporterDataSourceBaseRefPtr dataSource)
: TraceReporterBase(dataSource)
{}
void Update() {
//Call base class update to get the latest data from TraceCollector.
}
// TraceCollection::Visitor interface
// Only visit events marked with the custom category.
virtual bool AcceptsCategory(TraceCategoryId id) override {
return id == CustomPerfCounterCategory::GetId();
}
// Accumulate counter deltas.
virtual void OnEvent(
const TraceThreadId&, const TfToken& k, const TraceEvent& e) override {
_counters[k] += e.GetCounterValue();
}
}
virtual void OnBeginCollection() override {}
virtual void OnEndCollection() override {}
virtual void OnBeginThread(const TraceThreadId&) override {}
virtual void OnEndThread(const TraceThreadId&) override {}
protected:
// This will be called by the TraceReporterBase::_Update() for each
// TraceCollection received.
void _ProcessCollection(const CollectionPtr& collection) override {
// Iterate over the TraceCollection using the TraceCollection::Visitor
// interface.
collection->Iterate(*this);
}
std::map<TfToken, double> _counters;
};
// Instrumented code
void Foo()
{
CUSTOM_PERF_COUNTER("Foo Counter",1);
}
std::atomic<bool> CustomPerfCounterCategory::_isEnabled(false);
int main(int argc, char *argv[])
{
// Register a name with the id.
CustomPerfCounterCategory::GetId(), "CustomPerfCounter");
// Make sure an instance of the processor is available to receive notices.
CustomTraceEventProcessor eventProcessor(
// Enable the recording of events for the category.
CustomPerfCounterCategory::Enable();
// Call instrumented code.
Foo();
// Disable the recording of events for the category.
CustomPerfCounterCategory::Disable();
// Process the recorded events.
eventProcessor.Update();
}
TRACE_API double GetCounterValue() const
Return the counter value associated with this event.
TRACE_API EventType GetType() const
Returns the type of the event.
@ CounterDelta
The event represents a change in a counter.
static ThisRefPtr New()
Creates a new TraceReporterDataSourceCollector.