Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions defaults/python/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ async def main():
verbose = False
try:
# ---- Setup early logging to at least print something out
set_logger_settings(None, print_to_std=True)
set_logger_settings(logger, None, print_to_std=True)

# ---- General parser setup [start]
parser = ArgumentParserWithRedirect(
Expand All @@ -446,7 +446,8 @@ async def main():
# -------- Setup logging (as early as possible)
parser_args, _ = parser.parse_known_args()
verbose = parser_args.verbose
set_logger_settings(parser_args.log_file,
set_logger_settings(logger,
parser_args.log_file,
print_to_std=True,
log_preamble=f"Executing: {sys.argv[:]}, CWD: {Path.cwd()}",
verbose=verbose)
Expand Down
1 change: 1 addition & 0 deletions defaults/python/lib/constants.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
BUDDY_API_VERSION = 8
LOG_FILE = "/tmp/moondeck.log"
FRONTEND_LOG_FILE = "/tmp/moondeck-frontend.log"
RUNNER_LOG_FILE = "/tmp/moondeck-runner.log"
MOONLIGHT_LOG_FILE = "/tmp/moondeck-runner-moonlight.log"
RUNNER_RESULT_FILE = "/tmp/moondeck-runner.result"
Expand Down
27 changes: 15 additions & 12 deletions defaults/python/lib/logger.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging

def set_logger_settings(filename: str | None, rotate: bool = True, log_preamble: str | None = None, print_to_std: bool = False, verbose: bool = False):
def set_logger_settings(instance: logging.Logger, filename: str | None, rotate: bool = True, log_preamble: str | None = None, print_to_std: bool = False, verbose: bool = False):
# Lazy import to improve CLI performance
import sys
from pathlib import Path
Expand All @@ -17,13 +17,12 @@ def set_logger_settings(filename: str | None, rotate: bool = True, log_preamble:
)

if log_preamble is not None:
optional_separator = "\n\n" if Path(filename).stat().st_size > 0 else ""
optional_separator = "\n\n" if Path(filename).stat().st_size > 0 and log_preamble != "" else ""

handler.setFormatter(logging.Formatter("%(message)s"))
handler.emit(logging.makeLogRecord({"msg": f"{optional_separator}{log_preamble}"}))

handler.setFormatter(logging.Formatter(
"[%(asctime)s] %(levelname)s: %(message)s"))
handler.setFormatter(logging.Formatter("[%(asctime)s] %(levelname)s: %(message)s"))
handlers.append(handler)

if print_to_std:
Expand All @@ -42,16 +41,20 @@ def set_logger_settings(filename: str | None, rotate: bool = True, log_preamble:
handlers.append(stdout_handler)
handlers.append(stderr_handler)

logging.basicConfig(handlers=handlers,
level=logging.INFO,
force=True)
for h in instance.handlers[:]:
instance.removeHandler(h)
h.close()

if verbose:
enable_debug_level()
for h in handlers:
instance.addHandler(h)

instance.setLevel(logging.DEBUG if verbose else logging.INFO)

def enable_debug_level():
logging.getLogger().setLevel(logging.DEBUG)

def get_logger(name: str | None = None):
logger = logging.getLogger(name)
logger.propagate = False
return logger

logger = logging.getLogger()

logger = get_logger()
7 changes: 4 additions & 3 deletions defaults/python/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,20 @@ def add_plugin_to_path():
# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# autopep8: on

import logging

from lib.buddyrequests import BuddyException
from lib.runner.moondeckapprunner import MoonDeckAppRunner
from lib.runner.moonlightonlyrunner import MoonlightOnlyRunner
from lib.logger import logger, set_logger_settings, enable_debug_level
from lib.logger import logger, set_logger_settings
from lib.utils import is_moondeck_runner_ready
from lib.runner.settingsparser import parse_settings, RunnerType

import lib.constants as constants
import lib.runnerresult as runnerresult


set_logger_settings(constants.RUNNER_LOG_FILE, rotate=False)
set_logger_settings(logger, constants.RUNNER_LOG_FILE, rotate=False)

async def main():
try:
Expand All @@ -39,7 +40,7 @@ async def main():
settings = await parse_settings()

if settings["debug_logs"]:
enable_debug_level()
logger.setLevel(logging.DEBUG)

if settings["runner_type"] == RunnerType.MoonDeck:
await MoonDeckAppRunner.run(settings)
Expand Down
26 changes: 23 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,26 @@ def add_plugin_to_path():


import asyncio
import logging
import pathlib
import lib.gamestreaminfo as gamestreaminfo
import lib.constants as constants
import lib.utils as utils

from typing import Optional
from lib.plugin.settings import UserSettings, UserSettingsManager
from lib.logger import logger, set_logger_settings
from lib.logger import logger, set_logger_settings, get_logger
from lib.buddyrequests import SteamUiMode, SteamUiModeResponse, CurrentUserResponse, BuddyException
from lib.buddyclient import BuddyClient, AbortHostStateChangeResult
from lib.utils import wake_on_lan, change_moondeck_runner_ready_state, TimedPooler
from lib.runnerresult import Result, set_result, get_result
from lib.moonlightproxy import MoonlightProxy

set_logger_settings(logger, constants.LOG_FILE, rotate=True, verbose=True)

frontend_logger = get_logger("frontend")
set_logger_settings(frontend_logger, constants.FRONTEND_LOG_FILE, rotate=True, log_preamble="", verbose=True)

set_logger_settings(constants.LOG_FILE, rotate=True)
settings_manager = UserSettingsManager(constants.get_config_file_path())


Expand All @@ -47,6 +51,12 @@ async def _main(self):
async def _unload(self):
self.__cleanup_states()

async def frontend_log_entry(self, level: str, message: str):
try:
frontend_logger.log(logging._checkLevel(level), message)
except Exception:
logger.exception("Failed to save frontend log")

@utils.async_scope_log(logger.info)
async def set_runner_ready(self):
change_moondeck_runner_ready_state(True)
Expand All @@ -57,11 +67,20 @@ async def get_runner_result(self):
# Cleanup is needed to differentiate between moondeck launches
set_result(None)
return result

def set_log_levels(self, data: UserSettings):
level = logging.DEBUG if data["runnerDebugLogs"] else logging.INFO
for instance in [logger, frontend_logger]:
if instance.level != level:
instance.setLevel(level)
instance.info(f"Set logger log level to {logging.getLevelName(level)}")

@utils.async_scope_log(logger.info)
async def get_user_settings(self):
try:
return await settings_manager.read_or_update()
data = await settings_manager.read_or_update()
self.set_log_levels(data)
return data
except Exception:
logger.exception("Failed to get user settings")
return None
Expand All @@ -70,6 +89,7 @@ async def get_user_settings(self):
async def set_user_settings(self, data: UserSettings):
try:
await settings_manager.write(data)
self.set_log_levels(data)
except Exception:
logger.exception("Failed to set user settings")

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"async-mutex": "^0.5.0",
"ip-regex": "^5.0.0",
"lodash": "^4.17.21",
"loupe": "^3.2.1",
"mobx": "^6.15.0",
"promise-throttle-all": "^1.1.1",
"react-icons": "^5.5.0",
Expand Down
11 changes: 10 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions src/lib/executeasync.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { logger } from "./logger";

type AsyncCallback = () => Promise<void>;
type VoidPromise = Promise<void>;
type AsyncCallback = () => VoidPromise;

export function executeAsyncWrapper(callback: AsyncCallback) {
export function executeAsyncWrapper(input: AsyncCallback | VoidPromise) {
return () => {
Promise.resolve()
.then(async () => {
await callback();
if (typeof input === "function") {
await input();
} else {
await input;
}
})
.catch((e) => logger.critical(e));
};
}

export function executeAsync(callback: AsyncCallback) {
executeAsyncWrapper(callback)();
export function executeAsync(input: AsyncCallback | VoidPromise) {
executeAsyncWrapper(input)();
}
41 changes: 34 additions & 7 deletions src/lib/logger.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,31 @@
import { toaster } from "@decky/api";
import { call, toaster } from "@decky/api";
import { inspect } from "loupe";

function serialize(...args: unknown[]) {
return args.map((arg) => typeof arg === "string" ? arg : inspect(arg)).join(" ");
}

function criticalConsoleLog(...args: unknown[]) {
console.error(
"%c MoonDeck %c Critical:",
"background: #16a085; color: black;",
"background: transparent;",
...args
);
}

function executeAsyncSafe(input: Promise<void>) {
Promise.resolve(input).catch((e) => criticalConsoleLog(e));
}

type PythonLogLevel = "DEBUG" | "INFO" | "WARNING" | "ERROR" | "CRITICAL";
async function frontendLogEntry(level: PythonLogLevel, ...args: unknown[]): Promise<void> {
try {
await call<[PythonLogLevel, string], unknown>("frontend_log_entry", level, serialize(...args));
} catch (message) {
criticalConsoleLog("Error while trying to save frontend log: ", message);
}
}

class Logger {
toast(entry: string, options: { duration?: number; output?: "debug" | "log" | "warn" | "error" | null } = {}): void {
Expand Down Expand Up @@ -32,6 +59,7 @@ class Logger {
"background: transparent;",
...args
);
executeAsyncSafe(frontendLogEntry("DEBUG", ...args));
}

log(...args: unknown[]): void {
Expand All @@ -42,6 +70,7 @@ class Logger {
"background: transparent;",
...args
);
executeAsyncSafe(frontendLogEntry("INFO", ...args));
}

warn(...args: unknown[]): void {
Expand All @@ -52,6 +81,7 @@ class Logger {
"background: transparent;",
...args
);
executeAsyncSafe(frontendLogEntry("WARNING", ...args));
}

error(...args: unknown[]): void {
Expand All @@ -62,15 +92,12 @@ class Logger {
"background: transparent;",
...args
);
executeAsyncSafe(frontendLogEntry("ERROR", ...args));
}

critical(...args: unknown[]): void {
console.error(
"%c MoonDeck %c Critical:",
"background: #16a085; color: black;",
"background: transparent;",
...args
);
criticalConsoleLog(...args);
executeAsyncSafe(frontendLogEntry("CRITICAL", ...args));
}
}

Expand Down