Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,18 @@ set(PRIVATE_HEADERS
set(PROJECT_SOURCES
${PROJECT_SOURCE_DIR}/updater.cpp
${PROJECT_SOURCE_DIR}/sentryreporter.cpp
${PROJECT_SOURCE_DIR}/logger.cpp
${PROJECT_SOURCE_DIR}/application.cpp
${PROJECT_SOURCE_DIR}/mainwindow.cpp
${PROJECT_SOURCE_DIR}/style.cpp
${PROJECT_SOURCE_DIR}/minisplitter.cpp
${PROJECT_SOURCE_DIR}/navigationwidget.cpp
${PROJECT_SOURCE_DIR}/navigationpane.cpp
${PROJECT_SOURCE_DIR}/styledbar.cpp
${PROJECT_SOURCE_DIR}/logger.cpp
${PROJECT_SOURCE_DIR}/logger/baselogger.cpp
${PROJECT_SOURCE_DIR}/logger/consolelogger.cpp
${PROJECT_SOURCE_DIR}/logger/loggerdecorator.cpp
${PROJECT_SOURCE_DIR}/logger/sentrylogger.cpp
)

set(ACCESS_HHEADERS
Expand All @@ -65,6 +69,10 @@ set(ACCESS_HHEADERS
set(PRIVATE_HEADERS ${PRIVATE_HEADERS}
${PROJECT_SOURCE_DIR}/access/signserver.h
${PROJECT_SOURCE_DIR}/sentryreporter.h
${PROJECT_SOURCE_DIR}/logger/baselogger.h
${PROJECT_SOURCE_DIR}/logger/consolelogger.h
${PROJECT_SOURCE_DIR}/logger/loggerdecorator.h
${PROJECT_SOURCE_DIR}/logger/sentrylogger.h
${PROJECT_SOURCE_DIR}/logger.h
)

Expand Down
35 changes: 21 additions & 14 deletions src/framework/access/access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

#include "request.h"
#include "signserver.h"
#include "logger.h"
#include "version.h"

constexpr const char *apiEndpointSubpath = "/api/v1";
Expand Down Expand Up @@ -887,21 +888,27 @@ void NGAccess::updateSupportInfo() const

void NGAccess::logMessage(const QString &value, LogLevel level)
{
// Unknown levels will be info
SentryReporter::Level slevel = SentryReporter::Level::Info;
if(level == LogLevel::Warning) {
slevel = SentryReporter::Level::Warning;
auto &logger = getLogger();
const auto payload = QStringLiteral("[NGAccess] %1").arg(value);

switch (level)
{
case LogLevel::Debug:
logger.debug(payload);
break;
case LogLevel::Info:
logger.info(payload);
break;
case LogLevel::Warning:
logger.warning(payload);
break;
case LogLevel::Error:
logger.critical(payload);
break;
case LogLevel::Fatal:
logger.critical(QStringLiteral("[NGAccess] FATAL %1").arg(value));
break;
}
else if(level == LogLevel::Error) {
slevel = SentryReporter::Level::Error;
}
else if(level == LogLevel::Fatal) {
slevel = SentryReporter::Level::Fatal;
}
else if(level == LogLevel::Debug) {
slevel = SentryReporter::Level::Debug;
}
SentryReporter::instance().sendMessage(value, slevel);
}

SignInEvent::SignInEvent(QObject *parent) : QObject(parent)
Expand Down
70 changes: 54 additions & 16 deletions src/framework/access/signserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,34 @@ constexpr const char *contentStr = "<html>"
constexpr unsigned short listenPort = 65020;
constexpr const char *redirectUriStr = "http://127.0.0.1:65020";

namespace
{
void logAuth(const BaseLogger::LogLevel level, const QString &clientId, const QString &message, const bool flush = false)
{
auto &logger = getLogger();
const auto payload = QStringLiteral("Authorization [%1] %2").arg(clientId, message);

switch (level)
{
case BaseLogger::LogLevel::Debug:
logger.debug(payload);
break;
case BaseLogger::LogLevel::Info:
logger.info(payload);
break;
case BaseLogger::LogLevel::Warning:
logger.warning(payload);
break;
case BaseLogger::LogLevel::Critical:
logger.critical(payload);
break;
}

if (flush)
logger.flush();
}
}


static std::string toHex(unsigned char *value, int size)
{
Expand Down Expand Up @@ -104,7 +132,6 @@ NGSignServer::NGSignServer(const QString &clientId, const QString &scope,
m_redirectUri(redirectUriStr),
m_clientId(clientId),
m_scope(scope),
m_logger(new Logger(m_clientId, "Authorization Logging", this)),
m_timer(new QTimer(this))
{
setLabelText(tr("Please sign in\nvia the opened browser..."));
Expand All @@ -118,34 +145,37 @@ NGSignServer::NGSignServer(const QString &clientId, const QString &scope,
// Start listen server
m_listenServer = new QTcpServer(this);
bool result = m_listenServer->listen(QHostAddress::LocalHost, listenPort);
m_logger->add(QString("LISTEN result = %1, error = %2").arg(result ? "GOOD" : "BAD", m_listenServer->errorString()));
const auto listenMsg = QString("Listen result = %1, error = %2")
.arg(result ? "Success" : "Failed", m_listenServer->errorString());
logAuth(result ? BaseLogger::LogLevel::Info : BaseLogger::LogLevel::Warning,
m_clientId, listenMsg);

if (result)
{
connect(m_timer, &QTimer::timeout, this, [this]()
{
m_logger->add("TIMEOUT");
m_logger->send();
logAuth(BaseLogger::LogLevel::Warning, m_clientId,
QStringLiteral("Timeout while waiting for authorization reply"), true);
});
m_timer->start(30 * 1000); // 30 sec
}
else
{
m_logger->send();
getLogger().flush();
}

connect(m_listenServer, SIGNAL(newConnection()), this, SLOT(onIncomingConnection()));
connect(m_listenServer, &QTcpServer::acceptError, this, [this](QAbstractSocket::SocketError err)
{
m_timer->stop();
m_logger->add(QString("ACCEPT_ERROR: %1").arg(QString::number(static_cast<int>(err))));
m_logger->send();
logAuth(BaseLogger::LogLevel::Critical, m_clientId,
QString("Accept error: %1").arg(QString::number(static_cast<int>(err))), true);
});
}

NGSignServer::~NGSignServer()
{
m_logger->send();
getLogger().flush();
m_listenServer->close();
}

Expand All @@ -166,7 +196,8 @@ QString NGSignServer::verifier() const

void NGSignServer::onIncomingConnection()
{
m_logger->add("ON_INCOMING_CONNECTION");
logAuth(BaseLogger::LogLevel::Info, m_clientId,
QStringLiteral("Incoming connection received"));

QTcpSocket *socket = m_listenServer->nextPendingConnection();
connect(socket, SIGNAL(readyRead()), this, SLOT(onGetReply()), Qt::UniqueConnection);
Expand All @@ -176,18 +207,19 @@ void NGSignServer::onIncomingConnection()
void NGSignServer::onGetReply()
{
m_timer->stop();
m_logger->add("ON_GET_REPLY");
logAuth(BaseLogger::LogLevel::Info, m_clientId,
QStringLiteral("Processing authorization reply"));

if (!m_listenServer->isListening()) {
m_logger->add("ON_GET_REPLY status = ERROR: server is not listening");
m_logger->send();
logAuth(BaseLogger::LogLevel::Warning, m_clientId,
QStringLiteral("Authorization server is not listening"), true);
return;
}

QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
if (!socket) {
m_logger->add("ON_GET_REPLY status = ERROR: socket is null");
m_logger->send();
logAuth(BaseLogger::LogLevel::Warning, m_clientId,
QStringLiteral("Authorization reply socket is null"), true);
return;
}
socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
Expand Down Expand Up @@ -244,7 +276,10 @@ void NGSignServer::onGetReply()
socket->disconnectFromHost();
socket->deleteLater();

m_logger->add(QString("ON_GET_REPLY status = %1, code = %2, error = %3").arg(result ? "GOOD" : "BAD", m_code, errorMsg));
logAuth(result ? BaseLogger::LogLevel::Info : BaseLogger::LogLevel::Warning,
m_clientId,
QString("Authorization reply status = %1, code = %2, error = %3")
.arg(result ? "Success" : "Failed", m_code, errorMsg));

// Close dialog
done(result);
Expand Down Expand Up @@ -277,7 +312,10 @@ int NGSignServer::exec()
#endif

bool result = QDesktopServices::openUrl(url);
m_logger->add(QString("EXEC status = %1, url = %2").arg(result ? "GOOD" : "BAD", url.toDisplayString()));
logAuth(result ? BaseLogger::LogLevel::Info : BaseLogger::LogLevel::Warning,
m_clientId,
QString("Open authorization URL status = %1, url = %2")
.arg(result ? "Success" : "Failed", url.toDisplayString()));

return QProgressDialog::exec();
}
2 changes: 0 additions & 2 deletions src/framework/access/signserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <QProgressDialog>
#include <QTcpServer>

class Logger;
class QTimer;

class Q_DECL_HIDDEN NGSignServer : public QProgressDialog
Expand Down Expand Up @@ -51,7 +50,6 @@ private slots:
QString m_redirectUri;
QString m_clientId, m_scope, m_verifier;
QTcpServer *m_listenServer;
Logger* m_logger = {};
QTimer* m_timer = {};

// QDialog interface
Expand Down
39 changes: 31 additions & 8 deletions src/framework/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,43 @@
******************************************************************************/

#include "logger.h"
#include "sentryreporter.h"

Logger::Logger(const QString& id, const QString& title, QObject* parent)
: QObject(parent)
, m_message(QString("%1 %2").arg(title, id))
#include <QByteArray>

#include "logger/consolelogger.h"
#include "logger/sentrylogger.h"

namespace
{
std::shared_ptr<BaseLogger> g_logger;

void applyEnvironmentLogLevel(BaseLogger &logger)
{
const auto envValue = qgetenv("NGSTD_LOGGING_LEVEL");
if (envValue.isEmpty())
return;

logger.setLevel(QString::fromLocal8Bit(envValue));
}
}

void Logger::add(const QString& message)
BaseLogger &getLogger()
{
m_message += QString("\n* \"%1\"").arg(message);
if (!g_logger)
{
auto consoleLogger = std::make_shared<ConsoleLogger>();
g_logger = std::make_shared<SentryLogger>(consoleLogger);
applyEnvironmentLogLevel(*g_logger);
}

return *g_logger;
}

void Logger::send()
void setLogger(const std::shared_ptr<BaseLogger> &logger)
{
SentryReporter::instance().sendMessage(m_message);
g_logger = logger;

if (g_logger)
applyEnvironmentLogLevel(*g_logger);
}

41 changes: 5 additions & 36 deletions src/framework/logger.h
Original file line number Diff line number Diff line change
@@ -1,41 +1,10 @@
/******************************************************************************
* Project: NextGIS GIS libraries
* Purpose: Framework library
* Author: NextGIS
*******************************************************************************
* Copyright (C) 2012-2025 NextGIS, info@nextgis.ru
*
* 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#ifndef LOGGER_H
#define LOGGER_H

#include <QString>
#include <QObject>
#include "framework.h"

class Logger final : public QObject
{
public:
Logger(const QString& id, const QString& title, QObject* parent = nullptr);
~Logger() = default;

void add(const QString& message);
void send();
#include "logger/baselogger.h"
#include <memory>

private:
QString m_message;
};
NGFRAMEWORK_EXPORT BaseLogger &getLogger();
NGFRAMEWORK_EXPORT void setLogger(const std::shared_ptr<BaseLogger> &logger);

#endif LOGGER_H
#endif // LOGGER_H
Loading