Documentation‎ > ‎

Qt logging API

Please keep in mind that TimeToPic bundle can be used logging whatever system that produces files or can send data to socket. Qt Logging API just makes logging convenient since you don't have to implement logger component by yourself. 

Qt logging API is for application profiling. API macros are written in way that porting to other frameworks&systems should be rather straightforward. Current API should work on Windows and Ubuntu Linux. 
If dropping OS CPU & MEM counters then should work on all Qt supported platforms.


 
    (click to view picture)
 

Qt logger intro video Jan 2015


Features

  • Application logging over socket
  • Trace function entry/exit
  • Trace own events (on-off) 
  • Trace own state machines
  • Trace values (integers) 
  • Performance counters (sample some variable and dump value perioidically)
  • OS CPU and Memory stats
  • C++ API 
  • Qt QML API 
  • Routes qDebug() to socket

Setting it up

Add source files

Basically you need to add files 
timetopiclogger.h and timetopiclogger.h  into your project.
Take them from https://www.assembla.com/spaces/timetopic-logger-examples/git/source/master/src/qt

Libraries

Add "win32:LIBS += -lpsapi" into .pro file if using Windows. 

Set compiler flags

For compiler, you need to define "DEFINES+=TTPLOGGING" to buildsteps


Example instrumentation

Then you need to add profiling macros to relevant into code like examples below (C++ & QML). Example is part of TimeToPic Bundle.

Macros

When opening file "timetopiclogger.h" you will find following macros:

// Define TTPLOGGING to enable these macros
#ifdef TTPLOGGING
#define TTPLOG_EVENTSCOPE(channel)      EventScopeObject obj(channel)
										// [%1]%2 is TimeToPic Logger Graphviz friendly (scope)
#define TTPLOG_FUNCTIONSCOPE            EventScopeObject funcObj(QString("[%1]%2").arg((int)QThread::currentThreadId()).arg(__FUNCTION__))
#define TTPLOG_EVENT(channel, state)    TimeToPicLogger::instance()->logEvent(channel, state)
#define TTPLOG_VALUE(channel, value)    TimeToPicLogger::instance()->logValue(channel, QString::number(value))
#define TTPLOG_STATE(channel, state)    TimeToPicLogger::instance()->logState(channel, state)
#define TTPLOG_STRING(str)              TimeToPicLogger::instance()->logString(str)
#define TTPLOG_LOG_OS_COUNTERS          TimeToPicLogger::instance()->enableOsPerfCounters(true);

/* User performance counters are reported perioidically and updating them should be rather fast */
// Counters are enabled by calling TTPLOG_LOG_OS_COUNTERS once;

// Slower but easier way to update counter
#define TTPLOG_SETUSER_COUNTERVALUE(counterName, value)         TimeToPicLogger::instance()->GetCounter(counterName)->setCounterValue(value);

// Slower but easier way to increment counter
#define TTPLOG_INCREMENTUSER_COUNTERVALUE(counterName, value)   TimeToPicLogger::instance()->GetCounter(counterName)->incrementCounter(value);

// Fast way to access counter
// return TimeToPicLoggerUserPerformanceCounter *. Use it in code for incrementing it. If pointer is stored, accessing it
// via hash is avoided. When getting pointer, user needs to take care of conditional compilation when TTPLOGGING is not defined.
#define TTPLOG_GETUSER_COUNTER(counterName)                     TimeToPicLogger::instance()->GetCounter(counterName);


if flag "TTPLOGGING" is defined, macros will work. Otherwise they become empty when compiled.

Primitives

TimeTopic tool support 4 log item types. 3 of them are supported on Qt Logging API. 

TTPLOG_EVENT

When adding TTPLOG_EVENT(channel, state) to code user can measure events that have start and stop. 
When event starts, use TTPLOG_EVENT("myEvent", true) and TTPLOG_EVENT("myEvent", false) when event stops. 

TTPLOG_VALUE

When user wants track variable numerical value he/she can use TTPLOG_VALUE(channel, value); where value is integer type. Check first picture of this page for example.  

TTPLOG_STATE

When user wants track state machine behavior, macro TTPLOG_STATE(channel, state); can be used. Channel is name of state machine and state is next state of state machine.  

Derived

TTPLOG_FUNCTIONSCOPE

When looking inside macro you will see that
EventScopeObject funcObj(QString("[%1]%2").arg((int)QThread::currentThreadId()).arg(__FUNCTION__))
is EventScopeObject  class. Start event is generated on class constructor and close event on its destructor.  
Macro declaration is thread aware (i.e separate threads are distinguished on timeline). Nested function calls are not supported currently. 

TTPLOG_EVENTSCOPE

Similar to TTPLOG_FUNCTIONSCOPE but user can specify event name. 

TTPLOG_STRING

Free string output log stream. 

TTPLOG_LOG_OS_COUNTERS

Starts logging OS CPU and Memory usage periodically. 

TTPLOG_SETUSER_COUNTERVALUE

Performance counter where user overwrites current value with new one. Value is sent to socket periodically. 
This saves bandwidth but loses timing accuracy due sampling. 

TTPLOG_INCREMENTUSER_COUNTERVALUE

Performance counter where user increments current value with new one. Value is sent to socket periodically. Value is reset after it have been sent. 

TTPLOG_GETUSER_COUNTER

Helper for getting pointer to counter value. Accessing counter value directly without hash makes it bit faster:

get:
TimeToPicLoggerUserPerformanceCounter *c = TTPLOG_GETUSER_COUNTER("testcounter1");

use:
c->incrementCounter(1);

compared to 

use:
TimeToPicLogger::instance()->GetCounter(counterName)->setCounterValue(value);


TimeToPicLoggerUserPerformanceCounter * TimeToPicLogger::GetCounter(QString counterName)
{
    QMutexLocker locker(&m_userCountersMutex);
    if (mUserCounters.contains(counterName)==false ) {
        mUserCounters[counterName] = new TimeToPicLoggerUserPerformanceCounter();
         mUserCounters[counterName]->setCounterName(counterName);
    }
    return mUserCounters[counterName];
}