added open service logs to logs page (#951)

* added open service logs to logs page
* redesign of log saving buttons
* hide service logs buttons for mobile platforms
* refactoring: moved logger to common folder
* feature: added the ability to enable logs to the start screen
This commit is contained in:
Nethius 2024-09-09 20:53:44 +04:00 committed by GitHub
parent 918be16372
commit 9cab51fb00
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 519 additions and 691 deletions

View file

@ -113,6 +113,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/../ipc
${CMAKE_CURRENT_LIST_DIR}/../common/logger
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
@ -134,7 +135,6 @@ set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h
${CMAKE_CURRENT_LIST_DIR}/ui/pages.h
${CMAKE_CURRENT_LIST_DIR}/ui/property_helper.h
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h
${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h
${CMAKE_CURRENT_BINARY_DIR}/version.h
@ -143,6 +143,7 @@ set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h
${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h
${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.h
)
# Mozilla headres
@ -193,6 +194,7 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.cpp
)
# Mozilla sources

View file

@ -164,7 +164,7 @@ void AmneziaApplication::init()
bool enabled = m_settings->isSaveLogs();
#ifndef Q_OS_ANDROID
if (enabled) {
if (!Logger::init()) {
if (!Logger::init(false)) {
qWarning() << "Initialization of debug subsystem failed";
}
}

View file

@ -83,7 +83,6 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
}
qDebug().noquote() << lineToExec;
Logger::appendSshLog("Run command:" + lineToExec);
error = m_sshClient.executeCommand(lineToExec, cbReadStdOut, cbReadStdErr);
if (error != ErrorCode::NoError) {
@ -100,7 +99,6 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
{
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
Logger::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + ":\n" + script);
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
if (e)

View file

@ -1,107 +0,0 @@
#ifndef LOGGER_H
#define LOGGER_H
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QString>
#include <QTextStream>
#include "ui/property_helper.h"
#include "mozilla/shared/loglevel.h"
class Logger : public QObject
{
Q_OBJECT
AUTO_PROPERTY(QString, sshLog)
AUTO_PROPERTY(QString, allLog)
public:
static Logger& Instance();
static void appendSshLog(const QString &log);
static void appendAllLog(const QString &log);
static bool init();
static void deInit();
static bool setServiceLogsEnabled(bool enabled);
static bool openLogsFolder();
static bool openServiceLogsFolder();
static QString appLogFileNamePath();
static void clearLogs();
static void clearServiceLogs();
static void cleanUp();
static QString userLogsFilePath();
static QString getLogFile();
// compat with Mozilla logger
Logger(const QString &className) { m_className = className; }
const QString& className() const { return m_className; }
class Log {
public:
Log(Logger* logger, LogLevel level);
~Log();
Log& operator<<(uint64_t t);
Log& operator<<(const char* t);
Log& operator<<(const QString& t);
Log& operator<<(const QStringList& t);
Log& operator<<(const QByteArray& t);
Log& operator<<(const QJsonObject& t);
Log& operator<<(QTextStreamFunction t);
Log& operator<<(const void* t);
// Q_ENUM
template <typename T>
typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, Log&>::type
operator<<(T t) {
const QMetaObject* meta = qt_getEnumMetaObject(t);
const char* name = qt_getEnumName(t);
addMetaEnum(typename QFlags<T>::Int(t), meta, name);
return *this;
}
private:
void addMetaEnum(quint64 value, const QMetaObject* meta, const char* name);
Logger* m_logger;
LogLevel m_logLevel;
struct Data {
Data() : m_ts(&m_buffer, QIODevice::WriteOnly) {}
QString m_buffer;
QTextStream m_ts;
};
Data* m_data;
};
Log error();
Log warning();
Log info();
Log debug();
QString sensitive(const QString& input);
private:
Logger() {}
Logger(Logger const &) = delete;
Logger& operator= (Logger const&) = delete;
static QString userLogsDir();
static QFile m_file;
static QTextStream m_textStream;
static QString m_logFileName;
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
// compat with Mozilla logger
QString m_className;
};
#endif // LOGGER_H

View file

@ -227,7 +227,7 @@ void Settings::setSaveLogs(bool enabled)
if (!isSaveLogs()) {
Logger::deInit();
} else {
if (!Logger::init()) {
if (!Logger::init(false)) {
qWarning() << "Initialization of debug subsystem failed";
}
}

View file

@ -88,7 +88,12 @@ void SettingsController::toggleLogging(bool enable)
void SettingsController::openLogsFolder()
{
Logger::openLogsFolder();
Logger::openLogsFolder(false);
}
void SettingsController::openServiceLogsFolder()
{
Logger::openLogsFolder(true);
}
void SettingsController::exportLogsFile(const QString &fileName)
@ -100,12 +105,21 @@ void SettingsController::exportLogsFile(const QString &fileName)
#endif
}
void SettingsController::exportServiceLogsFile(const QString &fileName)
{
#ifdef Q_OS_ANDROID
AndroidController::instance()->exportLogsFile(fileName);
#else
SystemController::saveFile(fileName, Logger::getServiceLogFile());
#endif
}
void SettingsController::clearLogs()
{
#ifdef Q_OS_ANDROID
AndroidController::instance()->clearLogs();
#else
Logger::clearLogs();
Logger::clearLogs(false);
Logger::clearServiceLogs();
#endif
}

View file

@ -43,7 +43,9 @@ public slots:
void toggleLogging(bool enable);
void openLogsFolder();
void openServiceLogsFolder();
void exportLogsFile(const QString &fileName);
void exportServiceLogsFile(const QString &fileName);
void clearLogs();
void backupAppConfig(const QString &fileName);

View file

@ -1,27 +0,0 @@
#ifndef PROPERTY_HELPER_H
#define PROPERTY_HELPER_H
#include <QObject>
#define AUTO_PROPERTY(TYPE, NAME) \
Q_PROPERTY(TYPE NAME READ NAME WRITE set_ ## NAME NOTIFY NAME ## Changed ) \
public: \
TYPE NAME() const { return m_ ## NAME ; } \
void set_ ## NAME(TYPE value) { \
if (m_ ## NAME == value) return; \
m_ ## NAME = value; \
emit NAME ## Changed(value); \
} \
Q_SIGNAL void NAME ## Changed(TYPE value);\
private: \
TYPE m_ ## NAME{};
#define READONLY_PROPERTY(TYPE, NAME) \
Q_PROPERTY(TYPE NAME READ NAME CONSTANT ) \
public: \
TYPE NAME() const { return m_ ## NAME ; } \
private: \
void NAME(TYPE value) {m_ ## NAME = value; } \
TYPE m_ ## NAME{};
#endif // PROPERTY_HELPER_H

View file

@ -20,7 +20,8 @@ Item {
property string buttonImageSource
property string rightImageSource
property string leftImageSource
property bool isLeftImageHoverEnabled: true //todo separete this qml file to 3
property bool isLeftImageHoverEnabled: true
property bool isSmallLeftImage: false
property alias rightButton: rightImage
property alias eyeButton: eyeImage
@ -114,9 +115,9 @@ Item {
visible: leftImageSource ? true : false
Layout.preferredHeight: rightImageSource || !isLeftImageHoverEnabled ? leftImage.implicitHeight : 56
Layout.preferredWidth: rightImageSource || !isLeftImageHoverEnabled ? leftImage.implicitWidth : 56
Layout.rightMargin: rightImageSource || !isLeftImageHoverEnabled ? 16 : 0
Layout.preferredHeight: (rightImageSource || !isLeftImageHoverEnabled || isSmallLeftImage) ? 40 : 56
Layout.preferredWidth: (rightImageSource || !isLeftImageHoverEnabled || isSmallLeftImage)? 40 : 56
Layout.rightMargin: isSmallLeftImage ? 8 : (rightImageSource || !isLeftImageHoverEnabled) ? 16 : 0
radius: 12
color: AmneziaStyle.color.transparent

View file

@ -102,8 +102,7 @@ Switch {
contentItem: ColumnLayout {
id: content
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
ListItemTitleType {

View file

@ -16,18 +16,6 @@ import "../Controls2/TextTypes"
PageType {
id: root
Connections {
target: SettingsController
function onLoggingStateChanged() {
if (SettingsController.isLoggingEnabled) {
var message = qsTr("Logging is enabled. Note that logs will be automatically \
disabled after 14 days, and all log files will be deleted.")
PageController.showNotificationMessage(message)
}
}
}
defaultActiveFocusItem: focusItem
Item {
@ -58,13 +46,12 @@ disabled after 14 days, and all log files will be deleted.")
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 16
spacing: 0
HeaderType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("Logging")
descriptionText: qsTr("Enabling this function will save application's logs automatically. " +
@ -75,11 +62,13 @@ disabled after 14 days, and all log files will be deleted.")
id: switcher
Layout.fillWidth: true
Layout.topMargin: 16
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("Save logs")
text: qsTr("Enable logs")
checked: SettingsController.isLoggingEnabled
KeyNavigation.tab: openFolderButton
//KeyNavigation.tab: openFolderButton
onCheckedChanged: {
if (checked !== SettingsController.isLoggingEnabled) {
SettingsController.isLoggingEnabled = checked
@ -87,132 +76,200 @@ disabled after 14 days, and all log files will be deleted.")
}
}
RowLayout {
DividerType {}
LabelWithButtonType {
// id: labelWithButton2
Layout.fillWidth: true
Layout.topMargin: -8
ColumnLayout {
Layout.alignment: Qt.AlignBaseline
Layout.preferredWidth: GC.isMobile() ? 0 : root.width / 3
visible: !GC.isMobile()
text: qsTr("Clear logs")
leftImageSource: "qrc:/images/controls/trash.svg"
isSmallLeftImage: true
ImageButtonType {
id: openFolderButton
Layout.alignment: Qt.AlignHCenter
// KeyNavigation.tab: labelWithButton3
implicitWidth: 56
implicitHeight: 56
clickedFunction: function() {
var headerText = qsTr("Clear logs?")
var yesButtonText = qsTr("Continue")
var noButtonText = qsTr("Cancel")
image: "qrc:/images/controls/folder-open.svg"
KeyNavigation.tab: saveButton
onClicked: SettingsController.openLogsFolder()
Keys.onReturnPressed: openFolderButton.clicked()
Keys.onEnterPressed: openFolderButton.clicked()
var yesButtonFunction = function() {
PageController.showBusyIndicator(true)
SettingsController.clearLogs()
PageController.showBusyIndicator(false)
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
if (!GC.isMobile()) {
focusItem.forceActiveFocus()
}
}
CaptionTextType {
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
text: qsTr("Open folder with logs")
color: AmneziaStyle.color.paleGray
}
}
ColumnLayout {
Layout.alignment: Qt.AlignBaseline
Layout.preferredWidth: root.width / ( GC.isMobile() ? 2 : 3 )
ImageButtonType {
id: saveButton
Layout.alignment: Qt.AlignHCenter
implicitWidth: 56
implicitHeight: 56
image: "qrc:/images/controls/save.svg"
KeyNavigation.tab: clearButton
Keys.onReturnPressed: saveButton.clicked()
Keys.onEnterPressed: saveButton.clicked()
onClicked: {
var fileName = ""
if (GC.isMobile()) {
fileName = "AmneziaVPN.log"
} else {
fileName = SystemController.getFileName(qsTr("Save"),
qsTr("Logs files (*.log)"),
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN",
true,
".log")
}
if (fileName !== "") {
PageController.showBusyIndicator(true)
SettingsController.exportLogsFile(fileName)
PageController.showBusyIndicator(false)
PageController.showNotificationMessage(qsTr("Logs file saved"))
}
var noButtonFunction = function() {
if (!GC.isMobile()) {
focusItem.forceActiveFocus()
}
}
CaptionTextType {
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
}
}
text: qsTr("Save logs to file")
color: AmneziaStyle.color.paleGray
ListItemTitleType {
Layout.fillWidth: true
Layout.topMargin: 8
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("Client logs")
}
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 8
Layout.leftMargin: 16
Layout.rightMargin: 16
color: AmneziaStyle.color.mutedGray
text: qsTr("AmneziaVPN logs")
}
LabelWithButtonType {
// id: labelWithButton2
Layout.fillWidth: true
Layout.topMargin: -8
Layout.bottomMargin: -8
text: qsTr("Open logs folder")
leftImageSource: "qrc:/images/controls/folder-open.svg"
isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3
clickedFunction: function() {
SettingsController.openLogsFolder()
}
}
DividerType {}
LabelWithButtonType {
// id: labelWithButton2
Layout.fillWidth: true
Layout.topMargin: -8
Layout.bottomMargin: -8
text: qsTr("Export logs")
leftImageSource: "qrc:/images/controls/save.svg"
isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3
clickedFunction: function() {
var fileName = ""
if (GC.isMobile()) {
fileName = "AmneziaVPN.log"
} else {
fileName = SystemController.getFileName(qsTr("Save"),
qsTr("Logs files (*.log)"),
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN",
true,
".log")
}
if (fileName !== "") {
PageController.showBusyIndicator(true)
SettingsController.exportLogsFile(fileName)
PageController.showBusyIndicator(false)
PageController.showNotificationMessage(qsTr("Logs file saved"))
}
}
}
ColumnLayout {
Layout.alignment: Qt.AlignBaseline
Layout.preferredWidth: root.width / ( GC.isMobile() ? 2 : 3 )
DividerType {}
ImageButtonType {
id: clearButton
Layout.alignment: Qt.AlignHCenter
ListItemTitleType {
visible: !GC.isMobile()
implicitWidth: 56
implicitHeight: 56
Layout.fillWidth: true
Layout.topMargin: 32
Layout.leftMargin: 16
Layout.rightMargin: 16
image: "qrc:/images/controls/delete.svg"
Keys.onTabPressed: lastItemTabClicked(focusItem)
text: qsTr("Service logs")
}
Keys.onReturnPressed: clearButton.clicked()
Keys.onEnterPressed: clearButton.clicked()
onClicked: function() {
var headerText = qsTr("Clear logs?")
var yesButtonText = qsTr("Continue")
var noButtonText = qsTr("Cancel")
ParagraphTextType {
visible: !GC.isMobile()
var yesButtonFunction = function() {
PageController.showBusyIndicator(true)
SettingsController.clearLogs()
PageController.showBusyIndicator(false)
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
if (!GC.isMobile()) {
focusItem.forceActiveFocus()
}
}
var noButtonFunction = function() {
if (!GC.isMobile()) {
focusItem.forceActiveFocus()
}
}
Layout.fillWidth: true
Layout.topMargin: 8
Layout.leftMargin: 16
Layout.rightMargin: 16
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
}
color: AmneziaStyle.color.mutedGray
text: qsTr("AmneziaVPN-service logs")
}
LabelWithButtonType {
// id: labelWithButton2
visible: !GC.isMobile()
Layout.fillWidth: true
Layout.topMargin: -8
Layout.bottomMargin: -8
text: qsTr("Open logs folder")
leftImageSource: "qrc:/images/controls/folder-open.svg"
isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3
clickedFunction: function() {
SettingsController.openServiceLogsFolder()
}
}
DividerType {
visible: !GC.isMobile()
}
LabelWithButtonType {
// id: labelWithButton2
visible: !GC.isMobile()
Layout.fillWidth: true
Layout.topMargin: -8
Layout.bottomMargin: -8
text: qsTr("Export logs")
leftImageSource: "qrc:/images/controls/save.svg"
isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3
clickedFunction: function() {
var fileName = ""
if (GC.isMobile()) {
fileName = "AmneziaVPN-service.log"
} else {
fileName = SystemController.getFileName(qsTr("Save"),
qsTr("Logs files (*.log)"),
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN-service",
true,
".log")
}
CaptionTextType {
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
text: qsTr("Clear logs")
color: AmneziaStyle.color.paleGray
if (fileName !== "") {
PageController.showBusyIndicator(true)
SettingsController.exportServiceLogsFile(fileName)
PageController.showBusyIndicator(false)
PageController.showNotificationMessage(qsTr("Logs file saved"))
}
}
}
DividerType {
visible: !GC.isMobile()
}
}
}
}

View file

@ -55,6 +55,51 @@ PageType {
Layout.leftMargin: 16
headerText: qsTr("Connection")
actionButtonImage: PageController.isStartPageVisible() ? "qrc:/images/controls/more-vertical.svg" : ""
actionButtonFunction: function() {
moreActionsDrawer.open()
}
DrawerType2 {
id: moreActionsDrawer
parent: root
anchors.fill: parent
expandedHeight: root.height * 0.35
expandedContent: ColumnLayout {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
HeaderType {
Layout.fillWidth: true
Layout.topMargin: 32
headerText: qsTr("Settings")
}
SwitcherType {
id: switcher
Layout.fillWidth: true
Layout.topMargin: 16
text: qsTr("Enable logs")
checked: SettingsController.isLoggingEnabled
onCheckedChanged: {
if (checked !== SettingsController.isLoggingEnabled) {
SettingsController.isLoggingEnabled = checked
}
}
}
}
}
}
ParagraphTextType {

View file

@ -202,6 +202,14 @@ PageType {
PageController.showNotificationMessage(qsTr("Settings restored from backup file"))
PageController.goToPageHome()
}
function onLoggingStateChanged() {
if (SettingsController.isLoggingEnabled) {
var message = qsTr("Logging is enabled. Note that logs will be automatically" +
"disabled after 14 days, and all log files will be deleted.")
PageController.showNotificationMessage(message)
}
}
}
StackViewType {

View file

@ -69,22 +69,6 @@ QString Utils::JsonToString(const QJsonArray &array, QJsonDocument::JsonFormat f
return doc.toJson(format);
}
QString Utils::systemLogPath()
{
#ifdef Q_OS_WIN
QStringList locationList = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
QString primaryLocation = "ProgramData";
foreach (const QString &location, locationList) {
if (location.contains(primaryLocation)) {
return QString("%1/%2/log").arg(location).arg(APPLICATION_NAME);
}
}
return QString();
#else
return QString("/var/log/%1").arg(APPLICATION_NAME);
#endif
}
bool Utils::initializePath(const QString &path)
{
QDir dir;

View file

@ -23,7 +23,6 @@ public:
static QJsonObject JsonFromString(const QString &string);
static QString executable(const QString &baseName, bool absPath);
static QString usrExecutable(const QString &baseName);
static QString systemLogPath();
static bool createEmptyFile(const QString &path);
static bool initializePath(const QString &path);

View file

@ -4,18 +4,18 @@
#include <QDebug>
#include <QDesktopServices>
#include <QDir>
#include <QMetaEnum>
#include <QJsonDocument>
#include <QMetaEnum>
#include <QStandardPaths>
#include <QUrl>
#include <iostream>
#include "version.h"
#include "utilities.h"
#include "version.h"
#ifdef AMNEZIA_DESKTOP
#include <core/ipcclient.h>
#include <core/ipcclient.h>
#endif
#ifdef Q_OS_IOS
@ -25,8 +25,9 @@
QFile Logger::m_file;
QTextStream Logger::m_textStream;
QString Logger::m_logFileName = QString("%1.log").arg(APPLICATION_NAME);
QString Logger::m_serviceLogFileName = QString("%1.log").arg(SERVICE_NAME);
void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
if (msg.simplified().isEmpty()) {
return;
@ -37,12 +38,12 @@ void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
return;
}
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font") || msg.startsWith("stale focus object")) {
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font")
|| msg.startsWith("stale focus object")) {
return;
}
Logger::m_textStream << qFormatLogMessage(type, context, msg) << Qt::endl << Qt::flush;
Logger::appendAllLog(qFormatLogMessage(type, context, msg));
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush;
}
@ -53,36 +54,24 @@ Logger &Logger::Instance()
return s;
}
void Logger::appendSshLog(const QString &log)
bool Logger::init(bool isServiceLogger)
{
QString dt = QDateTime::currentDateTime().toString();
Instance().m_sshLog.append(dt + ": " + log + "\n");
emit Instance().sshLogChanged(Instance().sshLog());
}
void Logger::appendAllLog(const QString &log)
{
Instance().m_allLog.append(log + "\n");
emit Instance().allLogChanged(Instance().allLog());
}
bool Logger::init()
{
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
QString path = userLogsDir();
QString path = isServiceLogger ? systemLogDir() : userLogsDir();
QString logFileName = isServiceLogger ? m_serviceLogFileName : m_logFileName ;
QDir appDir(path);
if (!appDir.mkpath(path)) {
return false;
}
m_file.setFileName(appDir.filePath(m_logFileName));
m_file.setFileName(appDir.filePath(logFileName));
if (!m_file.open(QIODevice::Append)) {
qWarning() << "Cannot open log file:" << m_logFileName;
qWarning() << "Cannot open log file:" << logFileName;
return false;
}
m_file.setTextModeEnabled(true);
m_textStream.setDevice(&m_file);
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
#if !defined(QT_DEBUG) || defined(Q_OS_IOS)
qInstallMessageHandler(debugMessageHandler);
@ -99,7 +88,8 @@ void Logger::deInit()
m_file.close();
}
bool Logger::setServiceLogsEnabled(bool enabled) {
bool Logger::setServiceLogsEnabled(bool enabled)
{
#ifdef AMNEZIA_DESKTOP
IpcClient *m_IpcClient = new IpcClient;
@ -112,8 +102,7 @@ bool Logger::setServiceLogsEnabled(bool enabled) {
if (m_IpcClient->Interface()) {
m_IpcClient->Interface()->setLogsEnabled(enabled);
}
else {
} else {
qWarning() << "Error occurred setting up service logs";
return false;
}
@ -127,11 +116,32 @@ QString Logger::userLogsDir()
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/log";
}
QString Logger::systemLogDir()
{
#ifdef Q_OS_WIN
QStringList locationList = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
QString primaryLocation = "ProgramData";
foreach (const QString &location, locationList) {
if (location.contains(primaryLocation)) {
return QString("%1/%2/log").arg(location).arg(APPLICATION_NAME);
}
}
return QString();
#else
return QString("/var/log/%1").arg(APPLICATION_NAME);
#endif
}
QString Logger::userLogsFilePath()
{
return userLogsDir() + QDir::separator() + m_logFileName;
}
QString Logger::serviceLogsFilePath()
{
return systemLogDir() + QDir::separator() + m_serviceLogFileName;
}
QString Logger::getLogFile()
{
m_file.flush();
@ -145,12 +155,26 @@ QString Logger::getLogFile()
#else
return qtLog;
#endif
}
bool Logger::openLogsFolder()
QString Logger::getServiceLogFile()
{
QString path = userLogsDir();
m_file.flush();
QFile file(serviceLogsFilePath());
file.open(QIODevice::ReadOnly);
QString qtLog = file.readAll();
#ifdef Q_OS_IOS
return QString().fromStdString(AmneziaVPN::swiftUpdateLogData(qtLog.toStdString()));
#else
return qtLog;
#endif
}
bool Logger::openLogsFolder(bool isServiceLogger)
{
QString path = isServiceLogger ? systemLogDir() : userLogsDir();
#ifdef Q_OS_WIN
path = "file:///" + path;
#endif
@ -161,27 +185,12 @@ bool Logger::openLogsFolder()
return true;
}
bool Logger::openServiceLogsFolder()
{
QString path = Utils::systemLogPath();
#ifdef Q_OS_WIN
path = "file:///" + path;
#endif
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
return true;
}
QString Logger::appLogFileNamePath()
{
return m_file.fileName();
}
void Logger::clearLogs()
void Logger::clearLogs(bool isServiceLogger)
{
bool isLogActive = m_file.isOpen();
m_file.close();
QFile file(userLogsFilePath());
QFile file(isServiceLogger ? serviceLogsFilePath() : userLogsFilePath());
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
file.resize(0);
@ -192,7 +201,7 @@ void Logger::clearLogs()
#endif
if (isLogActive) {
init();
init(isServiceLogger);
}
}
@ -210,8 +219,7 @@ void Logger::clearServiceLogs()
if (m_IpcClient->Interface()) {
m_IpcClient->Interface()->clearLogs();
}
else {
} else {
qWarning() << "Error occurred cleaning up service logs";
}
#endif
@ -219,26 +227,41 @@ void Logger::clearServiceLogs()
void Logger::cleanUp()
{
clearLogs();
clearLogs(false);
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
dir.removeRecursively();
clearServiceLogs();
clearLogs(true);
}
Logger::Log::Log(Logger* logger, LogLevel logLevel)
: m_logger(logger), m_logLevel(logLevel), m_data(new Data()) {}
Logger::Log::Log(Logger *logger, LogLevel logLevel) : m_logger(logger), m_logLevel(logLevel), m_data(new Data())
{
}
Logger::Log::~Log() {
Logger::Log::~Log()
{
qDebug() << "Amnezia" << m_logger->className() << m_data->m_buffer.trimmed();
delete m_data;
}
Logger::Log Logger::error() { return Log(this, LogLevel::Error); }
Logger::Log Logger::warning() { return Log(this, LogLevel::Warning); }
Logger::Log Logger::info() { return Log(this, LogLevel::Info); }
Logger::Log Logger::debug() { return Log(this, LogLevel::Debug); }
QString Logger::sensitive(const QString& input) {
Logger::Log Logger::error()
{
return Log(this, LogLevel::Error);
}
Logger::Log Logger::warning()
{
return Log(this, LogLevel::Warning);
}
Logger::Log Logger::info()
{
return Log(this, LogLevel::Info);
}
Logger::Log Logger::debug()
{
return Log(this, LogLevel::Debug);
}
QString Logger::sensitive(const QString &input)
{
#ifdef Q_DEBUG
return input;
#else
@ -247,48 +270,51 @@ QString Logger::sensitive(const QString& input) {
#endif
}
#define CREATE_LOG_OP_REF(x) \
Logger::Log& Logger::Log::operator<<(x t) { \
m_data->m_ts << t << ' '; \
return *this; \
}
#define CREATE_LOG_OP_REF(x) \
Logger::Log &Logger::Log::operator<<(x t) \
{ \
m_data->m_ts << t << ' '; \
return *this; \
}
CREATE_LOG_OP_REF(uint64_t);
CREATE_LOG_OP_REF(const char*);
CREATE_LOG_OP_REF(const QString&);
CREATE_LOG_OP_REF(const QByteArray&);
CREATE_LOG_OP_REF(const void*);
CREATE_LOG_OP_REF(const char *);
CREATE_LOG_OP_REF(const QString &);
CREATE_LOG_OP_REF(const QByteArray &);
CREATE_LOG_OP_REF(const void *);
#undef CREATE_LOG_OP_REF
Logger::Log& Logger::Log::operator<<(const QStringList& t) {
Logger::Log &Logger::Log::operator<<(const QStringList &t)
{
m_data->m_ts << '[' << t.join(",") << ']' << ' ';
return *this;
}
Logger::Log& Logger::Log::operator<<(const QJsonObject& t) {
Logger::Log &Logger::Log::operator<<(const QJsonObject &t)
{
m_data->m_ts << QJsonDocument(t).toJson(QJsonDocument::Indented) << ' ';
return *this;
}
Logger::Log& Logger::Log::operator<<(QTextStreamFunction t) {
Logger::Log &Logger::Log::operator<<(QTextStreamFunction t)
{
m_data->m_ts << t;
return *this;
}
void Logger::Log::addMetaEnum(quint64 value, const QMetaObject* meta,
const char* name) {
void Logger::Log::addMetaEnum(quint64 value, const QMetaObject *meta, const char *name)
{
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
QString out;
QTextStream ts(&out);
if (const char* scope = me.scope()) {
if (const char *scope = me.scope()) {
ts << scope << "::";
}
const char* key = me.valueToKey(static_cast<int>(value));
const char *key = me.valueToKey(static_cast<int>(value));
const bool scoped = me.isScoped();
if (scoped || !key) {
ts << me.enumName() << (!key ? "(" : "::");

114
common/logger/logger.h Normal file
View file

@ -0,0 +1,114 @@
#ifndef LOGGER_H
#define LOGGER_H
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QString>
#include <QTextStream>
#include "mozilla/shared/loglevel.h"
class Logger : public QObject
{
Q_OBJECT
public:
static Logger &Instance();
static bool init(bool isServiceLogger);
static void deInit();
static bool setServiceLogsEnabled(bool enabled);
static bool openLogsFolder(bool isServiceLogger);
static void clearLogs(bool isServiceLogger);
static void clearServiceLogs();
static void cleanUp();
static QString userLogsFilePath();
static QString serviceLogsFilePath();
static QString systemLogDir();
static QString getLogFile();
static QString getServiceLogFile();
// compat with Mozilla logger
Logger(const QString &className)
{
m_className = className;
}
const QString &className() const
{
return m_className;
}
class Log
{
public:
Log(Logger *logger, LogLevel level);
~Log();
Log &operator<<(uint64_t t);
Log &operator<<(const char *t);
Log &operator<<(const QString &t);
Log &operator<<(const QStringList &t);
Log &operator<<(const QByteArray &t);
Log &operator<<(const QJsonObject &t);
Log &operator<<(QTextStreamFunction t);
Log &operator<<(const void *t);
// Q_ENUM
template<typename T> typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, Log &>::type operator<<(T t)
{
const QMetaObject *meta = qt_getEnumMetaObject(t);
const char *name = qt_getEnumName(t);
addMetaEnum(typename QFlags<T>::Int(t), meta, name);
return *this;
}
private:
void addMetaEnum(quint64 value, const QMetaObject *meta, const char *name);
Logger *m_logger;
LogLevel m_logLevel;
struct Data
{
Data() : m_ts(&m_buffer, QIODevice::WriteOnly)
{
}
QString m_buffer;
QTextStream m_ts;
};
Data *m_data;
};
Log error();
Log warning();
Log info();
Log debug();
QString sensitive(const QString &input);
private:
Logger() {};
Logger(Logger const &) = delete;
Logger &operator=(Logger const &) = delete;
static QString userLogsDir();
static QFile m_file;
static QTextStream m_textStream;
static QString m_logFileName;
static QString m_serviceLogFileName;
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
// compat with Mozilla logger
QString m_className;
};
#endif // LOGGER_H

View file

@ -1,32 +1,32 @@
#include "ipcserver.h"
#include <QObject>
#include <QDateTime>
#include <QLocalSocket>
#include <QFileInfo>
#include <QLocalSocket>
#include <QObject>
#include "router.h"
#include "logger.h"
#include "router.h"
#include "../client/protocols/protocols_defs.h"
#ifdef Q_OS_WIN
#include "tapcontroller_win.h"
#include "../client/platforms/windows/daemon/windowsfirewall.h"
#include "../client/platforms/windows/daemon/windowsdaemon.h"
#include "../client/platforms/windows/daemon/windowsdaemon.h"
#include "../client/platforms/windows/daemon/windowsfirewall.h"
#include "tapcontroller_win.h"
#endif
#ifdef Q_OS_LINUX
#include "../client/platforms/linux/daemon/linuxfirewall.h"
#include "../client/platforms/linux/daemon/linuxfirewall.h"
#endif
#ifdef Q_OS_MACOS
#include "../client/platforms/macos/daemon/macosfirewall.h"
#include "../client/platforms/macos/daemon/macosfirewall.h"
#endif
IpcServer::IpcServer(QObject *parent):
IpcInterfaceSource(parent)
IpcServer::IpcServer(QObject *parent) : IpcInterfaceSource(parent)
{}
{
}
int IpcServer::createPrivilegedProcess()
{
@ -58,23 +58,10 @@ int IpcServer::createPrivilegedProcess()
}
});
QObject::connect(pd.serverNode.data(), &QRemoteObjectHost::error, this, [pd](QRemoteObjectNode::ErrorCode errorCode) {
qDebug() << "QRemoteObjectHost::error" << errorCode;
});
QObject::connect(pd.serverNode.data(), &QRemoteObjectHost::error, this,
[pd](QRemoteObjectNode::ErrorCode errorCode) { qDebug() << "QRemoteObjectHost::error" << errorCode; });
QObject::connect(pd.serverNode.data(), &QRemoteObjectHost::destroyed, this, [pd]() {
qDebug() << "QRemoteObjectHost::destroyed";
});
// connect(pd.ipcProcess.data(), &IpcServerProcess::finished, this, [this, pid=m_localpid](int exitCode, QProcess::ExitStatus exitStatus){
// qDebug() << "IpcServerProcess finished" << exitCode << exitStatus;
//// if (m_processes.contains(pid)) {
//// m_processes[pid].ipcProcess.reset();
//// m_processes[pid].serverNode.reset();
//// m_processes[pid].localServer.reset();
//// m_processes.remove(pid);
//// }
// });
QObject::connect(pd.serverNode.data(), &QRemoteObjectHost::destroyed, this, [pd]() { qDebug() << "QRemoteObjectHost::destroyed"; });
m_processes.insert(m_localpid, pd);
@ -105,7 +92,7 @@ bool IpcServer::routeDeleteList(const QString &gw, const QStringList &ips)
qDebug() << "IpcServer::routeDeleteList";
#endif
return Router::routeDeleteList(gw ,ips);
return Router::routeDeleteList(gw, ips);
}
void IpcServer::flushDns()
@ -158,12 +145,13 @@ void IpcServer::cleanUp()
qDebug() << "IpcServer::cleanUp";
#endif
Logger::deinit();
Logger::deInit();
Logger::cleanUp();
}
void IpcServer::clearLogs() {
Logger::clearLogs();
void IpcServer::clearLogs()
{
Logger::clearLogs(true);
}
bool IpcServer::createTun(const QString &dev, const QString &subnet)
@ -176,7 +164,7 @@ bool IpcServer::deleteTun(const QString &dev)
return Router::deleteTun(dev);
}
bool IpcServer::updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers)
bool IpcServer::updateResolvers(const QString &ifname, const QList<QHostAddress> &resolvers)
{
return Router::updateResolvers(ifname, resolvers);
}
@ -197,14 +185,12 @@ void IpcServer::setLogsEnabled(bool enabled)
#endif
if (enabled) {
Logger::init();
}
else {
Logger::deinit();
Logger::init(true);
} else {
Logger::deInit();
}
}
bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterIndex)
{
#ifdef Q_OS_WIN
@ -220,13 +206,11 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
QStringList allownets;
QStringList blocknets;
if (splitTunnelType == 0)
{
if (splitTunnelType == 0) {
blockAll = true;
allowNets = true;
allownets.append(configStr.value(amnezia::config_key::hostName).toString());
} else if (splitTunnelType == 1)
{
} else if (splitTunnelType == 1) {
blockNets = true;
for (auto v : splitTunnelSites) {
blocknets.append(v.toString());
@ -268,18 +252,17 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
// double-check + ensure our firewall is installed and enabled. This is necessary as
// other software may disable pfctl before re-enabling with their own rules (e.g other VPNs)
if (!MacOSFirewall::isInstalled()) MacOSFirewall::install();
if (!MacOSFirewall::isInstalled())
MacOSFirewall::install();
MacOSFirewall::ensureRootAnchorPriority();
MacOSFirewall::setAnchorEnabled(QStringLiteral("000.allowLoopback"), true);
MacOSFirewall::setAnchorEnabled(QStringLiteral("100.blockAll"), blockAll);
MacOSFirewall::setAnchorEnabled(QStringLiteral("110.allowNets"), allowNets);
MacOSFirewall::setAnchorTable(QStringLiteral("110.allowNets"), allowNets,
QStringLiteral("allownets"), allownets);
MacOSFirewall::setAnchorTable(QStringLiteral("110.allowNets"), allowNets, QStringLiteral("allownets"), allownets);
MacOSFirewall::setAnchorEnabled(QStringLiteral("120.blockNets"), blockNets);
MacOSFirewall::setAnchorTable(QStringLiteral("120.blockNets"), blockNets,
QStringLiteral("blocknets"), blocknets);
MacOSFirewall::setAnchorTable(QStringLiteral("120.blockNets"), blockNets, QStringLiteral("blocknets"), blocknets);
MacOSFirewall::setAnchorEnabled(QStringLiteral("200.allowVPN"), true);
MacOSFirewall::setAnchorEnabled(QStringLiteral("250.blockIPv6"), true);
MacOSFirewall::setAnchorEnabled(QStringLiteral("290.allowDHCP"), true);
@ -330,10 +313,8 @@ bool IpcServer::enablePeerTraffic(const QJsonObject &configStr)
// Use APP split tunnel
if (splitTunnelType == 0 || splitTunnelType == 2) {
config.m_allowedIPAddressRanges.append(
IPAddress(QHostAddress("0.0.0.0"), 0));
config.m_allowedIPAddressRanges.append(
IPAddress(QHostAddress("::"), 0));
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress("0.0.0.0"), 0));
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress("::"), 0));
}
if (splitTunnelType == 1) {
@ -341,10 +322,9 @@ bool IpcServer::enablePeerTraffic(const QJsonObject &configStr)
QString ipRange = v.toString();
if (ipRange.split('/').size() > 1) {
config.m_allowedIPAddressRanges.append(
IPAddress(QHostAddress(ipRange.split('/')[0]), atoi(ipRange.split('/')[1].toLocal8Bit())));
IPAddress(QHostAddress(ipRange.split('/')[0]), atoi(ipRange.split('/')[1].toLocal8Bit())));
} else {
config.m_allowedIPAddressRanges.append(
IPAddress(QHostAddress(ipRange), 32));
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress(ipRange), 32));
}
}
}
@ -357,7 +337,7 @@ bool IpcServer::enablePeerTraffic(const QJsonObject &configStr)
}
}
for (const QJsonValue& i : configStr.value(amnezia::config_key::splitTunnelApps).toArray()) {
for (const QJsonValue &i : configStr.value(amnezia::config_key::splitTunnelApps).toArray()) {
if (!i.isString()) {
break;
}

View file

@ -19,7 +19,7 @@ set(HEADERS
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserver.h
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserverprocess.h
${CMAKE_CURRENT_LIST_DIR}/localserver.h
${CMAKE_CURRENT_LIST_DIR}/logger.h
${CMAKE_CURRENT_LIST_DIR}/../../common/logger/logger.h
${CMAKE_CURRENT_LIST_DIR}/router.h
${CMAKE_CURRENT_LIST_DIR}/systemservice.h
${CMAKE_CURRENT_BINARY_DIR}/version.h
@ -31,7 +31,7 @@ set(SOURCES
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserver.cpp
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserverprocess.cpp
${CMAKE_CURRENT_LIST_DIR}/localserver.cpp
${CMAKE_CURRENT_LIST_DIR}/logger.cpp
${CMAKE_CURRENT_LIST_DIR}/../../common/logger/logger.cpp
${CMAKE_CURRENT_LIST_DIR}/main.cpp
${CMAKE_CURRENT_LIST_DIR}/router.cpp
${CMAKE_CURRENT_LIST_DIR}/systemservice.cpp
@ -238,6 +238,7 @@ include_directories(
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/../../client
${CMAKE_CURRENT_LIST_DIR}/../../ipc
${CMAKE_CURRENT_LIST_DIR}/../../common/logger
${CMAKE_CURRENT_BINARY_DIR}
)

View file

@ -1,185 +0,0 @@
#include "logger.h"
#include <QDir>
#include <QJsonDocument>
#include <QMetaEnum>
#include <QStandardPaths>
#include <iostream>
#include "version.h"
#include "utilities.h"
QFile Logger::m_file;
QTextStream Logger::m_textStream;
QString Logger::m_logFileName = QString("%1.log").arg(SERVICE_NAME);
void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
if (msg.simplified().isEmpty()) {
return;
}
Logger::m_textStream << qFormatLogMessage(type, context, msg) << Qt::endl << Qt::flush;
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush;
}
bool Logger::init()
{
if (m_file.isOpen()) return true;
QString path = Utils::systemLogPath();
QDir appDir(path);
if (!appDir.mkpath(path)) {
return false;
}
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
m_file.setFileName(appDir.filePath(m_logFileName));
if (!m_file.open(QIODevice::Append)) {
qWarning() << "Cannot open log file:" << m_logFileName;
return false;
}
m_file.setTextModeEnabled(true);
m_textStream.setDevice(&m_file);
qInstallMessageHandler(debugMessageHandler);
return true;
}
void Logger::deinit()
{
m_file.close();
m_textStream.setDevice(nullptr);
qInstallMessageHandler(nullptr);
}
QString Logger::serviceLogFileNamePath()
{
return m_file.fileName();
}
void Logger::clearLogs()
{
bool isLogActive = m_file.isOpen();
m_file.close();
QString path = Utils::systemLogPath();
QDir appDir(path);
QFile file;
file.setFileName(appDir.filePath(m_logFileName));
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
file.resize(0);
file.close();
if (isLogActive) {
init();
}
}
void Logger::cleanUp()
{
clearLogs();
deinit();
QString path = Utils::systemLogPath();
QDir appDir(path);
{
QFile file;
file.setFileName(appDir.filePath(m_logFileName));
file.remove();
}
{
QFile file;
file.setFileName(appDir.filePath("openvpn.log"));
file.remove();
}
#ifdef Q_OS_WINDOWS
QDir dir(Utils::systemLogPath());
dir.removeRecursively();
#endif
}
Logger::Log::Log(Logger* logger, LogLevel logLevel)
: m_logger(logger), m_logLevel(logLevel), m_data(new Data()) {}
Logger::Log::~Log() {
qDebug() << "Amnezia" << m_logger->className() << m_data->m_buffer.trimmed();
delete m_data;
}
Logger::Log Logger::error() { return Log(this, LogLevel::Error); }
Logger::Log Logger::warning() { return Log(this, LogLevel::Warning); }
Logger::Log Logger::info() { return Log(this, LogLevel::Info); }
Logger::Log Logger::debug() { return Log(this, LogLevel::Debug); }
QString Logger::sensitive(const QString& input) {
#ifdef Q_DEBUG
return input;
#else
Q_UNUSED(input);
return QString(8, 'X');
#endif
}
#define CREATE_LOG_OP_REF(x) \
Logger::Log& Logger::Log::operator<<(x t) { \
m_data->m_ts << t << ' '; \
return *this; \
}
CREATE_LOG_OP_REF(uint64_t);
CREATE_LOG_OP_REF(const char*);
CREATE_LOG_OP_REF(const QString&);
CREATE_LOG_OP_REF(const QByteArray&);
CREATE_LOG_OP_REF(const void*);
#undef CREATE_LOG_OP_REF
Logger::Log& Logger::Log::operator<<(const QStringList& t) {
m_data->m_ts << '[' << t.join(",") << ']' << ' ';
return *this;
}
Logger::Log& Logger::Log::operator<<(const QJsonObject& t) {
m_data->m_ts << QJsonDocument(t).toJson(QJsonDocument::Indented) << ' ';
return *this;
}
Logger::Log& Logger::Log::operator<<(QTextStreamFunction t) {
m_data->m_ts << t;
return *this;
}
void Logger::Log::addMetaEnum(quint64 value, const QMetaObject* meta,
const char* name) {
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
QString out;
QTextStream ts(&out);
if (const char* scope = me.scope()) {
ts << scope << "::";
}
const char* key = me.valueToKey(static_cast<int>(value));
const bool scoped = me.isScoped();
if (scoped || !key) {
ts << me.enumName() << (!key ? "(" : "::");
}
if (key) {
ts << key;
} else {
ts << value << ")";
}
m_data->m_ts << out;
}

View file

@ -1,83 +0,0 @@
#ifndef LOGGER_H
#define LOGGER_H
#include <QDebug>
#include <QFile>
#include <QString>
#include <QTextStream>
#include "mozilla/shared/loglevel.h"
class Logger
{
public:
static bool init();
static void deinit();
static QString serviceLogFileNamePath();
static void clearLogs();
static void cleanUp();
// compat with Mozilla logger
Logger(const QString &className) { m_className = className; }
const QString& className() const { return m_className; }
class Log {
public:
Log(Logger* logger, LogLevel level);
~Log();
Log& operator<<(uint64_t t);
Log& operator<<(const char* t);
Log& operator<<(const QString& t);
Log& operator<<(const QStringList& t);
Log& operator<<(const QByteArray& t);
Log& operator<<(const QJsonObject& t);
Log& operator<<(QTextStreamFunction t);
Log& operator<<(const void* t);
// Q_ENUM
template <typename T>
typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, Log&>::type
operator<<(T t) {
const QMetaObject* meta = qt_getEnumMetaObject(t);
const char* name = qt_getEnumName(t);
addMetaEnum(typename QFlags<T>::Int(t), meta, name);
return *this;
}
private:
void addMetaEnum(quint64 value, const QMetaObject* meta, const char* name);
Logger* m_logger;
LogLevel m_logLevel;
struct Data {
Data() : m_ts(&m_buffer, QIODevice::WriteOnly) {}
QString m_buffer;
QTextStream m_ts;
};
Data* m_data;
};
Log error();
Log warning();
Log info();
Log debug();
QString sensitive(const QString& input);
private:
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
static QFile m_file;
static QString m_logFileName;
static QTextStream m_textStream;
// compat with Mozilla logger
QString m_className;
};
#endif // LOGGER_H

View file

@ -44,7 +44,7 @@ int runApplication(int argc, char** argv)
int main(int argc, char **argv)
{
Utils::initializePath(Utils::systemLogPath());
Utils::initializePath(Logger::systemLogDir());
if (argc >= 2) {
qInfo() << "Started as console application";