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;
Q_GLOBAL_STATIC(QString,sFileFilter)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   if ( CMAKE_SOURCE_DIR[sPrefixLength - 1] == '/' )
55     sPrefixLength++;
56 }
57 
debug(const QString & msg,int debuglevel,const char * file,const char * function,int line)58 void QgsLogger::debug( const QString &msg, int debuglevel, const char *file, const char *function, int line )
59 {
60   init();
61 
62   if ( !file && !sFileFilter()->isEmpty() && !sFileFilter()->endsWith( file ) )
63     return;
64 
65   if ( sDebugLevel == 0 || debuglevel > sDebugLevel )
66     return;
67 
68 
69   QString m = msg;
70 
71   if ( file )
72   {
73     if ( qApp && qApp->thread() != QThread::currentThread() )
74     {
75       m.prepend( QStringLiteral( "[thread:0x%1] " ).arg( reinterpret_cast< qint64 >( QThread::currentThread() ), 0, 16 ) );
76     }
77 
78     m.prepend( QStringLiteral( "[%1ms] " ).arg( sTime()->elapsed() ) );
79     sTime()->restart();
80 
81     if ( function )
82     {
83       m.prepend( QStringLiteral( " (%1) " ).arg( function ) );
84     }
85 
86     if ( line != -1 )
87     {
88 #ifndef _MSC_VER
89       m.prepend( QStringLiteral( ":%1 :" ).arg( line ) );
90 #else
91       m.prepend( QString( "(%1) :" ).arg( line ) );
92 #endif
93     }
94 
95 #ifndef _MSC_VER
96     m.prepend( file + ( file[0] == '/' ? sPrefixLength : 0 ) );
97 #else
98     m.prepend( file );
99 #endif
100   }
101 
102   if ( sLogFile()->isEmpty() )
103   {
104     qDebug( "%s", m.toUtf8().constData() );
105   }
106   else
107   {
108     logMessageToFile( m );
109   }
110 }
111 
debug(const QString & var,int val,int debuglevel,const char * file,const char * function,int line)112 void QgsLogger::debug( const QString &var, int val, int debuglevel, const char *file, const char *function, int line )
113 {
114   debug( QStringLiteral( "%1: %2" ).arg( var ).arg( val ), debuglevel, file, function, line );
115 }
116 
debug(const QString & var,double val,int debuglevel,const char * file,const char * function,int line)117 void QgsLogger::debug( const QString &var, double val, int debuglevel, const char *file, const char *function, int line )
118 {
119   debug( QStringLiteral( "%1: %2" ).arg( var ).arg( val ), debuglevel, file, function, line );
120 }
121 
warning(const QString & msg)122 void QgsLogger::warning( const QString &msg )
123 {
124   logMessageToFile( msg );
125   qWarning( "Logged warning: %s", msg.toLocal8Bit().constData() );
126 }
127 
critical(const QString & msg)128 void QgsLogger::critical( const QString &msg )
129 {
130   logMessageToFile( msg );
131   qCritical( "Logged critical: %s", msg.toLocal8Bit().constData() );
132 }
133 
fatal(const QString & msg)134 void QgsLogger::fatal( const QString &msg )
135 {
136   logMessageToFile( msg );
137   qFatal( "Logged fatal: %s", msg.toLocal8Bit().constData() );
138 }
139 
logMessageToFile(const QString & message)140 void QgsLogger::logMessageToFile( const QString &message )
141 {
142   if ( sLogFile()->isEmpty() )
143     return;
144 
145   //Maybe more efficient to keep the file open for the life of qgis...
146   QFile file( *sLogFile() );
147   if ( !file.open( QIODevice::Append ) )
148     return;
149   file.write( message.toLocal8Bit().constData() );
150   file.write( "\n" );
151   file.close();
152 }
153 
logFile()154 QString QgsLogger::logFile()
155 {
156   init();
157   return *sLogFile();
158 }
159