File indexing completed on 2024-05-19 04:49:32
0001 /* 0002 Copyright (c) 2003-2005 Max Howell <max.howell@methylblue.com> 0003 Copyright (c) 2007-2009 Mark Kretschmann <kretschmann@kde.org> 0004 Copyright (c) 2010-2011 Kevin Funk <krf@electrostorm.net> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Lesser General Public 0008 License as published by the Free Software Foundation; either 0009 version 2.1 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Lesser General Public License for more details. 0015 0016 You should have received a copy of the GNU Lesser General Public 0017 License along with this library. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "amarok_export.h" 0021 #include "core/support/Debug.h" 0022 #include "core/support/Debug_p.h" 0023 0024 #include <KConfigCore/KConfigGroup> 0025 0026 #include <QApplication> 0027 #include <QMutex> 0028 #include <QObject> 0029 0030 #include <iostream> 0031 #include <unistd.h> 0032 0033 // Define Application wide prefix 0034 #ifndef APP_PREFIX 0035 #define APP_PREFIX QLatin1String( "amarok:" ) 0036 #endif 0037 0038 #define DEBUG_INDENT_OBJECTNAME QLatin1String("Debug_Indent_object") 0039 0040 AMAROKCORE_EXPORT QMutex Debug::mutex( QMutex::Recursive ); 0041 0042 using namespace Debug; 0043 0044 static bool s_debugEnabled = false; 0045 static bool s_debugColorsEnabled = false; 0046 0047 Q_GLOBAL_STATIC( NoDebugStream, s_noDebugStream ) 0048 0049 IndentPrivate::IndentPrivate(QObject* parent) 0050 : QObject(parent) 0051 { 0052 setObjectName( DEBUG_INDENT_OBJECTNAME ); 0053 } 0054 0055 /** 0056 * We can't use a statically instantiated QString for the indent, because 0057 * static namespaces are unique to each dlopened library. So we piggy back 0058 * the QString on the QApplication instance 0059 */ 0060 IndentPrivate* IndentPrivate::instance() 0061 { 0062 QObject* qOApp = reinterpret_cast<QObject*>(qApp); 0063 QObject* obj = qOApp ? qOApp->findChild<QObject*>( DEBUG_INDENT_OBJECTNAME ) : nullptr; 0064 return (obj ? static_cast<IndentPrivate*>( obj ) : new IndentPrivate( qApp )); 0065 } 0066 0067 /* 0068 Text color codes (use last digit here) 0069 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white 0070 */ 0071 static int s_colors[] = { 1, 2, 4, 5, 6 }; // no yellow and white for sanity 0072 static int s_colorIndex = 0; 0073 0074 static QString toString( DebugLevel level ) 0075 { 0076 switch( level ) 0077 { 0078 case KDEBUG_WARN: 0079 return QStringLiteral("[WARNING]"); 0080 case KDEBUG_ERROR: 0081 return QStringLiteral("[ERROR__]"); 0082 case KDEBUG_FATAL: 0083 return QStringLiteral("[FATAL__]"); 0084 default: 0085 return QString(); 0086 } 0087 } 0088 0089 static int toColor( DebugLevel level ) 0090 { 0091 switch( level ) { 0092 case KDEBUG_WARN: 0093 return 3; // red 0094 case KDEBUG_ERROR: 0095 case KDEBUG_FATAL: 0096 return 1; // yellow 0097 default: 0098 return 0; // default: black 0099 } 0100 } 0101 0102 static QString colorize( const QString &text, int color = s_colorIndex ) 0103 { 0104 if( !debugColorEnabled() ) 0105 return text; 0106 0107 return QStringLiteral( "\x1b[00;3%1m%2\x1b[00;39m" ).arg( QString::number(s_colors[color]), text ); 0108 } 0109 0110 static QString reverseColorize( const QString &text, int color ) 0111 { 0112 if( !debugColorEnabled() ) 0113 return text; 0114 0115 return QStringLiteral( "\x1b[07;3%1m%2\x1b[00;39m" ).arg( QString::number(color), text ); 0116 } 0117 0118 QString Debug::indent() 0119 { 0120 return IndentPrivate::instance()->m_string; 0121 } 0122 0123 bool Debug::debugEnabled() 0124 { 0125 return s_debugEnabled; 0126 } 0127 0128 bool Debug::debugColorEnabled() 0129 { 0130 return s_debugColorsEnabled; 0131 } 0132 0133 void Debug::setDebugEnabled( bool enable ) 0134 { 0135 s_debugEnabled = enable; 0136 } 0137 0138 void Debug::setColoredDebug( bool enable ) 0139 { 0140 s_debugColorsEnabled = enable; 0141 } 0142 0143 QDebug Debug::dbgstream( DebugLevel level ) 0144 { 0145 if( !debugEnabled() ) 0146 return QDebug( s_noDebugStream ); 0147 0148 mutex.lock(); 0149 const QString currentIndent = indent(); 0150 mutex.unlock(); 0151 0152 QString text = QStringLiteral("%1%2").arg( APP_PREFIX ).arg( currentIndent ); 0153 if ( level > KDEBUG_INFO ) 0154 text.append( ' ' + reverseColorize( toString(level), toColor( level ) ) ); 0155 0156 return QDebug( QtDebugMsg ) << qPrintable( text ); 0157 } 0158 0159 void Debug::perfLog( const QString &message, const QString &func ) 0160 { 0161 #ifdef Q_OS_UNIX 0162 if( !debugEnabled() ) 0163 return; 0164 0165 QString str = QStringLiteral( "MARK: %1: %2 %3" ).arg( qApp->applicationName(), func, message ); 0166 access( str.toLocal8Bit().data(), F_OK ); 0167 #endif 0168 } 0169 0170 Block::Block( const char *label ) 0171 : m_label( label ) 0172 , m_color( s_colorIndex ) 0173 { 0174 if( !debugEnabled() ) 0175 return; 0176 0177 m_startTime.start(); 0178 0179 mutex.lock(); 0180 s_colorIndex = (s_colorIndex + 1) % 5; 0181 dbgstream() 0182 << qPrintable( colorize( QLatin1String( "BEGIN:" ), m_color ) ) 0183 << m_label; 0184 IndentPrivate::instance()->m_string += QLatin1String(" "); 0185 mutex.unlock(); 0186 } 0187 0188 Block::~Block() 0189 { 0190 if( !debugEnabled() ) 0191 return; 0192 0193 double duration = m_startTime.elapsed() / 1000.0; 0194 0195 mutex.lock(); 0196 IndentPrivate::instance()->m_string.truncate( Debug::indent().length() - 2 ); 0197 mutex.unlock(); 0198 0199 #ifdef DEBUG_OVERRIDE_ELAPSED_TIME 0200 duration = DEBUG_OVERRIDE_ELAPSED_TIME; 0201 #endif 0202 // Print timing information, and a special message (DELAY) if the method took longer than 5s 0203 if( duration < 5.0 ) 0204 { 0205 dbgstream() 0206 << qPrintable( colorize( QLatin1String( "END__:" ), m_color ) ) 0207 << m_label 0208 << qPrintable( colorize( QString( "[Took: %3s]") 0209 .arg( QString::number(duration, 'g', 2) ), m_color ) ); 0210 } 0211 else 0212 { 0213 dbgstream() 0214 << qPrintable( colorize( QString( "END__:" ), m_color ) ) 0215 << m_label 0216 << qPrintable( reverseColorize( QString( "[DELAY Took (quite long) %3s]") 0217 .arg( QString::number(duration, 'g', 2) ), toColor( KDEBUG_WARN ) ) ); 0218 } 0219 } 0220 0221 void Debug::stamp() 0222 { 0223 static int n = 0; 0224 debug() << "| Stamp: " << ++n << Qt::endl; 0225 }