Skip to content

Commit

Permalink
Merge pull request #1208 from geode-sdk/log-levels
Browse files Browse the repository at this point in the history
Log levels
  • Loading branch information
Fleeym authored Jan 13, 2025
2 parents 5f64d77 + 9e81be5 commit 9219a2b
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 36 deletions.
15 changes: 15 additions & 0 deletions loader/resources/mod.json.in
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,21 @@
],
"requires-restart": true
},
"console-log-level": {
"type": "string",
"default": "info",
"name": "Console Log Level",
"description": "Sets the log level for the <cb>platform console</c>.",
"platforms": ["win", "mac"],
"one-of": ["debug", "info", "warn", "error"]
},
"file-log-level": {
"type": "string",
"default": "info",
"name": "File Log Level",
"description": "Sets the log level for the <cb>log files</c>.",
"one-of": ["debug", "info", "warn", "error"]
},
"server-cache-size-limit": {
"type": "int",
"default": 20,
Expand Down
5 changes: 4 additions & 1 deletion loader/src/load.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ bool safeModeCheck() {
int geodeEntry(void* platformData) {
thread::setName("Main");

log::Logger::get()->setup();
console::setup();
if (LoaderImpl::get()->isForwardCompatMode()) {
console::openIfClosed();
Expand Down Expand Up @@ -152,6 +151,10 @@ int geodeEntry(void* platformData) {
}
}

// Setup logger here so that internal mod is setup and we can read log level
// Logging before this point does store the log, and everything gets logged in this setup call
log::Logger::get()->setup();

tryShowForwardCompat();

// open console
Expand Down
56 changes: 28 additions & 28 deletions loader/src/loader/LoaderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,28 +80,28 @@ Result<> Loader::Impl::setup() {
}

if (this->supportsLaunchArguments()) {
log::debug("Loading launch arguments");
log::info("Loading launch arguments");
log::NestScope nest;
this->initLaunchArguments();
}

// on some platforms, using the crash handler overrides more convenient native handlers
if (!this->getLaunchFlag("disable-crash-handler")) {
log::debug("Setting up crash handler");
log::info("Setting up crash handler");
log::NestScope nest;
if (!crashlog::setupPlatformHandler()) {
log::debug("Failed to set up crash handler");
}
} else {
log::debug("Crash handler setup skipped");
log::info("Crash handler setup skipped");
}

log::debug("Loading hooks");
log::info("Loading hooks");
if (log::NestScope nest; !this->loadHooks()) {
return Err("There were errors loading some hooks, see console for details");
}

log::debug("Setting up directories");
log::info("Setting up directories");
{
log::NestScope nest;
this->createDirectories();
Expand All @@ -112,6 +112,7 @@ Result<> Loader::Impl::setup() {
// this function is already on the gd thread, so this should be fine
ModStateEvent(Mod::get(), ModEventType::Loaded).post();

log::info("Refreshing mod graph");
this->refreshModGraph();

m_isSetup = true;
Expand Down Expand Up @@ -405,18 +406,18 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
}

if (node->hasUnresolvedDependencies()) {
log::debug("{} {} has unresolved dependencies", node->getID(), node->getVersion());
log::warn("{} {} has unresolved dependencies", node->getID(), node->getVersion());
return;
}
if (node->hasUnresolvedIncompatibilities()) {
log::debug("{} {} has unresolved incompatibilities", node->getID(), node->getVersion());
log::warn("{} {} has unresolved incompatibilities", node->getID(), node->getVersion());
return;
}

log::NestScope nest;

if (node->isEnabled()) {
log::warn("Mod {} already loaded, this should never happen", node->getID());
log::error("Mod {} already loaded, this should never happen", node->getID());
return;
}

Expand All @@ -426,16 +427,14 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
m_lateRefreshedModCount += early ? 0 : 1;

auto unzipFunction = [this, node]() {
log::debug("Unzip");
log::NestScope nest;
log::debug("Unzipping .geode file");
auto res = node->m_impl->unzipGeodeFile(node->getMetadata());
return res;
};

auto loadFunction = [this, node, early]() {
if (node->shouldLoad()) {
log::debug("Load");
log::NestScope nest;
log::debug("Loading binary");
auto res = node->m_impl->loadBinary();
if (!res) {
this->addProblem({
Expand Down Expand Up @@ -513,7 +512,7 @@ void Loader::Impl::findProblems() {
continue;
}
if (mod->targetsOutdatedVersion()) {
log::debug("{} is outdated", id);
log::warn("{} is outdated", id);
continue;
}
log::debug("{}", id);
Expand All @@ -536,7 +535,7 @@ void Loader::Impl::findProblems() {
log::info("{} suggests {} {}", id, dep.id, dep.version);
}
else {
log::info("{} suggests {} {}, but that suggestion was dismissed", id, dep.id, dep.version);
log::debug("{} suggests {} {}, but that suggestion was dismissed", id, dep.id, dep.version);
}
break;
case ModMetadata::Dependency::Importance::Recommended:
Expand All @@ -546,10 +545,10 @@ void Loader::Impl::findProblems() {
mod,
fmt::format("{} {}", dep.id, dep.version.toString())
});
log::warn("{} recommends {} {}", id, dep.id, dep.version);
log::info("{} recommends {} {}", id, dep.id, dep.version);
}
else {
log::warn("{} recommends {} {}, but that suggestion was dismissed", id, dep.id, dep.version);
log::debug("{} recommends {} {}, but that suggestion was dismissed", id, dep.id, dep.version);
}
break;
case ModMetadata::Dependency::Importance::Required:
Expand Down Expand Up @@ -648,7 +647,6 @@ void Loader::Impl::findProblems() {
}

void Loader::Impl::refreshModGraph() {
log::info("Refreshing mod graph");
log::NestScope nest;

if (m_isSetup) {
Expand All @@ -661,52 +659,54 @@ void Loader::Impl::refreshModGraph() {
m_problems.clear();

m_loadingState = LoadingState::Queue;
log::debug("Queueing mods");
log::info("Queueing mods");
std::vector<ModMetadata> modQueue;
{
log::NestScope nest;
this->queueMods(modQueue);
}

m_loadingState = LoadingState::List;
log::debug("Populating mod list");
log::info("Populating mod list");
{
log::NestScope nest;
this->populateModList(modQueue);
modQueue.clear();
}

m_loadingState = LoadingState::Graph;
log::debug("Building mod graph");
log::info("Building mod graph");
{
log::NestScope nest;
this->buildModGraph();
}

log::debug("Ordering mod stack");
log::info("Ordering mod stack");
{
log::NestScope nest;
this->orderModStack();
}

m_loadingState = LoadingState::EarlyMods;
log::debug("Loading early mods");
log::info("Loading early mods");
{
log::NestScope nest;
while (!m_modsToLoad.empty() && m_modsToLoad.front()->needsEarlyLoad()) {
auto mod = m_modsToLoad.front();
m_modsToLoad.pop_front();
log::info("Loading mod {} {}", mod->getID(), mod->getVersion());
this->loadModGraph(mod, true);
}
}

auto end = std::chrono::high_resolution_clock::now();
auto time = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
log::info("Took {}s. Continuing next frame...", static_cast<float>(time) / 1000.f);
log::debug("Took {}s. Continuing next frame...", static_cast<float>(time) / 1000.f);

m_loadingState = LoadingState::Mods;

queueInMainThread([this]() {
log::info("Loading non-early mods");
this->continueRefreshModGraph();
});
}
Expand Down Expand Up @@ -769,10 +769,10 @@ void Loader::Impl::continueRefreshModGraph() {
if (m_lateRefreshedModCount > 0) {
auto end = std::chrono::high_resolution_clock::now();
auto time = std::chrono::duration_cast<std::chrono::milliseconds>(end - m_timerBegin).count();
log::info("Took {}s", static_cast<float>(time) / 1000.f);
log::debug("Took {}s", static_cast<float>(time) / 1000.f);
}

log::info("Continuing mod graph refresh...");
log::debug("Continuing mod graph refresh...");
log::NestScope nest;

m_timerBegin = std::chrono::high_resolution_clock::now();
Expand All @@ -782,14 +782,14 @@ void Loader::Impl::continueRefreshModGraph() {
if (!m_modsToLoad.empty()) {
auto mod = m_modsToLoad.front();
m_modsToLoad.pop_front();
log::debug("Loading mod {} {}", mod->getID(), mod->getVersion());
log::info("Loading mod {} {}", mod->getID(), mod->getVersion());
this->loadModGraph(mod, false);
break;
}
m_loadingState = LoadingState::Problems;
[[fallthrough]];
case LoadingState::Problems:
log::debug("Finding problems");
log::info("Finding problems");
{
log::NestScope nest;
this->findProblems();
Expand All @@ -798,7 +798,7 @@ void Loader::Impl::continueRefreshModGraph() {
{
auto end = std::chrono::high_resolution_clock::now();
auto time = std::chrono::duration_cast<std::chrono::milliseconds>(end - m_timerBegin).count();
log::info("Took {}s", static_cast<float>(time) / 1000.f);
log::debug("Took {}s", static_cast<float>(time) / 1000.f);
}
break;
default:
Expand Down
64 changes: 62 additions & 2 deletions loader/src/loader/Log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
#include "LogImpl.hpp"

#include <Geode/loader/Dirs.hpp>
#include <Geode/loader/Loader.hpp>
#include <Geode/loader/Log.hpp>
#include <Geode/loader/Mod.hpp>
#include <Geode/loader/Types.hpp>
#include <Geode/utils/casts.hpp>
#include <Geode/utils/general.hpp>
#include <fmt/chrono.h>
Expand Down Expand Up @@ -216,6 +218,10 @@ Logger* Logger::get() {
}

void Logger::setup() {
if (m_initialized) {
return;
}

auto logDir = dirs::getGeodeLogDir();

// on the first launch, this doesn't exist yet..
Expand All @@ -226,6 +232,19 @@ void Logger::setup() {

m_logPath = logDir / log::generateLogName();
m_logStream = std::ofstream(m_logPath);

// Logs can and will probably be added before setup() is called, so we'll write them now
for (Log const& log : m_logs) {
const std::string logStr = log.toString();
if (log.getSeverity() >= this->getConsoleLogLevel()) {
console::log(logStr, log.getSeverity());
}
if (log.getSeverity() >= this->getFileLogLevel()) {
m_logStream << logStr << std::endl;
}
}

m_initialized = true;
}

void Logger::deleteOldLogs(size_t maxAgeHours) {
Expand Down Expand Up @@ -260,16 +279,57 @@ std::mutex& getLogMutex() {
return mutex;
}

Severity Logger::getConsoleLogLevel() {
const std::string level = Mod::get()->getSettingValue<std::string>("console-log-level");
if (level == "debug") {
return Severity::Debug;
} else if (level == "info") {
return Severity::Info;
} else if (level == "warn") {
return Severity::Warning;
} else if (level == "error") {
return Severity::Error;
} else {
return Severity::Info;
}
}

Severity Logger::getFileLogLevel() {
const std::string level = Mod::get()->getSettingValue<std::string>("file-log-level");
if (level == "debug") {
return Severity::Debug;
} else if (level == "info") {
return Severity::Info;
} else if (level == "warn") {
return Severity::Warning;
} else if (level == "error") {
return Severity::Error;
} else {
return Severity::Info;
}
}


void Logger::push(Severity sev, std::string&& thread, std::string&& source, int32_t nestCount,
std::string&& content) {
std::lock_guard g(getLogMutex());

Log& log = m_logs.emplace_back(sev, std::move(thread), std::move(source), nestCount,
std::move(content));

// If logger is not initialized, store the log anyway. When the logger is initialized the pending logs will be logged.
if (!m_initialized) {
return;
}

auto const logStr = log.toString();
console::log(logStr, log.getSeverity());
m_logStream << logStr << std::endl;

if (sev >= this->getConsoleLogLevel()) {
console::log(logStr, log.getSeverity());
}
if (sev >= this->getFileLogLevel()) {
m_logStream << logStr << std::endl;
}
}

Nest::Nest(std::shared_ptr<Nest::Impl> impl) : m_impl(std::move(impl)) { }
Expand Down
4 changes: 4 additions & 0 deletions loader/src/loader/LogImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <Geode/DefaultInclude.hpp>
#include <Geode/loader/Log.hpp>
#include <Geode/loader/Mod.hpp>
#include <Geode/loader/Types.hpp>
#include <vector>
#include <fstream>
#include <string>
Expand All @@ -29,6 +30,7 @@ namespace geode::log {

class Logger {
private:
bool m_initialized = false;
std::vector<Log> m_logs;
std::ofstream m_logStream;
std::filesystem::path m_logPath;
Expand All @@ -43,6 +45,8 @@ namespace geode::log {
std::string&& content);

std::vector<Log> const& list();
Severity getConsoleLogLevel();
Severity getFileLogLevel();
void clear();

std::filesystem::path const& getLogPath() const;
Expand Down
Loading

0 comments on commit 9219a2b

Please sign in to comment.