Skip to content
Permalink
Browse files

Merge pull request #7814 from elemoine/ele_logging

Support QGIS Server logs to stderr
  • Loading branch information
pblottiere committed Sep 14, 2018
2 parents a78a7e7 + 9eaee8f commit 2e91c29dff1963b5f1aaaab0d68e9671cf1c7486
@@ -107,18 +107,43 @@ class QgsMessageLogConsole : QObject
%Docstring
Default implementation of message logging interface

This class outputs log messages to the standard output. Therefore it might
be the right choice for apps without GUI.
This class outputs log messages to the standard error. Therefore it might
be the right choice for applications without GUI.
%End

%TypeHeaderCode
#include "qgsmessagelog.h"
%End
public:

QgsMessageLogConsole();
%Docstring
Constructor for QgsMessageLogConsole.
%End

protected:

QString formatLogMessage( const QString &message, const QString &tag, Qgis::MessageLevel level = Qgis::Info ) const;
%Docstring
Formats a log message. Used by child classes.

:param message: the message to format
:param tag: the tag of the message
:param level: the log level of the message

.. versionadded:: 3.4
%End

public slots:
void logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level );

virtual void logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level );
%Docstring
Logs a message to stderr.

:param message: the message to format
:param tag: the tag of the message
:param level: the log level of the message
%End
};

/************************************************************************
@@ -0,0 +1,85 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/server/qgsserverlogger.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/






class QgsServerLogger : QgsMessageLogConsole
{
%Docstring
Writes message log into server logfile

.. versionadded:: 2.8
%End

%TypeHeaderCode
#include "qgsserverlogger.h"
%End
public:

static QgsServerLogger *instance();
%Docstring
Gets the singleton instance
%End

Qgis::MessageLevel logLevel() const;
%Docstring
Gets the current log level

:return: the log level

.. versionadded:: 3.0
%End

void setLogLevel( Qgis::MessageLevel level );
%Docstring
Set the current log level

:param level: the log level

.. versionadded:: 3.0
%End

void setLogFile( const QString &filename = QString() );
%Docstring
Set the current log file
%End

void setLogStderr();
%Docstring
Activates logging to stderr.

.. versionadded:: 3.4.
%End

public slots:

virtual void logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level );

%Docstring
Log a message from the server context

:param message: the message
:param tag: tag of the message
:param level: log level of the message
%End

protected:
QgsServerLogger();

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/server/qgsserverlogger.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -94,6 +94,15 @@ Returns the QGS project file to use.
Returns the log file.

:return: the path of the log file or an empty string if none is defined.
%End

bool logStderr() const;
%Docstring
Returns whether logging to stderr is activated.

:return: true if logging to stderr is activated, false otherwise.

.. versionadded:: 3.4
%End

qint64 cacheSize() const;
@@ -3,6 +3,7 @@
%Include auto_generated/qgsmapserviceexception.sip
%Include auto_generated/qgscapabilitiescache.sip
%Include auto_generated/qgsconfigcache.sip
%Include auto_generated/qgsserverlogger.sip
%Include auto_generated/qgsserversettings.sip
%Include auto_generated/qgsserverparameters.sip
%Include auto_generated/qgsbufferserverrequest.sip
@@ -18,7 +18,9 @@
#include "qgslogger.h"
#include <QDateTime>
#include <QMetaType>
#include <QTextStream>
#include <iostream>
#include <stdio.h>

class QgsMessageLogConsole;

@@ -47,12 +49,19 @@ QgsMessageLogConsole::QgsMessageLogConsole()

void QgsMessageLogConsole::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
{
std::cerr
<< tag.toLocal8Bit().data() << "[" <<
( level == Qgis::Info ? "INFO"
: level == Qgis::Warning ? "WARNING"
: "CRITICAL" )
<< "]: " << message.toLocal8Bit().data() << std::endl;
QString formattedMessage = formatLogMessage( message, tag, level );
QTextStream cerr( stderr );
cerr << formattedMessage;
}

QString QgsMessageLogConsole::formatLogMessage( const QString &message, const QString &tag, Qgis::MessageLevel level ) const
{
const QString time = QTime::currentTime().toString();
const QString levelStr = level == Qgis::Info ? QStringLiteral( "INFO" ) :
level == Qgis::Warning ? QStringLiteral( "WARNING" ) :
QStringLiteral( "CRITICAL" );
const QString pid = QString::number( QCoreApplication::applicationPid() );
return QStringLiteral( "%1 %2 %3[%4]: %5\n" ).arg( time, levelStr, tag, pid, message );
}

//
@@ -128,20 +128,44 @@ class CORE_EXPORT QgsMessageLogNotifyBlocker

/**
* \ingroup core
\brief Default implementation of message logging interface
This class outputs log messages to the standard output. Therefore it might
be the right choice for apps without GUI.
*/
* \brief Default implementation of message logging interface
*
* This class outputs log messages to the standard error. Therefore it might
* be the right choice for applications without GUI.
*/
class CORE_EXPORT QgsMessageLogConsole : public QObject
{
Q_OBJECT

public:

/**
* Constructor for QgsMessageLogConsole.
*/
QgsMessageLogConsole();

protected:

/**
* Formats a log message. Used by child classes.
*
* \param message the message to format
* \param tag the tag of the message
* \param level the log level of the message
* \since QGIS 3.4
*/
QString formatLogMessage( const QString &message, const QString &tag, Qgis::MessageLevel level = Qgis::Info ) const;

public slots:
void logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level );

/**
* Logs a message to stderr.
*
* \param message the message to format
* \param tag the tag of the message
* \param level the log level of the message
*/
virtual void logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level );
};

#endif
@@ -186,7 +186,14 @@ bool QgsServer::init()
// init and configure logger
QgsServerLogger::instance();
QgsServerLogger::instance()->setLogLevel( sSettings.logLevel() );
QgsServerLogger::instance()->setLogFile( sSettings.logFile() );
if ( ! sSettings.logFile().isEmpty() )
{
QgsServerLogger::instance()->setLogFile( sSettings.logFile() );
}
else if ( sSettings.logStderr() )
{
QgsServerLogger::instance()->setLogStderr();
}

// log settings currently used
sSettings.logSummary();
@@ -36,44 +36,47 @@ QgsServerLogger *QgsServerLogger::instance()
}

QgsServerLogger::QgsServerLogger()
: mLogFile( nullptr )
: QgsMessageLogConsole()
{
connect( QgsApplication::messageLog(), static_cast<void ( QgsMessageLog::* )( const QString &, const QString &, Qgis::MessageLevel )>( &QgsMessageLog::messageReceived ), this,
&QgsServerLogger::logMessage );
}

void QgsServerLogger::setLogLevel( Qgis::MessageLevel level )
void QgsServerLogger::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
{
mLogLevel = level;
if ( mLogLevel > level )
{
return;
}
if ( mLogFile.isOpen() )
{
QString formattedMessage = formatLogMessage( message, tag, level );
mTextStream << formattedMessage;
mTextStream.flush();
}
else if ( mLogStderr )
{
QgsMessageLogConsole::logMessage( message, tag, level );
}
}

void QgsServerLogger::setLogFile( const QString &f )
void QgsServerLogger::setLogLevel( const Qgis::MessageLevel level )
{
if ( ! f.isEmpty() )
{
if ( mLogFile.exists() )
{
mTextStream.flush();
mLogFile.close();
}

mLogFile.setFileName( f );
if ( mLogFile.open( QIODevice::Append ) )
{
mTextStream.setDevice( &mLogFile );
}
}
mLogLevel = level;
}

void QgsServerLogger::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
void QgsServerLogger::setLogFile( const QString &filename )
{
Q_UNUSED( tag );
if ( !mLogFile.isOpen() || mLogLevel > level )
mTextStream.flush();
mLogFile.close();
mLogFile.setFileName( filename );

if ( ( ! filename.isEmpty() ) && mLogFile.open( QIODevice::Append ) )
{
return;
mTextStream.setDevice( &mLogFile );
}
}

mTextStream << ( "[" + QString::number( qlonglong( QCoreApplication::applicationPid() ) ) + "]["
+ QTime::currentTime().toString() + "] " + message + "\n" );
mTextStream.flush();
void QgsServerLogger::setLogStderr()
{
setLogFile();
mLogStderr = true;
}
@@ -18,22 +18,21 @@
#ifndef QGSSERVERLOGGER_H
#define QGSSERVERLOGGER_H

#define SIP_NO_FILE


#include "qgsmessagelog.h"

#include <QFile>
#include <QObject>
#include <QString>
#include <QTextStream>
#include "qgis_server.h"

/**
* \ingroup server
* \brief Writes message log into server logfile
* \since QGIS 2.8
*/
class QgsServerLogger: public QObject
class SERVER_EXPORT QgsServerLogger : public QgsMessageLogConsole
{
Q_OBJECT
public:
@@ -60,7 +59,13 @@ class QgsServerLogger: public QObject
/**
* Set the current log file
*/
void setLogFile( const QString &f );
void setLogFile( const QString &filename = QString() );

/**
* Activates logging to stderr.
* \since QGIS 3.4.
*/
void setLogStderr();

public slots:

@@ -71,7 +76,7 @@ class QgsServerLogger: public QObject
* \param tag tag of the message
* \param level log level of the message
*/
void logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level );
void logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level ) override;

protected:
QgsServerLogger();
@@ -80,6 +85,7 @@ class QgsServerLogger: public QObject
static QgsServerLogger *sInstance;

QFile mLogFile;
bool mLogStderr = false;
QTextStream mTextStream;
Qgis::MessageLevel mLogLevel = Qgis::None;
};

0 comments on commit 2e91c29

Please sign in to comment.
You can’t perform that action at this time.