Skip to content

Commit

Permalink
[FEATURE]: Server logging also in release mode
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed May 13, 2014
2 parents 436973d + 8707cf2 commit 29c39b9
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 35 deletions.
2 changes: 2 additions & 0 deletions src/mapserver/CMakeLists.txt
Expand Up @@ -39,6 +39,7 @@ SET ( qgis_mapserv_SRCS
qgshostedrdsbuilder.cpp
qgsremotedatasourcebuilder.cpp
qgssentdatasourcebuilder.cpp
qgsserverlogger.cpp
qgsmsutils.cpp
qgswcsprojectparser.cpp
qgswfsprojectparser.cpp
Expand All @@ -58,6 +59,7 @@ SET (qgis_mapserv_MOC_HDRS
qgscapabilitiescache.h
qgsconfigcache.h
qgsmslayercache.h
qgsserverlogger.h
)

SET (qgis_mapserv_RCCS
Expand Down
76 changes: 45 additions & 31 deletions src/mapserver/qgis_map_serv.cpp
Expand Up @@ -33,6 +33,7 @@
#include "qgspallabeling.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsmaplayerregistry.h"
#include "qgsserverlogger.h"

#include <QDomDocument>
#include <QNetworkDiskCache>
Expand All @@ -49,7 +50,7 @@

void dummyMessageHandler( QtMsgType type, const char *msg )
{
#ifdef QGSMSDEBUG
#if 0 //def QGSMSDEBUG
QString output;

switch ( type )
Expand Down Expand Up @@ -81,53 +82,61 @@ void dummyMessageHandler( QtMsgType type, const char *msg )

void printRequestInfos()
{
#ifdef QGSMSDEBUG
//print out some infos about the request
QgsDebugMsg( "************************new request**********************" );
QgsDebugMsg( QDateTime::currentDateTime().toString( "yyyy-MM-dd hh:mm:ss" ) );

QgsMessageLog::logMessage( "********************new request***************", "Server", QgsMessageLog::INFO );
if ( getenv( "REMOTE_ADDR" ) != NULL )
{
QgsDebugMsg( "remote ip: " + QString( getenv( "REMOTE_ADDR" ) ) );
QgsMessageLog::logMessage( "remote ip: " + QString( getenv( "REMOTE_ADDR" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "REMOTE_HOST" ) != NULL )
{
QgsDebugMsg( "remote host: " + QString( getenv( "REMOTE_HOST" ) ) );
QgsMessageLog::logMessage( "remote ip: " + QString( getenv( "REMOTE_ADDR" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "REMOTE_USER" ) != NULL )
{
QgsDebugMsg( "remote user: " + QString( getenv( "REMOTE_USER" ) ) );
QgsMessageLog::logMessage( "remote user: " + QString( getenv( "REMOTE_USER" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "REMOTE_IDENT" ) != NULL )
{
QgsDebugMsg( "REMOTE_IDENT: " + QString( getenv( "REMOTE_IDENT" ) ) );
QgsMessageLog::logMessage( "REMOTE_IDENT: " + QString( getenv( "REMOTE_IDENT" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "CONTENT_TYPE" ) != NULL )
{
QgsDebugMsg( "CONTENT_TYPE: " + QString( getenv( "CONTENT_TYPE" ) ) );
QgsMessageLog::logMessage( "CONTENT_TYPE: " + QString( getenv( "CONTENT_TYPE" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "AUTH_TYPE" ) != NULL )
{
QgsDebugMsg( "AUTH_TYPE: " + QString( getenv( "AUTH_TYPE" ) ) );
QgsMessageLog::logMessage( "AUTH_TYPE: " + QString( getenv( "AUTH_TYPE" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "HTTP_USER_AGENT" ) != NULL )
{
QgsDebugMsg( "HTTP_USER_AGENT: " + QString( getenv( "HTTP_USER_AGENT" ) ) );
QgsMessageLog::logMessage( "HTTP_USER_AGENT: " + QString( getenv( "HTTP_USER_AGENT" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "HTTP_PROXY" ) != NULL )
{
QgsDebugMsg( "HTTP_PROXY: " + QString( getenv( "HTTP_PROXY" ) ) );
QgsMessageLog::logMessage( "HTTP_PROXY: " + QString( getenv( "HTTP_PROXY" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "HTTPS_PROXY" ) != NULL )
{
QgsDebugMsg( "HTTPS_PROXY: " + QString( getenv( "HTTPS_PROXY" ) ) );
QgsMessageLog::logMessage( "HTTPS_PROXY: " + QString( getenv( "HTTPS_PROXY" ) ), "Server", QgsMessageLog::INFO );
}
if ( getenv( "NO_PROXY" ) != NULL )
{
QgsDebugMsg( "NO_PROXY: " + QString( getenv( "NO_PROXY" ) ) );
QgsMessageLog::logMessage( "NO_PROXY: " + QString( getenv( "NO_PROXY" ) ), "Server", QgsMessageLog::INFO );
}
}

#endif //QGSMSDEBUG
void printRequestParameters( const QMap< QString, QString>& parameterMap, int logLevel )
{
if ( logLevel > 0 )
{
return;
}

QMap< QString, QString>::const_iterator pIt = parameterMap.constBegin();
for ( ; pIt != parameterMap.constEnd(); ++pIt )
{
QgsMessageLog::logMessage( pIt.key() + ":" + pIt.value(), "Server", QgsMessageLog::INFO );
}
}

QFileInfo defaultProjectFile()
Expand Down Expand Up @@ -289,25 +298,20 @@ int main( int argc, char * argv[] )
QgsFontUtils::loadStandardTestFonts( QStringList() << "Roman" << "Bold" );
#endif

QString logFile = QgsLogger::logFile();
int logLevel = QgsServerLogger::instance()->logLevel();
QTime time; //used for measuring request time if loglevel < 1

while ( fcgi_accept() >= 0 )
{
QgsMapLayerRegistry::instance()->removeAllMapLayers();
qgsapp.processEvents();


if ( !logFile.isEmpty() )
if ( logLevel < 1 )
{
#ifdef Q_WS_WIN
putenv( QString( "QGIS_LOG_FILE=%1" ).arg( logFile ).toLocal8Bit().constData() );
#else
setenv( "QGIS_LOG_FILE", logFile.toLocal8Bit().constData(), 1 );
#endif
time.start();
printRequestInfos();
}

printRequestInfos(); //print request infos if in debug mode

//Request handler
QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler() );
QMap<QString, QString> parameterMap;
Expand All @@ -317,11 +321,12 @@ int main( int argc, char * argv[] )
}
catch ( QgsMapServiceException& e )
{
QgsDebugMsg( "An exception was thrown during input parsing" );
QgsMessageLog::logMessage( "Parse input exception: " + e.message(), "Server", QgsMessageLog::CRITICAL );
theRequestHandler->sendServiceException( e );
continue;
}

printRequestParameters( parameterMap, logLevel );
QMap<QString, QString>::const_iterator paramIt;

//Config file path
Expand All @@ -332,6 +337,7 @@ int main( int argc, char * argv[] )
paramIt = parameterMap.find( "SERVICE" );
if ( paramIt == parameterMap.constEnd() )
{
QgsMessageLog::logMessage( "Exception: SERVICE parameter is missing", "Server", QgsMessageLog::CRITICAL );
theRequestHandler->sendServiceException( QgsMapServiceException( "ServiceNotSpecified", "Service not specified. The SERVICE parameter is mandatory" ) );
continue;
}
Expand All @@ -345,7 +351,8 @@ int main( int argc, char * argv[] )
QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( configFilePath );
if ( !p )
{
//error handling
theRequestHandler->sendServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) );
continue;
}
QgsWCSServer wcsServer( configFilePath, parameterMap, p, theRequestHandler.take() );
wcsServer.executeRequest();
Expand All @@ -355,7 +362,8 @@ int main( int argc, char * argv[] )
QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( configFilePath );
if ( !p )
{
//error handling
theRequestHandler->sendServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) );
continue;
}
QgsWFSServer wfsServer( configFilePath, parameterMap, p, theRequestHandler.take() );
wfsServer.executeRequest();
Expand All @@ -365,12 +373,18 @@ int main( int argc, char * argv[] )
QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( configFilePath, parameterMap );
if ( !p )
{
//error handling
theRequestHandler->sendServiceException( QgsMapServiceException( "WMS configuration error", "There was an error reading gthe project file or the SLD configuration" ) );
continue;
}
//adminConfigParser->loadLabelSettings( theMapRenderer->labelingEngine() );
QgsWMSServer wmsServer( configFilePath, parameterMap, p, theRequestHandler.take(), theMapRenderer.data(), &capabilitiesCache );
wmsServer.executeRequest();
}

if ( logLevel < 1 )
{
QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO );
}
}

return 0;
Expand Down
15 changes: 11 additions & 4 deletions src/mapserver/qgsconfigcache.cpp
Expand Up @@ -16,6 +16,7 @@
***************************************************************************/

#include "qgsconfigcache.h"
#include "qgsmessagelog.h"
#include "qgswcsprojectparser.h"
#include "qgswfsprojectparser.h"
#include "qgswmsprojectparser.h"
Expand Down Expand Up @@ -118,9 +119,15 @@ QDomDocument* QgsConfigCache::xmlDocument( const QString& filePath )
{
//first open file
QFile configFile( filePath );
if ( !configFile.exists() || !configFile.open( QIODevice::ReadOnly ) )
if ( !configFile.exists() )
{
QgsDebugMsg( "File unreadable: " + filePath );
QgsMessageLog::logMessage( "Error, configuration file '" + filePath + "' does not exist", "Server", QgsMessageLog::CRITICAL );
return 0;
}

if ( !configFile.open( QIODevice::ReadOnly ) )
{
QgsMessageLog::logMessage( "Error, cannot open configuration file '" + filePath + "'", "Server", QgsMessageLog::CRITICAL );
return 0;
}

Expand All @@ -130,8 +137,8 @@ QDomDocument* QgsConfigCache::xmlDocument( const QString& filePath )
int line, column;
if ( !xmlDoc->setContent( &configFile, true, &errorMsg, &line, &column ) )
{
QgsDebugMsg( QString( "Parse error %1 at row %2, column %3 in %4 " )
.arg( errorMsg ).arg( line ).arg( column ).arg( filePath ) );
QgsMessageLog::logMessage( "Error parsing file '" + filePath +
QString( "': parse error %1 at row %2, column %3" ).arg( errorMsg ).arg( line ).arg( column ), "Server", QgsMessageLog::CRITICAL );
delete xmlDoc;
return 0;
}
Expand Down
71 changes: 71 additions & 0 deletions src/mapserver/qgsserverlogger.cpp
@@ -0,0 +1,71 @@
/***************************************************************************
qgsserverlogger.cpp
-------------------
begin : May 5, 2014
copyright : (C) 2014 by Marco Hugentobler
email : marco dot hugentobler at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsserverlogger.h"
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QTime>

QgsServerLogger* QgsServerLogger::mInstance = 0;

QgsServerLogger* QgsServerLogger::instance()
{
if ( mInstance == 0 )
{
mInstance = new QgsServerLogger();
}
return mInstance;
}

QgsServerLogger::QgsServerLogger(): mLogFile( 0 )
{
//logfile
QString filePath = getenv( "QGIS_LOG_FILE" );
mLogFile.setFileName( filePath );
if ( mLogFile.open( QIODevice::Append ) )
{
mTextStream.setDevice( &mLogFile );
}

//log level
char* logLevelChar = getenv( "QGIS_LOG_LEVEL" );

This comment has been minimized.

Copy link
@dakcarto

dakcarto May 15, 2014

Member

@mhugent Hi. On Mac, using clang, I had to add:

#include <cstdlib>

Otherwise, the getenv() calls (here and at line # 38) were undefined, and the build threw errors. The fix worked for me, but figured you had a better idea on how to fix it, i.e. I won't do a commit unless you think it is OK.

This comment has been minimized.

Copy link
@mhugent

mhugent May 15, 2014

Author Contributor

Hi Larry

Thanks, #include is fine, please do the commit.

This comment has been minimized.

Copy link
@dakcarto

dakcarto May 15, 2014

Member

Thanks. Done.

if ( logLevelChar )
{
mLogLevel = atoi( logLevelChar );
}
else
{
mLogLevel = 3;
}

connect( QgsMessageLog::instance(), SIGNAL( messageReceived( QString, QString, QgsMessageLog::MessageLevel ) ), this,
SLOT( logMessage( QString, QString, QgsMessageLog::MessageLevel ) ) );
}

void QgsServerLogger::logMessage( QString message, QString tag, QgsMessageLog::MessageLevel level )
{
Q_UNUSED( tag );
if ( !mLogFile.isOpen() || mLogLevel > level )
{
return;
}

mTextStream << ( "[" + QString::number( qlonglong( QCoreApplication::applicationPid() ) ) + "]["
+ QTime::currentTime().toString() + "] " + message + "\n" );
mTextStream.flush();
}
52 changes: 52 additions & 0 deletions src/mapserver/qgsserverlogger.h
@@ -0,0 +1,52 @@
/***************************************************************************
qgsserverlogger.h
-----------------
begin : May 5, 2014
copyright : (C) 2014 by Marco Hugentobler
email : marco dot hugentobler at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSSERVERLOGGER_H
#define QGSSERVERLOGGER_H

#include "qgsmessagelog.h"

#include <QFile>
#include <QObject>
#include <QString>
#include <QTextStream>

/**Writes message log into server logfile*/
class QgsServerLogger: public QObject
{
Q_OBJECT
public:
static QgsServerLogger* instance();

int logLevel() const { return mLogLevel; }
//QString logFile() const { return mLogFile; }

public slots:
void logMessage( QString message, QString tag, QgsMessageLog::MessageLevel level );

protected:
QgsServerLogger();

private:
static QgsServerLogger* mInstance;

QFile mLogFile;
QTextStream mTextStream;
int mLogLevel;
};

#endif // QGSSERVERLOGGER_H

0 comments on commit 29c39b9

Please sign in to comment.