QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
qgslogger.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslogger.cpp - description
3  -------------------
4  begin : April 2006
5  copyright : (C) 2006 by Marco Hugentobler
6  email : marco.hugentobler at karto dot baug dot ethz dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgslogger.h"
19 
20 #include <QApplication>
21 #include <QtDebug>
22 #include <QFile>
23 #include <QElapsedTimer>
24 #include <QThread>
25 
26 #ifndef CMAKE_SOURCE_DIR
27 #error CMAKE_SOURCE_DIR undefined
28 #endif // CMAKE_SOURCE_DIR
29 
30 int QgsLogger::sDebugLevel = -999; // undefined value
31 int QgsLogger::sPrefixLength = -1;
32 Q_GLOBAL_STATIC( QString, sFileFilter )
33 Q_GLOBAL_STATIC( QString, sLogFile )
34 Q_GLOBAL_STATIC( QElapsedTimer, sTime )
35 
36 void QgsLogger::init()
37 {
38  if ( sDebugLevel != -999 )
39  return;
40 
41  sTime()->start();
42 
43  *sLogFile() = getenv( "QGIS_LOG_FILE" ) ? getenv( "QGIS_LOG_FILE" ) : "";
44  *sFileFilter() = getenv( "QGIS_DEBUG_FILE" ) ? getenv( "QGIS_DEBUG_FILE" ) : "";
45  sDebugLevel = getenv( "QGIS_DEBUG" ) ? atoi( getenv( "QGIS_DEBUG" ) ) :
46 #ifdef QGISDEBUG
47  1
48 #else
49  0
50 #endif
51  ;
52 
53  sPrefixLength = sizeof( CMAKE_SOURCE_DIR );
54  // cppcheck-suppress internalAstError
55  if ( CMAKE_SOURCE_DIR[sPrefixLength - 1] == '/' )
56  sPrefixLength++;
57 }
58 
59 void QgsLogger::debug( const QString &msg, int debuglevel, const char *file, const char *function, int line )
60 {
61  init();
62 
63  if ( !file && !sFileFilter()->isEmpty() && !sFileFilter()->endsWith( file ) )
64  return;
65 
66  if ( sDebugLevel == 0 || debuglevel > sDebugLevel )
67  return;
68 
69 
70  QString m = msg;
71 
72  if ( file )
73  {
74  if ( qApp && qApp->thread() != QThread::currentThread() )
75  {
76  m.prepend( QStringLiteral( "[thread:0x%1] " ).arg( reinterpret_cast< qint64 >( QThread::currentThread() ), 0, 16 ) );
77  }
78 
79  m.prepend( QStringLiteral( "[%1ms] " ).arg( sTime()->elapsed() ) );
80  sTime()->restart();
81 
82  if ( function )
83  {
84  m.prepend( QStringLiteral( " (%1) " ).arg( function ) );
85  }
86 
87  if ( line != -1 )
88  {
89 #ifndef _MSC_VER
90  m.prepend( QStringLiteral( ":%1 :" ).arg( line ) );
91 #else
92  m.prepend( QString( "(%1) :" ).arg( line ) );
93 #endif
94  }
95 
96 #ifndef _MSC_VER
97  m.prepend( file + ( file[0] == '/' ? sPrefixLength : 0 ) );
98 #else
99  m.prepend( file );
100 #endif
101  }
102 
103  if ( sLogFile()->isEmpty() )
104  {
105  if ( debuglevel == 0 )
106  {
107  // debug level 0 is for errors only, so highlight these by dumping them to stderr
108  std::cerr << m.toUtf8().constData() << std::endl;
109  }
110  else
111  {
112  qDebug( "%s", m.toUtf8().constData() );
113  }
114  }
115  else
116  {
117  logMessageToFile( m );
118  }
119 }
120 
121 void QgsLogger::debug( const QString &var, int val, int debuglevel, const char *file, const char *function, int line )
122 {
123  debug( QStringLiteral( "%1: %2" ).arg( var ).arg( val ), debuglevel, file, function, line );
124 }
125 
126 void QgsLogger::debug( const QString &var, double val, int debuglevel, const char *file, const char *function, int line )
127 {
128  debug( QStringLiteral( "%1: %2" ).arg( var ).arg( val ), debuglevel, file, function, line );
129 }
130 
131 void QgsLogger::warning( const QString &msg )
132 {
133  logMessageToFile( msg );
134  qWarning( "Logged warning: %s", msg.toLocal8Bit().constData() );
135 }
136 
137 void QgsLogger::critical( const QString &msg )
138 {
139  logMessageToFile( msg );
140  qCritical( "Logged critical: %s", msg.toLocal8Bit().constData() );
141 }
142 
143 void QgsLogger::fatal( const QString &msg )
144 {
145  logMessageToFile( msg );
146  qFatal( "Logged fatal: %s", msg.toLocal8Bit().constData() );
147 }
148 
149 void QgsLogger::logMessageToFile( const QString &message )
150 {
151  if ( sLogFile()->isEmpty() )
152  return;
153 
154  //Maybe more efficient to keep the file open for the life of qgis...
155  QFile file( *sLogFile() );
156  if ( !file.open( QIODevice::Append ) )
157  return;
158  file.write( message.toLocal8Bit().constData() );
159  file.write( "\n" );
160  file.close();
161 }
162 
164 {
165  init();
166  return *sLogFile();
167 }
static void fatal(const QString &msg)
Goes to qFatal.
Definition: qgslogger.cpp:143
static void debug(const QString &msg, int debuglevel=1, const char *file=nullptr, const char *function=nullptr, int line=-1)
Goes to qDebug.
Definition: qgslogger.cpp:59
static QString logFile()
Reads the environment variable QGIS_LOG_FILE.
Definition: qgslogger.cpp:163
static void critical(const QString &msg)
Goes to qCritical.
Definition: qgslogger.cpp:137
static void logMessageToFile(const QString &message)
Logs the message passed in to the logfile defined in QGIS_LOG_FILE if any.
Definition: qgslogger.cpp:149
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:131
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)