QGIS API Documentation  3.27.0-Master (aef1b1ec20)
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 
24 struct TraceItem
25 {
26  QgsEventTracing::EventType type;
27  uint threadId;
28  qint64 timestamp;
29  QString category;
30  QString name;
31  QString id;
32 };
33 
35 static bool sIsTracing = false;
37 Q_GLOBAL_STATIC( QElapsedTimer, sTracingTimer )
39 Q_GLOBAL_STATIC( QVector<TraceItem>, sTraceEvents )
41 Q_GLOBAL_STATIC( QMutex, sTraceEventsMutex )
42 
43 
44 bool 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 
58 bool QgsEventTracing::stopTracing()
59 {
60  if ( !sIsTracing )
61  return false;
62 
63  sIsTracing = false;
64  sTracingTimer()->invalidate();
65  return false;
66 }
67 
68 bool QgsEventTracing::isTracingEnabled()
69 {
70  return sIsTracing;
71 }
72 
73 static 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 
86 bool 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 
126 void 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)