hyprctl: added --follow option to rolliglog (#6325)
Co-authored-by: Крылов Александр <aleksandr.krylov@hyperus.team>
This commit is contained in:
parent
9cd5b3587c
commit
b2590b58c5
6 changed files with 185 additions and 13 deletions
|
|
@ -28,6 +28,7 @@ using namespace Hyprutils::String;
|
|||
#include "../devices/IKeyboard.hpp"
|
||||
#include "../devices/ITouch.hpp"
|
||||
#include "../devices/Tablet.hpp"
|
||||
#include "debug/RollingLogFollow.hpp"
|
||||
#include "config/ConfigManager.hpp"
|
||||
#include "helpers/MiscFunctions.hpp"
|
||||
|
||||
|
|
@ -1732,6 +1733,46 @@ std::string CHyprCtl::makeDynamicCall(const std::string& input) {
|
|||
return getReply(input);
|
||||
}
|
||||
|
||||
bool successWrite(int fd, const std::string& data, bool needLog = true) {
|
||||
if (write(fd, data.c_str(), data.length()) > 0)
|
||||
return true;
|
||||
|
||||
if (errno == EAGAIN)
|
||||
return true;
|
||||
|
||||
if (needLog)
|
||||
Debug::log(ERR, "Couldn't write to socket. Error: " + std::string(strerror(errno)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void runWritingDebugLogThread(const int conn) {
|
||||
using namespace std::chrono_literals;
|
||||
Debug::log(LOG, "In followlog thread, got connection, start writing: {}", conn);
|
||||
//will be finished, when reading side close connection
|
||||
std::thread([conn]() {
|
||||
while (Debug::RollingLogFollow::Get().IsRunning()) {
|
||||
if (Debug::RollingLogFollow::Get().isEmpty(conn)) {
|
||||
std::this_thread::sleep_for(1000ms);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto line = Debug::RollingLogFollow::Get().GetLog(conn);
|
||||
if (!successWrite(conn, line))
|
||||
// We cannot write, when connection is closed. So thread will successfully exit by itself
|
||||
break;
|
||||
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
close(conn);
|
||||
Debug::RollingLogFollow::Get().StopFor(conn);
|
||||
}).detach();
|
||||
}
|
||||
|
||||
bool isFollowUpRollingLogRequest(const std::string& request) {
|
||||
return request.contains("rollinglog") && request.contains("f");
|
||||
}
|
||||
|
||||
int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
||||
return 0;
|
||||
|
|
@ -1775,9 +1816,15 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
|||
reply = "Err: " + std::string(e.what());
|
||||
}
|
||||
|
||||
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
|
||||
successWrite(ACCEPTEDCONNECTION, reply);
|
||||
|
||||
close(ACCEPTEDCONNECTION);
|
||||
if (isFollowUpRollingLogRequest(request)) {
|
||||
Debug::log(LOG, "Followup rollinglog request received. Starting thread to write to socket.");
|
||||
Debug::RollingLogFollow::Get().StartFor(ACCEPTEDCONNECTION);
|
||||
runWritingDebugLogThread(ACCEPTEDCONNECTION);
|
||||
Debug::log(LOG, Debug::RollingLogFollow::Get().DebugInfo());
|
||||
} else
|
||||
close(ACCEPTEDCONNECTION);
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||
g_pConfigManager->ensureMonitorStatus();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "Log.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "RollingLogFollow.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
|
@ -73,6 +74,9 @@ void Debug::log(LogLevel level, std::string str) {
|
|||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||
|
||||
if (RollingLogFollow::Get().IsRunning())
|
||||
RollingLogFollow::Get().AddLog(str);
|
||||
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
|
|
|
|||
65
src/debug/RollingLogFollow.hpp
Normal file
65
src/debug/RollingLogFollow.hpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace Debug {
|
||||
struct RollingLogFollow {
|
||||
std::unordered_map<int, std::string> socketToRollingLogFollowQueue;
|
||||
std::shared_mutex m;
|
||||
bool running = false;
|
||||
static constexpr size_t ROLLING_LOG_FOLLOW_TOO_BIG = 8192;
|
||||
|
||||
// Returns true if the queue is empty for the given socket
|
||||
bool isEmpty(int socket) {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return socketToRollingLogFollowQueue[socket].empty();
|
||||
}
|
||||
|
||||
std::string DebugInfo() {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return std::format("RollingLogFollow, got {} connections", socketToRollingLogFollowQueue.size());
|
||||
}
|
||||
|
||||
std::string GetLog(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
|
||||
const std::string ret = socketToRollingLogFollowQueue[socket];
|
||||
socketToRollingLogFollowQueue[socket] = "";
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
void AddLog(std::string log) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
running = true;
|
||||
std::vector<int> to_erase;
|
||||
for (const auto& p : socketToRollingLogFollowQueue)
|
||||
socketToRollingLogFollowQueue[p.first] += log + "\n";
|
||||
}
|
||||
|
||||
bool IsRunning() {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return running;
|
||||
}
|
||||
|
||||
void StopFor(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
socketToRollingLogFollowQueue.erase(socket);
|
||||
if (socketToRollingLogFollowQueue.empty())
|
||||
running = false;
|
||||
}
|
||||
|
||||
void StartFor(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
socketToRollingLogFollowQueue[socket] = std::format("[LOG] Following log to socket: {} started\n", socket);
|
||||
running = true;
|
||||
}
|
||||
|
||||
static RollingLogFollow& Get() {
|
||||
static RollingLogFollow instance;
|
||||
static std::mutex gm;
|
||||
std::lock_guard<std::mutex> lock(gm);
|
||||
return instance;
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue