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
filenameis 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
portNumberis 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
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.
myDataStructureis 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:
argis the concatentation of strings passed to your