mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Basic logging implemented
Implemented scuffed logging settings page Add helper function to PathManager to create an arbitrary folder
This commit is contained in:
parent
f474db9443
commit
2f0844ebd9
14 changed files with 201 additions and 151 deletions
|
@ -101,8 +101,8 @@ SOURCES += \
|
|||
src/widgets/settingsdialog.cpp \
|
||||
src/widgets/helper/settingsdialogtab.cpp \
|
||||
src/widgets/textinputdialog.cpp \
|
||||
src/logging/loggingmanager.cpp \
|
||||
src/logging/loggingchannel.cpp \
|
||||
src/singletons/loggingmanager.cpp \
|
||||
src/singletons/helper/loggingchannel.cpp \
|
||||
src/singletons/windowmanager.cpp \
|
||||
src/singletons/channelmanager.cpp \
|
||||
src/singletons/fontmanager.cpp \
|
||||
|
@ -193,8 +193,8 @@ HEADERS += \
|
|||
src/widgets/helper/resizingtextedit.hpp \
|
||||
src/messages/limitedqueue.hpp \
|
||||
src/messages/limitedqueuesnapshot.hpp \
|
||||
src/logging/loggingmanager.hpp \
|
||||
src/logging/loggingchannel.hpp \
|
||||
src/singletons/loggingmanager.hpp \
|
||||
src/singletons/helper/loggingchannel.hpp \
|
||||
src/singletons/channelmanager.hpp \
|
||||
src/singletons/windowmanager.hpp \
|
||||
src/singletons/settingsmanager.hpp \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "application.hpp"
|
||||
#include "logging/loggingmanager.hpp"
|
||||
#include "singletons/loggingmanager.hpp"
|
||||
#include "singletons/accountmanager.hpp"
|
||||
#include "singletons/commandmanager.hpp"
|
||||
#include "singletons/emotemanager.hpp"
|
||||
|
@ -18,7 +18,7 @@ Application::Application()
|
|||
{
|
||||
singletons::WindowManager::getInstance();
|
||||
|
||||
logging::init();
|
||||
singletons::LoggingManager::getInstance();
|
||||
|
||||
singletons::SettingManager::getInstance().init();
|
||||
singletons::CommandManager::getInstance().loadCommands();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "channel.hpp"
|
||||
#include "debug/log.hpp"
|
||||
#include "logging/loggingmanager.hpp"
|
||||
#include "messages/message.hpp"
|
||||
#include "singletons/emotemanager.hpp"
|
||||
#include "singletons/ircmanager.hpp"
|
||||
#include "singletons/loggingmanager.hpp"
|
||||
#include "singletons/windowmanager.hpp"
|
||||
|
||||
#include <QJsonArray>
|
||||
|
@ -20,7 +20,6 @@ namespace chatterino {
|
|||
|
||||
Channel::Channel(const QString &_name)
|
||||
: name(_name)
|
||||
// , loggingChannel(logging::get(name))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -45,12 +44,10 @@ void Channel::addMessage(MessagePtr message)
|
|||
this->addRecentChatter(message);
|
||||
}
|
||||
|
||||
// if (_loggingChannel.get() != nullptr) {
|
||||
// _loggingChannel->append(message);
|
||||
// }
|
||||
singletons::LoggingManager::getInstance().addMessage(this->name, message);
|
||||
|
||||
if (this->messages.pushBack(message, deleted)) {
|
||||
messageRemovedFromStart(deleted);
|
||||
this->messageRemovedFromStart(deleted);
|
||||
}
|
||||
|
||||
this->messageAppended(message);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "logging/loggingchannel.hpp"
|
||||
#include "messages/image.hpp"
|
||||
#include "messages/limitedqueue.hpp"
|
||||
#include "messages/message.hpp"
|
||||
#include "util/concurrentmap.hpp"
|
||||
|
||||
#include <QMap>
|
||||
|
@ -60,8 +60,6 @@ public:
|
|||
|
||||
private:
|
||||
messages::LimitedQueue<messages::MessagePtr> messages;
|
||||
|
||||
// std::shared_ptr<logging::Channel> loggingChannel;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Channel> ChannelPtr;
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
#include "loggingmanager.hpp"
|
||||
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace chatterino {
|
||||
namespace logging {
|
||||
|
||||
static QString logBasePath;
|
||||
static QString channelBasePath;
|
||||
static QString whispersBasePath;
|
||||
static QString mentionsBasePath;
|
||||
|
||||
std::unordered_map<std::string, std::weak_ptr<Channel>> channels;
|
||||
|
||||
void init()
|
||||
{
|
||||
// Make sure all folders are properly created
|
||||
logBasePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
|
||||
QDir::separator() + "Logs";
|
||||
channelBasePath = logBasePath + QDir::separator() + "Channels";
|
||||
whispersBasePath = logBasePath + QDir::separator() + "Whispers";
|
||||
mentionsBasePath = logBasePath + QDir::separator() + "Mentions";
|
||||
|
||||
{
|
||||
QDir dir(logBasePath);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QDir dir(channelBasePath);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QDir dir(whispersBasePath);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QDir dir(mentionsBasePath);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const QString &getBaseDirectory(const QString &channelName)
|
||||
{
|
||||
if (channelName == "/whispers") {
|
||||
return whispersBasePath;
|
||||
} else if (channelName == "/mentions") {
|
||||
return mentionsBasePath;
|
||||
} else {
|
||||
return channelBasePath;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Channel> get(const QString &channelName)
|
||||
{
|
||||
if (channelName.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const QString &baseDirectory = getBaseDirectory(channelName);
|
||||
|
||||
auto channel = channels.find(channelName.toStdString());
|
||||
if (channel == std::end(channels)) {
|
||||
// This channel is definitely not logged yet.
|
||||
// Create shared_ptr that we will return, and store a weak_ptr reference
|
||||
std::shared_ptr<Channel> ret =
|
||||
std::shared_ptr<Channel>(new Channel(channelName, baseDirectory));
|
||||
|
||||
channels[channelName.toStdString()] = std::weak_ptr<Channel>(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (auto ret = channels[channelName.toStdString()].lock()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<Channel> ret =
|
||||
std::shared_ptr<Channel>(new Channel(channelName, baseDirectory));
|
||||
|
||||
channels[channelName.toStdString()] = std::weak_ptr<Channel>(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace logging
|
||||
} // namespace chatterino
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "loggingchannel.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace chatterino {
|
||||
namespace logging {
|
||||
|
||||
void init();
|
||||
std::shared_ptr<Channel> get(const QString &channelName);
|
||||
|
||||
} // namespace logging
|
||||
} // namespace chatterino
|
|
@ -1,35 +1,34 @@
|
|||
#include "loggingchannel.hpp"
|
||||
#include "loggingmanager.hpp"
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
namespace chatterino {
|
||||
namespace logging {
|
||||
namespace singletons {
|
||||
|
||||
Channel::Channel(const QString &_channelName, const QString &_baseDirectory)
|
||||
LoggingChannel::LoggingChannel(const QString &_channelName, const QString &_baseDirectory)
|
||||
: channelName(_channelName)
|
||||
, baseDirectory(_baseDirectory)
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
|
||||
this->fileName = this->channelName + "-" + now.toString("yyyy-MM-dd") + ".log";
|
||||
QString baseFileName = this->channelName + "-" + now.toString("yyyy-MM-dd") + ".log";
|
||||
|
||||
// Open file handle to log file of current date
|
||||
this->fileHandle.setFileName(this->baseDirectory + QDir::separator() + this->fileName);
|
||||
this->fileHandle.setFileName(this->baseDirectory + QDir::separator() + baseFileName);
|
||||
|
||||
this->fileHandle.open(QIODevice::Append);
|
||||
this->appendLine(this->generateOpeningString(now));
|
||||
}
|
||||
|
||||
Channel::~Channel()
|
||||
LoggingChannel::~LoggingChannel()
|
||||
{
|
||||
this->appendLine(this->generateClosingString());
|
||||
this->fileHandle.close();
|
||||
}
|
||||
|
||||
void Channel::append(std::shared_ptr<messages::Message> message)
|
||||
void LoggingChannel::addMessage(std::shared_ptr<messages::Message> message)
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
|
||||
|
@ -37,14 +36,21 @@ void Channel::append(std::shared_ptr<messages::Message> message)
|
|||
str.append('[');
|
||||
str.append(now.toString("HH:mm:ss"));
|
||||
str.append("] ");
|
||||
str.append(message->loginName);
|
||||
str.append(": ");
|
||||
str.append(message->searchText);
|
||||
str.append('\n');
|
||||
|
||||
if ((message->flags & messages::Message::MessageFlags::System) != 0) {
|
||||
str.append(message->searchText);
|
||||
str.append('\n');
|
||||
} else {
|
||||
str.append(message->loginName);
|
||||
str.append(": ");
|
||||
str.append(message->searchText);
|
||||
str.append('\n');
|
||||
}
|
||||
|
||||
this->appendLine(str);
|
||||
}
|
||||
|
||||
QString Channel::generateOpeningString(const QDateTime &now) const
|
||||
QString LoggingChannel::generateOpeningString(const QDateTime &now) const
|
||||
{
|
||||
QString ret = QLatin1Literal("# Start logging at ");
|
||||
|
||||
|
@ -55,7 +61,7 @@ QString Channel::generateOpeningString(const QDateTime &now) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
QString Channel::generateClosingString(const QDateTime &now) const
|
||||
QString LoggingChannel::generateClosingString(const QDateTime &now) const
|
||||
{
|
||||
QString ret = QLatin1Literal("# Stop logging at ");
|
||||
|
||||
|
@ -66,11 +72,11 @@ QString Channel::generateClosingString(const QDateTime &now) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Channel::appendLine(const QString &line)
|
||||
void LoggingChannel::appendLine(const QString &line)
|
||||
{
|
||||
this->fileHandle.write(line.toUtf8());
|
||||
this->fileHandle.flush();
|
||||
}
|
||||
|
||||
} // namespace logging
|
||||
} // namespace singletons
|
||||
} // namespace chatterino
|
|
@ -5,19 +5,20 @@
|
|||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace chatterino {
|
||||
namespace logging {
|
||||
namespace singletons {
|
||||
|
||||
class Channel
|
||||
class LoggingChannel : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
explicit Channel(const QString &_channelName, const QString &_baseDirectory);
|
||||
~Channel();
|
||||
explicit LoggingChannel(const QString &_channelName, const QString &_baseDirectory);
|
||||
|
||||
void append(std::shared_ptr<messages::Message> message);
|
||||
public:
|
||||
~LoggingChannel();
|
||||
void addMessage(std::shared_ptr<messages::Message> message);
|
||||
|
||||
private:
|
||||
QString generateOpeningString(const QDateTime &now = QDateTime::currentDateTime()) const;
|
||||
|
@ -30,7 +31,9 @@ private:
|
|||
const QString &baseDirectory;
|
||||
QString fileName;
|
||||
QFile fileHandle;
|
||||
|
||||
friend class LoggingManager;
|
||||
};
|
||||
|
||||
} // namespace logging
|
||||
} // namespace singletons
|
||||
} // namespace chatterino
|
61
src/singletons/loggingmanager.cpp
Normal file
61
src/singletons/loggingmanager.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "singletons/loggingmanager.hpp"
|
||||
#include "debug/log.hpp"
|
||||
#include "singletons/pathmanager.hpp"
|
||||
#include "singletons/settingsmanager.hpp"
|
||||
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace chatterino {
|
||||
namespace singletons {
|
||||
|
||||
LoggingManager::LoggingManager()
|
||||
: pathManager(PathManager::getInstance())
|
||||
{
|
||||
}
|
||||
|
||||
LoggingManager &LoggingManager::getInstance()
|
||||
{
|
||||
static LoggingManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void LoggingManager::addMessage(const QString &channelName, messages::MessagePtr message)
|
||||
{
|
||||
const auto &settings = singletons::SettingManager::getInstance();
|
||||
|
||||
if (!settings.enableLogging) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = this->loggingChannels.find(channelName);
|
||||
if (it == this->loggingChannels.end()) {
|
||||
auto channel = new LoggingChannel(channelName, this->getDirectoryForChannel(channelName));
|
||||
channel->addMessage(message);
|
||||
this->loggingChannels.emplace(channelName, std::move(channel));
|
||||
} else {
|
||||
it->second->addMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
QString LoggingManager::getDirectoryForChannel(const QString &channelName)
|
||||
{
|
||||
if (channelName.startsWith("/whispers")) {
|
||||
return this->pathManager.whispersLogsFolderPath;
|
||||
} else if (channelName.startsWith("/mentions")) {
|
||||
return this->pathManager.mentionsLogsFolderPath;
|
||||
} else {
|
||||
QString logPath(this->pathManager.channelsLogsFolderPath + QDir::separator() + channelName);
|
||||
|
||||
if (!this->pathManager.createFolder(logPath)) {
|
||||
debug::Log("Error creating channel logs folder for channel {}", channelName);
|
||||
}
|
||||
|
||||
return logPath;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace singletons
|
||||
} // namespace chatterino
|
32
src/singletons/loggingmanager.hpp
Normal file
32
src/singletons/loggingmanager.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include "messages/message.hpp"
|
||||
#include "singletons/helper/loggingchannel.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace chatterino {
|
||||
namespace singletons {
|
||||
|
||||
class PathManager;
|
||||
|
||||
class LoggingManager : boost::noncopyable
|
||||
{
|
||||
LoggingManager();
|
||||
|
||||
PathManager &pathManager;
|
||||
|
||||
public:
|
||||
static LoggingManager &getInstance();
|
||||
|
||||
void addMessage(const QString &channelName, messages::MessagePtr message);
|
||||
|
||||
private:
|
||||
std::map<QString, std::unique_ptr<LoggingChannel>> loggingChannels;
|
||||
QString getDirectoryForChannel(const QString &channelName);
|
||||
};
|
||||
|
||||
} // namespace singletons
|
||||
} // namespace chatterino
|
|
@ -57,8 +57,44 @@ bool PathManager::init(int argc, char **argv)
|
|||
return false;
|
||||
}
|
||||
|
||||
this->logsFolderPath = rootPath + "/Logs";
|
||||
|
||||
if (!QDir().mkpath(this->logsFolderPath)) {
|
||||
printf("Error creating logs directory: %s\n", qPrintable(this->logsFolderPath));
|
||||
return false;
|
||||
}
|
||||
|
||||
this->channelsLogsFolderPath = this->logsFolderPath + "/Channels";
|
||||
|
||||
if (!QDir().mkpath(this->channelsLogsFolderPath)) {
|
||||
printf("Error creating channelsLogs directory: %s\n",
|
||||
qPrintable(this->channelsLogsFolderPath));
|
||||
return false;
|
||||
}
|
||||
|
||||
this->whispersLogsFolderPath = this->logsFolderPath + "/Whispers";
|
||||
|
||||
if (!QDir().mkpath(this->whispersLogsFolderPath)) {
|
||||
printf("Error creating whispersLogs directory: %s\n",
|
||||
qPrintable(this->whispersLogsFolderPath));
|
||||
return false;
|
||||
}
|
||||
|
||||
this->mentionsLogsFolderPath = this->logsFolderPath + "/Mentions";
|
||||
|
||||
if (!QDir().mkpath(this->mentionsLogsFolderPath)) {
|
||||
printf("Error creating mentionsLogs directory: %s\n",
|
||||
qPrintable(this->mentionsLogsFolderPath));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PathManager::createFolder(const QString &folderPath)
|
||||
{
|
||||
return QDir().mkpath(folderPath);
|
||||
}
|
||||
|
||||
} // namespace singletons
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -17,6 +17,14 @@ public:
|
|||
QString settingsFolderPath;
|
||||
QString customFolderPath;
|
||||
QString cacheFolderPath;
|
||||
|
||||
// Logs
|
||||
QString logsFolderPath;
|
||||
QString channelsLogsFolderPath;
|
||||
QString whispersLogsFolderPath;
|
||||
QString mentionsLogsFolderPath;
|
||||
|
||||
bool createFolder(const QString &folderPath);
|
||||
};
|
||||
|
||||
} // namespace singletons
|
||||
|
|
|
@ -89,6 +89,9 @@ public:
|
|||
BoolSetting enableHighlightTaskbar = {"/highlighting/enableTaskbarFlashing", true};
|
||||
BoolSetting customHighlightSound = {"/highlighting/useCustomSound", false};
|
||||
|
||||
/// Logging
|
||||
BoolSetting enableLogging = {"/logging/enabled", false};
|
||||
|
||||
ChatterinoSetting<std::vector<messages::HighlightPhrase>> highlightProperties = {
|
||||
"/highlighting/highlights"};
|
||||
|
||||
|
|
|
@ -1,12 +1,32 @@
|
|||
#include "logspage.hpp"
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "util/layoutcreator.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
LogsPage::LogsPage()
|
||||
: SettingsPage("Logs", "")
|
||||
{
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
util::LayoutCreator<LogsPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||
|
||||
{
|
||||
auto form = layout.emplace<QFormLayout>();
|
||||
|
||||
// clang-format off
|
||||
form->addRow("Enabled:", this->createCheckBox("Enable logging", settings.enableLogging));
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
layout->addStretch(1);
|
||||
}
|
||||
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
||||
|
|
Loading…
Reference in a new issue