QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgseventtracing.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgseventtracing.cpp
3 --------------------------------------
4 Date : October 2019
5 Copyright : (C) 2019 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgseventtracing.h"
17
18#include <QCoreApplication>
19#include <QFile>
20#include <QThread>
21
23
24struct TraceItem
25{
26 QgsEventTracing::EventType type;
27 uint threadId;
28 qint64 timestamp;
29 QString category;
30 QString name;
31 QString id;
32};
33
35static bool sIsTracing = false;
37Q_GLOBAL_STATIC( QElapsedTimer, sTracingTimer )
39Q_GLOBAL_STATIC( QVector<TraceItem>, sTraceEvents )
41Q_GLOBAL_STATIC( QMutex, sTraceEventsMutex )
42
43
44bool QgsEventTracing::startTracing()
45{
46 if ( sIsTracing )
47 return false;
48
49 sIsTracing = true;
50 sTraceEventsMutex()->lock();
51 sTracingTimer()->start();
52 sTraceEvents()->clear();
53 sTraceEvents()->reserve( 1000 );
54 sTraceEventsMutex()->unlock();
55 return true;
56}
57
58bool QgsEventTracing::stopTracing()
59{
60 if ( !sIsTracing )
61 return false;
62
63 sIsTracing = false;
64 sTracingTimer()->invalidate();
65 return false;
66}
67
68bool QgsEventTracing::isTracingEnabled()
69{
70 return sIsTracing;
71}
72
73static char _eventTypeToChar( QgsEventTracing::EventType type )
74{
75 switch ( type )
76 {
77 case QgsEventTracing::Begin: return 'B';
78 case QgsEventTracing::End: return 'E';
79 case QgsEventTracing::Instant: return 'i';
80 case QgsEventTracing::AsyncBegin: return 'b';
81 case QgsEventTracing::AsyncEnd: return 'e';
82 }
83 return '?';
84}
85
86bool QgsEventTracing::writeTrace( const QString &fileName )
87{
88 if ( sIsTracing )
89 return false;
90
91 QFile f( fileName );
92 if ( !f.open( QIODevice::WriteOnly ) )
93 return false;
94
95 f.write( "{\n\"traceEvents\": [\n" );
96
97 bool first = true;
98 for ( const auto &item : *sTraceEvents() )
99 {
100 if ( !first )
101 f.write( ",\n" );
102 else
103 first = false;
104 const char t = _eventTypeToChar( item.type );
105 QString msg = QStringLiteral( " {\"cat\": \"%1\", \"pid\": 1, \"tid\": %2, \"ts\": %3, \"ph\": \"%4\", \"name\": \"%5\"" )
106 .arg( item.category ).arg( item.threadId ).arg( item.timestamp ).arg( t ).arg( item.name );
107
108 // for instant events we always set them as global (currently not supporting instant events at thread scope)
109 if ( item.type == Instant )
110 msg += QLatin1String( ", \"s\": \"g\"" );
111
112 // async events also need to have ID associated
113 if ( item.type == AsyncBegin || item.type == AsyncEnd )
114 msg += QStringLiteral( ", \"id\": \"%1\"" ).arg( item.id );
115
116 msg += " }";
117
118 f.write( msg.toUtf8() );
119 }
120
121 f.write( "\n]\n}\n" );
122 f.close();
123 return true;
124}
125
126void QgsEventTracing::addEvent( QgsEventTracing::EventType type, const QString &category, const QString &name, const QString &id )
127{
128 if ( !sIsTracing )
129 return;
130
131 sTraceEventsMutex()->lock();
132 TraceItem item;
133 item.type = type;
134 item.timestamp = sTracingTimer()->nsecsElapsed() / 1000;
135 if ( QThread::currentThread() == QCoreApplication::instance()->thread() )
136 item.threadId = 0; // to make it show up first
137 else
138 item.threadId = static_cast<uint>( reinterpret_cast<quint64>( QThread::currentThreadId() ) );
139 item.category = category;
140 item.name = name;
141 item.id = id;
142 sTraceEvents()->append( item );
143 sTraceEventsMutex()->unlock();
144}
145
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)