An example of an instrumented C++ program is available for reference; you can cut and paste snippets from there to instrument your program. The example uses multiple threads producing different trace events.
Here we'll explain the basic principles behind C++-level generation of TuningFork traces and how to use the individual APIs.
ILogger *logger = LoggerFactory::makeFileLogger(portLibrary, fileNameOrPortNumber);where
filename
is the String with the filename. The
generated trace can then be viewed in TuningFork using the "Open
Trace" operation from the File menu. Note that a portLibrary must be
passed into constructors of various classes. This object is
internally used to allow us to port the library to different
platforms. An instance of this can be created with
PortLibrary *portLibrary = new PortLibrary();
To create a socket logger, use
ILogger* logger = LoggerFactory::makeServerLogger(portNumber);where
portNumber
is the integer port number to use for
the socket. The generated trace can then be viewed in TuningFork as
the instrumented program is running by connecting to the trace socket
with "Connect to a Trace" from the File menu.
There is also a logger that simply ignores all logging requests. This
is useful so that you don't have to sprinkle if (LOGGING)
conditionals throughout your code. You can simply decide at the
beginning of execution whether you actually want to generate a trace.
If you don't, create a null logger:
ILogger* logger = LoggerFactory::makeNullLogger(portLibrary);
The TuningFork tool will take care of re-assembling the events in the feedlets in order, so you can use the feedlets without worrying about time synchronization between them. To create a feedlet, use
IFeedlet* myFeedlet = logger.makeFeedlet("My Feedlet", "Primary feedlet for my program"); myFeedlet->setName("My Feedlet");The feedlet name is purely for your convenience, so you can use anything you like.
You can add events to feedlets explicitly, but it's more convenient to associate a feedlet with a thread, which you can do with
myFeedlet->bindToCurrentThread();After that, if you log a trace event on that thread without specifying a feedlet, it will be placed in the feedlet you bound to the thread.
To create a timer event, use
ITimerEvent* phaseTimer = logger->makeTimerEvent("Phase of My Program");The timer event can now be used to add events to the log. Similarly, to create a value event, use
IValueEvent* sizeEvent = logger->makeValueEvent("Size of My Primary Data Structure");
Value events record a single double
value along with their timestamp.
sizeEvent->addValue(myDataStructure->size());where
myDataStructure
is some object whose size you want to monitor.
To add a timer event marking the beginning and end of some operation, you could use
peacetimes->start(); myApplicationWork(); phaseTimer->stop();where
myApplicationWork()
is a method in your program whose timing you want to measure.
Properties should only be added once; they are not events. If you have some repeating occurrence that you want to log, use a value event and not a property.
For example, you could add information about the way the program was run:
logger->addProperty("Command", arg);where
arg
is the concatentation of strings passed to your main()
function.