mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Added option to log streams by their ID, allowing for easier "per-stream" log analyzing (#5507)
This commit is contained in:
parent
b9f669d3a5
commit
9788d0f8f7
|
@ -15,6 +15,7 @@
|
||||||
- Minor: Added support for Brave & google-chrome-stable browsers. (#5452)
|
- Minor: Added support for Brave & google-chrome-stable browsers. (#5452)
|
||||||
- Minor: Added drop indicator line while dragging in tables. (#5256)
|
- Minor: Added drop indicator line while dragging in tables. (#5256)
|
||||||
- Minor: Add channel points indication for new bits power-up redemptions. (#5471)
|
- Minor: Add channel points indication for new bits power-up redemptions. (#5471)
|
||||||
|
- Minor: Added option to log streams by their ID, allowing for easier "per-stream" log analyzing. (#5507)
|
||||||
- Minor: Added `/warn <username> <reason>` command for mods. This prevents the user from chatting until they acknowledge the warning. (#5474)
|
- Minor: Added `/warn <username> <reason>` command for mods. This prevents the user from chatting until they acknowledge the warning. (#5474)
|
||||||
- Minor: Improve appearance of reply button. (#5491)
|
- Minor: Improve appearance of reply button. (#5491)
|
||||||
- Minor: Introduce HTTP API for plugins. (#5383, #5492, #5494)
|
- Minor: Introduce HTTP API for plugins. (#5383, #5492, #5494)
|
||||||
|
|
|
@ -16,7 +16,7 @@ public:
|
||||||
|
|
||||||
MOCK_METHOD(void, addMessage,
|
MOCK_METHOD(void, addMessage,
|
||||||
(const QString &channelName, MessagePtr message,
|
(const QString &channelName, MessagePtr message,
|
||||||
const QString &platformName),
|
const QString &platformName, const QString &streamID),
|
||||||
(override));
|
(override));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,7 +27,8 @@ public:
|
||||||
~EmptyLogging() override = default;
|
~EmptyLogging() override = default;
|
||||||
|
|
||||||
void addMessage(const QString &channelName, MessagePtr message,
|
void addMessage(const QString &channelName, MessagePtr message,
|
||||||
const QString &platformName) override
|
const QString &platformName,
|
||||||
|
const QString &streamID) override
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,8 @@ void Channel::addMessage(MessagePtr message, MessageContext context,
|
||||||
{
|
{
|
||||||
// Only log messages where the `DoNotLog` flag is not set
|
// Only log messages where the `DoNotLog` flag is not set
|
||||||
getIApp()->getChatLogger()->addMessage(this->name_, message,
|
getIApp()->getChatLogger()->addMessage(this->name_, message,
|
||||||
this->platform_);
|
this->platform_,
|
||||||
|
this->getCurrentStreamID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,6 +357,11 @@ void Channel::reconnect()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Channel::getCurrentStreamID() const
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Channel> Channel::getEmpty()
|
std::shared_ptr<Channel> Channel::getEmpty()
|
||||||
{
|
{
|
||||||
static std::shared_ptr<Channel> channel(new Channel("", Type::None));
|
static std::shared_ptr<Channel> channel(new Channel("", Type::None));
|
||||||
|
|
|
@ -119,6 +119,7 @@ public:
|
||||||
virtual bool shouldIgnoreHighlights() const;
|
virtual bool shouldIgnoreHighlights() const;
|
||||||
virtual bool canReconnect() const;
|
virtual bool canReconnect() const;
|
||||||
virtual void reconnect();
|
virtual void reconnect();
|
||||||
|
virtual QString getCurrentStreamID() const;
|
||||||
|
|
||||||
static std::shared_ptr<Channel> getEmpty();
|
static std::shared_ptr<Channel> getEmpty();
|
||||||
|
|
||||||
|
|
|
@ -457,6 +457,7 @@ void TwitchChannel::updateStreamStatus(
|
||||||
auto stream = *helixStream;
|
auto stream = *helixStream;
|
||||||
{
|
{
|
||||||
auto status = this->streamStatus_.access();
|
auto status = this->streamStatus_.access();
|
||||||
|
status->streamId = stream.id;
|
||||||
status->viewerCount = stream.viewerCount;
|
status->viewerCount = stream.viewerCount;
|
||||||
status->gameId = stream.gameId;
|
status->gameId = stream.gameId;
|
||||||
status->game = stream.gameName;
|
status->game = stream.gameName;
|
||||||
|
@ -770,6 +771,17 @@ void TwitchChannel::reconnect()
|
||||||
getIApp()->getTwitchAbstract()->connect();
|
getIApp()->getTwitchAbstract()->connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString TwitchChannel::getCurrentStreamID() const
|
||||||
|
{
|
||||||
|
auto streamStatus = this->accessStreamStatus();
|
||||||
|
if (streamStatus->live)
|
||||||
|
{
|
||||||
|
return streamStatus->streamId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
QString TwitchChannel::roomId() const
|
QString TwitchChannel::roomId() const
|
||||||
{
|
{
|
||||||
return *this->roomID_.access();
|
return *this->roomID_.access();
|
||||||
|
|
|
@ -87,6 +87,7 @@ public:
|
||||||
QString uptime;
|
QString uptime;
|
||||||
int uptimeSeconds = 0;
|
int uptimeSeconds = 0;
|
||||||
QString streamType;
|
QString streamType;
|
||||||
|
QString streamId;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RoomModes {
|
struct RoomModes {
|
||||||
|
@ -133,6 +134,7 @@ public:
|
||||||
bool hasHighRateLimit() const override;
|
bool hasHighRateLimit() const override;
|
||||||
bool canReconnect() const override;
|
bool canReconnect() const override;
|
||||||
void reconnect() override;
|
void reconnect() override;
|
||||||
|
QString getCurrentStreamID() const override;
|
||||||
void createClip();
|
void createClip();
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
|
|
|
@ -33,7 +33,7 @@ Logging::Logging(Settings &settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logging::addMessage(const QString &channelName, MessagePtr message,
|
void Logging::addMessage(const QString &channelName, MessagePtr message,
|
||||||
const QString &platformName)
|
const QString &platformName, const QString &streamID)
|
||||||
{
|
{
|
||||||
this->threadGuard.guard();
|
this->threadGuard.guard();
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ void Logging::addMessage(const QString &channelName, MessagePtr message,
|
||||||
if (platIt == this->loggingChannels_.end())
|
if (platIt == this->loggingChannels_.end())
|
||||||
{
|
{
|
||||||
auto *channel = new LoggingChannel(channelName, platformName);
|
auto *channel = new LoggingChannel(channelName, platformName);
|
||||||
channel->addMessage(message);
|
channel->addMessage(message, streamID);
|
||||||
auto map = std::map<QString, std::unique_ptr<LoggingChannel>>();
|
auto map = std::map<QString, std::unique_ptr<LoggingChannel>>();
|
||||||
this->loggingChannels_[platformName] = std::move(map);
|
this->loggingChannels_[platformName] = std::move(map);
|
||||||
auto &ref = this->loggingChannels_.at(platformName);
|
auto &ref = this->loggingChannels_.at(platformName);
|
||||||
|
@ -65,12 +65,12 @@ void Logging::addMessage(const QString &channelName, MessagePtr message,
|
||||||
if (chanIt == platIt->second.end())
|
if (chanIt == platIt->second.end())
|
||||||
{
|
{
|
||||||
auto *channel = new LoggingChannel(channelName, platformName);
|
auto *channel = new LoggingChannel(channelName, platformName);
|
||||||
channel->addMessage(message);
|
channel->addMessage(message, streamID);
|
||||||
platIt->second.emplace(channelName, std::move(channel));
|
platIt->second.emplace(channelName, std::move(channel));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
chanIt->second->addMessage(message);
|
chanIt->second->addMessage(message, streamID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ public:
|
||||||
virtual ~ILogging() = default;
|
virtual ~ILogging() = default;
|
||||||
|
|
||||||
virtual void addMessage(const QString &channelName, MessagePtr message,
|
virtual void addMessage(const QString &channelName, MessagePtr message,
|
||||||
const QString &platformName) = 0;
|
const QString &platformName,
|
||||||
|
const QString &streamID) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Logging : public ILogging
|
class Logging : public ILogging
|
||||||
|
@ -31,7 +32,8 @@ public:
|
||||||
Logging(Settings &settings);
|
Logging(Settings &settings);
|
||||||
|
|
||||||
void addMessage(const QString &channelName, MessagePtr message,
|
void addMessage(const QString &channelName, MessagePtr message,
|
||||||
const QString &platformName) override;
|
const QString &platformName,
|
||||||
|
const QString &streamID) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using PlatformName = QString;
|
using PlatformName = QString;
|
||||||
|
|
|
@ -447,6 +447,10 @@ public:
|
||||||
BoolSetting enableLogging = {"/logging/enabled", false};
|
BoolSetting enableLogging = {"/logging/enabled", false};
|
||||||
BoolSetting onlyLogListedChannels = {"/logging/onlyLogListedChannels",
|
BoolSetting onlyLogListedChannels = {"/logging/onlyLogListedChannels",
|
||||||
false};
|
false};
|
||||||
|
BoolSetting separatelyStoreStreamLogs = {
|
||||||
|
"/logging/separatelyStoreStreamLogs",
|
||||||
|
false,
|
||||||
|
};
|
||||||
|
|
||||||
QStringSetting logPath = {"/logging/path", ""};
|
QStringSetting logPath = {"/logging/path", ""};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "LoggingChannel.hpp"
|
#include "singletons/helper/LoggingChannel.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "common/QLogging.hpp"
|
#include "common/QLogging.hpp"
|
||||||
|
@ -7,16 +7,58 @@
|
||||||
#include "singletons/Paths.hpp"
|
#include "singletons/Paths.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const QByteArray ENDLINE("\n");
|
||||||
|
|
||||||
|
void appendLine(QFile &fileHandle, const QString &line)
|
||||||
|
{
|
||||||
|
assert(fileHandle.isOpen());
|
||||||
|
assert(fileHandle.isWritable());
|
||||||
|
|
||||||
|
fileHandle.write(line.toUtf8());
|
||||||
|
fileHandle.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString generateOpeningString(
|
||||||
|
const QDateTime &now = QDateTime::currentDateTime())
|
||||||
|
{
|
||||||
|
QString ret("# Start logging at ");
|
||||||
|
|
||||||
|
ret.append(now.toString("yyyy-MM-dd HH:mm:ss "));
|
||||||
|
ret.append(now.timeZoneAbbreviation());
|
||||||
|
ret.append(ENDLINE);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString generateClosingString(
|
||||||
|
const QDateTime &now = QDateTime::currentDateTime())
|
||||||
|
{
|
||||||
|
QString ret("# Stop logging at ");
|
||||||
|
|
||||||
|
ret.append(now.toString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
ret.append(now.timeZoneAbbreviation());
|
||||||
|
ret.append(ENDLINE);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString generateDateString(const QDateTime &now)
|
||||||
|
{
|
||||||
|
return now.toString("yyyy-MM-dd");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
QByteArray endline("\n");
|
LoggingChannel::LoggingChannel(QString _channelName, QString _platform)
|
||||||
|
: channelName(std::move(_channelName))
|
||||||
LoggingChannel::LoggingChannel(const QString &_channelName,
|
, platform(std::move(_platform))
|
||||||
const QString &_platform)
|
|
||||||
: channelName(_channelName)
|
|
||||||
, platform(_platform)
|
|
||||||
{
|
{
|
||||||
if (this->channelName.startsWith("/whispers"))
|
if (this->channelName.startsWith("/whispers"))
|
||||||
{
|
{
|
||||||
|
@ -54,14 +96,15 @@ LoggingChannel::LoggingChannel(const QString &_channelName,
|
||||||
|
|
||||||
LoggingChannel::~LoggingChannel()
|
LoggingChannel::~LoggingChannel()
|
||||||
{
|
{
|
||||||
this->appendLine(this->generateClosingString());
|
appendLine(this->fileHandle, generateClosingString());
|
||||||
this->fileHandle.close();
|
this->fileHandle.close();
|
||||||
|
this->currentStreamFileHandle.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggingChannel::openLogFile()
|
void LoggingChannel::openLogFile()
|
||||||
{
|
{
|
||||||
QDateTime now = QDateTime::currentDateTime();
|
QDateTime now = QDateTime::currentDateTime();
|
||||||
this->dateString = this->generateDateString(now);
|
this->dateString = generateDateString(now);
|
||||||
|
|
||||||
if (this->fileHandle.isOpen())
|
if (this->fileHandle.isOpen())
|
||||||
{
|
{
|
||||||
|
@ -87,14 +130,45 @@ void LoggingChannel::openLogFile()
|
||||||
|
|
||||||
this->fileHandle.open(QIODevice::Append);
|
this->fileHandle.open(QIODevice::Append);
|
||||||
|
|
||||||
this->appendLine(this->generateOpeningString(now));
|
appendLine(this->fileHandle, generateOpeningString(now));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggingChannel::addMessage(MessagePtr message)
|
void LoggingChannel::openStreamLogFile(const QString &streamID)
|
||||||
|
{
|
||||||
|
QDateTime now = QDateTime::currentDateTime();
|
||||||
|
this->currentStreamID = streamID;
|
||||||
|
|
||||||
|
if (this->currentStreamFileHandle.isOpen())
|
||||||
|
{
|
||||||
|
this->currentStreamFileHandle.flush();
|
||||||
|
this->currentStreamFileHandle.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString baseFileName = this->channelName + "-" + streamID + ".log";
|
||||||
|
|
||||||
|
QString directory =
|
||||||
|
this->baseDirectory + QDir::separator() + this->subDirectory;
|
||||||
|
|
||||||
|
if (!QDir().mkpath(directory))
|
||||||
|
{
|
||||||
|
qCDebug(chatterinoHelper) << "Unable to create logging path";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fileName = directory + QDir::separator() + baseFileName;
|
||||||
|
qCDebug(chatterinoHelper) << "Logging stream to" << fileName;
|
||||||
|
this->currentStreamFileHandle.setFileName(fileName);
|
||||||
|
|
||||||
|
this->currentStreamFileHandle.open(QIODevice::Append);
|
||||||
|
appendLine(this->currentStreamFileHandle, generateOpeningString(now));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoggingChannel::addMessage(const MessagePtr &message,
|
||||||
|
const QString &streamID)
|
||||||
{
|
{
|
||||||
QDateTime now = QDateTime::currentDateTime();
|
QDateTime now = QDateTime::currentDateTime();
|
||||||
|
|
||||||
QString messageDateString = this->generateDateString(now);
|
QString messageDateString = generateDateString(now);
|
||||||
if (messageDateString != this->dateString)
|
if (messageDateString != this->dateString)
|
||||||
{
|
{
|
||||||
this->dateString = messageDateString;
|
this->dateString = messageDateString;
|
||||||
|
@ -154,42 +228,19 @@ void LoggingChannel::addMessage(MessagePtr message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str.append(messageText);
|
str.append(messageText);
|
||||||
str.append(endline);
|
str.append(ENDLINE);
|
||||||
|
|
||||||
this->appendLine(str);
|
appendLine(this->fileHandle, str);
|
||||||
}
|
|
||||||
|
|
||||||
QString LoggingChannel::generateOpeningString(const QDateTime &now) const
|
if (!streamID.isEmpty() && getSettings()->separatelyStoreStreamLogs)
|
||||||
{
|
{
|
||||||
QString ret("# Start logging at ");
|
if (this->currentStreamID != streamID)
|
||||||
|
{
|
||||||
|
this->openStreamLogFile(streamID);
|
||||||
|
}
|
||||||
|
|
||||||
ret.append(now.toString("yyyy-MM-dd HH:mm:ss "));
|
appendLine(this->currentStreamFileHandle, str);
|
||||||
ret.append(now.timeZoneAbbreviation());
|
}
|
||||||
ret.append(endline);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString LoggingChannel::generateClosingString(const QDateTime &now) const
|
|
||||||
{
|
|
||||||
QString ret("# Stop logging at ");
|
|
||||||
|
|
||||||
ret.append(now.toString("yyyy-MM-dd HH:mm:ss"));
|
|
||||||
ret.append(now.timeZoneAbbreviation());
|
|
||||||
ret.append(endline);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggingChannel::appendLine(const QString &line)
|
|
||||||
{
|
|
||||||
this->fileHandle.write(line.toUtf8());
|
|
||||||
this->fileHandle.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString LoggingChannel::generateDateString(const QDateTime &now)
|
|
||||||
{
|
|
||||||
return now.toString("yyyy-MM-dd");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
@ -14,8 +13,7 @@ using MessagePtr = std::shared_ptr<const Message>;
|
||||||
|
|
||||||
class LoggingChannel
|
class LoggingChannel
|
||||||
{
|
{
|
||||||
explicit LoggingChannel(const QString &_channelName,
|
explicit LoggingChannel(QString _channelName, QString _platform);
|
||||||
const QString &platform);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~LoggingChannel();
|
~LoggingChannel();
|
||||||
|
@ -26,19 +24,11 @@ public:
|
||||||
LoggingChannel(LoggingChannel &&) = delete;
|
LoggingChannel(LoggingChannel &&) = delete;
|
||||||
LoggingChannel &operator=(LoggingChannel &&) = delete;
|
LoggingChannel &operator=(LoggingChannel &&) = delete;
|
||||||
|
|
||||||
void addMessage(MessagePtr message);
|
void addMessage(const MessagePtr &message, const QString &streamID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void openLogFile();
|
void openLogFile();
|
||||||
|
void openStreamLogFile(const QString &streamID);
|
||||||
QString generateOpeningString(
|
|
||||||
const QDateTime &now = QDateTime::currentDateTime()) const;
|
|
||||||
QString generateClosingString(
|
|
||||||
const QDateTime &now = QDateTime::currentDateTime()) const;
|
|
||||||
|
|
||||||
void appendLine(const QString &line);
|
|
||||||
|
|
||||||
QString generateDateString(const QDateTime &now);
|
|
||||||
|
|
||||||
const QString channelName;
|
const QString channelName;
|
||||||
const QString platform;
|
const QString platform;
|
||||||
|
@ -46,6 +36,8 @@ private:
|
||||||
QString subDirectory;
|
QString subDirectory;
|
||||||
|
|
||||||
QFile fileHandle;
|
QFile fileHandle;
|
||||||
|
QFile currentStreamFileHandle;
|
||||||
|
QString currentStreamID;
|
||||||
|
|
||||||
QString dateString;
|
QString dateString;
|
||||||
|
|
||||||
|
|
|
@ -157,11 +157,21 @@ ModerationPage::ModerationPage()
|
||||||
onlyLogListedChannels->setEnabled(getSettings()->enableLogging);
|
onlyLogListedChannels->setEnabled(getSettings()->enableLogging);
|
||||||
logs.append(onlyLogListedChannels);
|
logs.append(onlyLogListedChannels);
|
||||||
|
|
||||||
|
auto *separatelyStoreStreamLogs =
|
||||||
|
this->createCheckBox("Store live stream logs as separate files",
|
||||||
|
getSettings()->separatelyStoreStreamLogs);
|
||||||
|
|
||||||
|
separatelyStoreStreamLogs->setEnabled(getSettings()->enableLogging);
|
||||||
|
logs.append(separatelyStoreStreamLogs);
|
||||||
|
|
||||||
// Select event
|
// Select event
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
enableLogging, &QCheckBox::stateChanged, this,
|
enableLogging, &QCheckBox::stateChanged, this,
|
||||||
[enableLogging, onlyLogListedChannels]() mutable {
|
[enableLogging, onlyLogListedChannels,
|
||||||
|
separatelyStoreStreamLogs]() mutable {
|
||||||
onlyLogListedChannels->setEnabled(enableLogging->isChecked());
|
onlyLogListedChannels->setEnabled(enableLogging->isChecked());
|
||||||
|
separatelyStoreStreamLogs->setEnabled(
|
||||||
|
getSettings()->enableLogging);
|
||||||
});
|
});
|
||||||
|
|
||||||
EditableModelView *view =
|
EditableModelView *view =
|
||||||
|
|
Loading…
Reference in a new issue