diff --git a/.gitignore b/.gitignore index 4969e3e4..64a08345 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ node_modules #internal/native/lib ui/reports + +# compiled remote-agent test binary +e2e/remote-agent/remote-agent diff --git a/config.go b/config.go index 75a9ed44..4a9eafa2 100644 --- a/config.go +++ b/config.go @@ -291,11 +291,6 @@ func LoadConfig() { loadedConfig.KeyboardLayout = "en-US" } - // Migrate old verbose log level to sensible default - if loadedConfig.DefaultLogLevel == "INFO" { - loadedConfig.DefaultLogLevel = "WARN" - } - // Migrate old default EDID (Toshiba TSB, no CEA extension) to new JetKVM v1 EDID const oldDefaultEDID = "00ffffffffffff0052620188008888881c150103800000780a0dc9a05747982712484c00000001010101010101010101010101010101023a801871382d40582c4500c48e2100001e011d007251d01e206e285500c48e2100001e000000fc00543734392d6648443732300a20000000fd00147801ff1d000a202020202020017b" if loadedConfig.EdidString == "" || loadedConfig.EdidString == oldDefaultEDID { diff --git a/internal/logging/logger.go b/internal/logging/logger.go index 4a75300b..139d49e7 100644 --- a/internal/logging/logger.go +++ b/internal/logging/logger.go @@ -188,14 +188,13 @@ func (l *Logger) UpdateLogLevel(configDefaultLogLevel string) { if configDefaultLogLevel != "" { if logLevel, ok := zerologLevels[configDefaultLogLevel]; ok { + if l.defaultLogLevelFromConfig != logLevel { + needUpdate = true + } l.defaultLogLevelFromConfig = logLevel } else { l.l.Warn().Str("logLevel", configDefaultLogLevel).Msg("invalid defaultLogLevel from config, using ERROR") } - - if l.defaultLogLevelFromConfig != l.defaultLogLevel { - needUpdate = true - } } l.updateLogLevel() diff --git a/internal/usbgadget/changeset_resolver.go b/internal/usbgadget/changeset_resolver.go index 67812e0d..7dc295ce 100644 --- a/internal/usbgadget/changeset_resolver.go +++ b/internal/usbgadget/changeset_resolver.go @@ -129,7 +129,7 @@ func (c *ChangeSetResolver) applyChanges() error { err := c.changeset.applyChange(change) if err != nil { if change.IgnoreErrors { - c.l.Warn().Str("change", change.String()).Err(err).Msg("ignoring error") + c.l.Debug().Str("change", change.String()).Err(err).Msg("ignoring error") } else { return err } diff --git a/jsonrpc.go b/jsonrpc.go index aeae20bf..4b9376be 100644 --- a/jsonrpc.go +++ b/jsonrpc.go @@ -17,6 +17,7 @@ import ( "github.com/rs/zerolog" "github.com/jetkvm/kvm/internal/hidrpc" + "github.com/jetkvm/kvm/internal/logging" "github.com/jetkvm/kvm/internal/usbgadget" "github.com/jetkvm/kvm/internal/utils" ) @@ -1086,6 +1087,62 @@ func rpcSetLocalLoopbackOnly(enabled bool) error { return nil } +var validLogLevels = map[string]bool{ + "TRACE": true, + "DEBUG": true, + "INFO": true, + "WARN": true, + "ERROR": true, +} + +const testLogProbeMessage = "JSON-RPC test log probe" + +func rpcGetDefaultLogLevel() (string, error) { + return config.DefaultLogLevel, nil +} + +func rpcSetDefaultLogLevel(level string) error { + if !validLogLevels[level] { + return fmt.Errorf("invalid log level: %s", level) + } + + if config.DefaultLogLevel == level { + return nil + } + + config.DefaultLogLevel = level + if err := SaveConfig(); err != nil { + return fmt.Errorf("failed to save config: %w", err) + } + + logging.GetRootLogger().UpdateLogLevel(level) + + return nil +} + +func rpcEmitTestLog(level string) error { + if !validLogLevels[level] { + return fmt.Errorf("invalid log level: %s", level) + } + + testLogger := logging.GetSubsystemLogger("testlog") + + switch level { + case "TRACE": + testLogger.Trace().Msg(testLogProbeMessage) + case "DEBUG": + testLogger.Debug().Msg(testLogProbeMessage) + case "INFO": + testLogger.Info().Msg(testLogProbeMessage) + case "WARN": + testLogger.Warn().Msg(testLogProbeMessage) + case "ERROR": + testLogger.Error().Msg(testLogProbeMessage) + } + + return nil +} + var ( keyboardMacroCancel context.CancelFunc keyboardMacroLock sync.Mutex @@ -1281,6 +1338,9 @@ var rpcHandlers = map[string]RPCHandler{ "setKeyboardMacros": {Func: setKeyboardMacros, Params: []string{"params"}}, "getLocalLoopbackOnly": {Func: rpcGetLocalLoopbackOnly}, "setLocalLoopbackOnly": {Func: rpcSetLocalLoopbackOnly, Params: []string{"enabled"}}, + "getDefaultLogLevel": {Func: rpcGetDefaultLogLevel}, + "setDefaultLogLevel": {Func: rpcSetDefaultLogLevel, Params: []string{"level"}}, + "emitTestLog": {Func: rpcEmitTestLog, Params: []string{"level"}}, "getPublicIPAddresses": {Func: rpcGetPublicIPAddresses, Params: []string{"refresh"}}, "checkPublicIPAddresses": {Func: rpcCheckPublicIPAddresses}, "getTailscaleStatus": {Func: rpcGetTailscaleStatus}, diff --git a/ui/.gitignore b/ui/.gitignore index 720a9ef8..5dd6617a 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +/screenshot.png diff --git a/ui/.oxlintrc.json b/ui/.oxlintrc.json index 5c61d962..750eaf13 100644 --- a/ui/.oxlintrc.json +++ b/ui/.oxlintrc.json @@ -9,7 +9,7 @@ }, "rules": { "typescript/no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }], - "typescript/no-floating-promises": "warn", + "typescript/no-floating-promises": "off", "typescript/restrict-template-expressions": "warn", "typescript/no-base-to-string": "warn", "import/order": [ diff --git a/ui/e2e/log-level.spec.ts b/ui/e2e/log-level.spec.ts new file mode 100644 index 00000000..8eb050f2 --- /dev/null +++ b/ui/e2e/log-level.spec.ts @@ -0,0 +1,85 @@ +import { test, expect } from "@playwright/test"; + +import { + ensureLocalAuthMode, + waitForWebRTCReady, + dismissSessionTakeoverDialog, + callJsonRpc, + sshExec, +} from "./helpers"; + +const DEVICE_LAST_LOG_PATH = "/userdata/jetkvm/last.log"; +const TEST_LOG_PATTERN = "JSON-RPC test log probe"; +const LOG_LEVELS = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR"] as const; +type LogLevel = (typeof LOG_LEVELS)[number]; + +function shellEscapeDoubleQuotes(value: string): string { + return value.replace(/["\\$`]/g, "\\$&"); +} + +async function clearDeviceLog(): Promise { + await sshExec(`: > ${DEVICE_LAST_LOG_PATH}`, true); +} + +async function countDeviceLogMatches(pattern: string): Promise { + const escapedPattern = shellEscapeDoubleQuotes(pattern); + const output = await sshExec( + `sh -lc "grep -F -c -- \\"${escapedPattern}\\" ${DEVICE_LAST_LOG_PATH} 2>/dev/null || true"`, + true, + ); + return Number.parseInt(output.trim() || "0", 10); +} + +async function emitTestLog( + page: Parameters[0] extends never ? never : any, + level: LogLevel, +): Promise { + await callJsonRpc(page, "emitTestLog", { level }); +} + +test.describe("Log level filtering", () => { + test.setTimeout(45_000); + + test("live changes filter TRACE/DEBUG/INFO/WARN/ERROR logs without restart", async ({ page }) => { + await page.goto("/"); + await page.waitForLoadState("networkidle"); + await ensureLocalAuthMode(page, { mode: "noPassword" }); + await dismissSessionTakeoverDialog(page); + await waitForWebRTCReady(page); + + const originalLevel = (await callJsonRpc(page, "getDefaultLogLevel")) as LogLevel; + + try { + for (const [index, level] of LOG_LEVELS.entries()) { + await clearDeviceLog(); + await callJsonRpc(page, "setDefaultLogLevel", { level }); + await page.waitForTimeout(250); + await emitTestLog(page, level); + + await expect + .poll(() => countDeviceLogMatches(TEST_LOG_PATTERN), { + message: `Waiting for ${level} probe log to be written`, + timeout: 5_000, + intervals: [200, 500, 1000], + }) + .toBe(1); + + const moreVerboseLevel = LOG_LEVELS[index - 1]; + if (!moreVerboseLevel) continue; + + await clearDeviceLog(); + await callJsonRpc(page, "setDefaultLogLevel", { level }); + await page.waitForTimeout(250); + await emitTestLog(page, moreVerboseLevel); + await page.waitForTimeout(1_000); + + expect( + await countDeviceLogMatches(TEST_LOG_PATTERN), + `${moreVerboseLevel} log should be suppressed when default log level is ${level}`, + ).toBe(0); + } + } finally { + await callJsonRpc(page, "setDefaultLogLevel", { level: originalLevel }).catch(() => {}); + } + }); +}); diff --git a/ui/localization/messages/cy.json b/ui/localization/messages/cy.json index c32e87b5..df7f93b1 100644 --- a/ui/localization/messages/cy.json +++ b/ui/localization/messages/cy.json @@ -76,6 +76,7 @@ "advanced_error_loopback_enable": "Methwyd galluogi modd loopback yn unig: {error}", "advanced_error_set_dev_channel": "Methwyd gosod cyflwr sianel ddatblygu: {error}", "advanced_error_set_dev_mode": "Methwyd gosod modd datblygwr: {error}", + "advanced_error_set_log_level": "Methwyd gosod lefel log: {error}", "advanced_error_update_ssh_key": "Methwyd diweddaru allwedd SSH: {error}", "advanced_error_usb_emulation_disable": "Methwyd analluogi efelychu USB: {error}", "advanced_error_usb_emulation_enable": "Methwyd galluogi efelychu USB: {error}", @@ -88,6 +89,11 @@ "advanced_factory_reset_error": "Methwyd ag ailosod i osodiadau ffatri: {error}", "advanced_factory_reset_success": "Cychwynnwyd ailosodiad ffatri. Bydd y ddyfais yn ailgychwyn yn fuan.", "advanced_factory_reset_title": "Ailosodiad Ffatri", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Gwall", + "advanced_log_level_info": "Gwybodaeth", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Rhybudd", "advanced_loopback_only_description": "Cyfyngu mynediad rhyngwyneb gwe i localhost yn unig (127.0.0.1)", "advanced_loopback_only_title": "Modd Loopback yn Unig", "advanced_loopback_warning_before": "Cyn galluogi'r nodwedd hon, sicrhewch fod gennych naill ai:", @@ -107,6 +113,8 @@ "advanced_success_loopback_enabled": "Modd loopback yn unig wedi'i alluogi. Ailgychwynnwch eich dyfais i'w gymhwyso.", "advanced_success_update_ssh_key": "Allwedd SSH wedi'i diweddaru'n llwyddiannus", "advanced_title": "Uwch", + "advanced_troubleshooting_log_level_description": "Addaswch fanylion log ar gyfer diagnosteg. Gall lefelau uwch effeithio ar berfformiad", + "advanced_troubleshooting_log_level_title": "Lefel log", "advanced_troubleshooting_mode_description": "Offer diagnostig a rheolaethau ychwanegol ar gyfer datrys problemau a dibenion datblygu", "advanced_troubleshooting_mode_title": "Modd Datrys Problemau", "advanced_update_ssh_key_button": "Diweddaru Allwedd SSH", diff --git a/ui/localization/messages/da.json b/ui/localization/messages/da.json index f9253863..5c472cb8 100644 --- a/ui/localization/messages/da.json +++ b/ui/localization/messages/da.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Konfigurationen kunne ikke nulstilles: {error}", "advanced_error_set_dev_channel": "Kunne ikke indstille udviklerkanaltilstand: {error}", "advanced_error_set_dev_mode": "Kunne ikke indstille udviklertilstand: {error}", + "advanced_error_set_log_level": "Kunne ikke indstille logniveau: {error}", "advanced_error_update_ssh_key": "Kunne ikke opdatere SSH-nøglen: {error}", "advanced_error_usb_emulation_disable": "Kunne ikke deaktivere USB-emulering: {error}", "advanced_error_usb_emulation_enable": "Kunne ikke aktivere USB-emulering: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Fabriksnulstilling mislykkedes: {error}", "advanced_factory_reset_success": "Fabriksnulstilling startet. Enheden genstarter om kort tid.", "advanced_factory_reset_title": "Fabriksnulstilling", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Fejl", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Advarsel", "advanced_loopback_only_description": "Begræns webgrænsefladeadgang kun til localhost (127.0.0.1)", "advanced_loopback_only_title": "Kun loopback-tilstand", "advanced_loopback_warning_before": "Før du aktiverer denne funktion, skal du sikre dig, at du har enten:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "Konfigurationen er nulstillet til standard", "advanced_success_update_ssh_key": "SSH-nøglen er blevet opdateret", "advanced_title": "Avanceret", + "advanced_troubleshooting_log_level_description": "Juster logdetaljer til fejlsøgning. Højere niveauer kan påvirke ydeevnen", + "advanced_troubleshooting_log_level_title": "Logniveau", "advanced_troubleshooting_mode_description": "Diagnostiske værktøjer og yderligere kontroller til fejlfinding og udviklingsformål", "advanced_troubleshooting_mode_title": "Fejlfindingstilstand", "advanced_update_ssh_key_button": "Opdater SSH-nøgle", diff --git a/ui/localization/messages/de.json b/ui/localization/messages/de.json index bd26f37b..386f149c 100644 --- a/ui/localization/messages/de.json +++ b/ui/localization/messages/de.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Konfiguration konnte nicht zurückgesetzt werden: {error}", "advanced_error_set_dev_channel": "Der Dev-Kanalstatus konnte nicht festgelegt werden: {error}", "advanced_error_set_dev_mode": "Fehler beim Festlegen des Entwicklungsmodus: {error}", + "advanced_error_set_log_level": "Fehler beim Festlegen der Protokollebene: {error}", "advanced_error_update_ssh_key": "SSH-Schlüssel konnte nicht aktualisiert werden: {error}", "advanced_error_usb_emulation_disable": "USB-Emulation konnte nicht deaktiviert werden: {error}", "advanced_error_usb_emulation_enable": "USB-Emulation konnte nicht aktiviert werden: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Werksreset fehlgeschlagen: {error}", "advanced_factory_reset_success": "Werksreset eingeleitet. Das Gerät wird in Kürze neu gestartet.", "advanced_factory_reset_title": "Werksreset", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Fehler", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Warnung", "advanced_loopback_only_description": "Beschränken Sie den Zugriff auf die Weboberfläche nur auf den lokalen Host (127.0.0.1).", "advanced_loopback_only_title": "Nur-Loopback-Modus", "advanced_loopback_warning_before": "Bevor Sie diese Funktion aktivieren, stellen Sie sicher, dass Sie über Folgendes verfügen:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "Konfiguration erfolgreich auf Standard zurückgesetzt", "advanced_success_update_ssh_key": "SSH-Schlüssel erfolgreich aktualisiert", "advanced_title": "Erweitert", + "advanced_troubleshooting_log_level_description": "Protokolldetails für die Diagnose anpassen. Höhere Stufen können die Leistung beeinträchtigen", + "advanced_troubleshooting_log_level_title": "Protokollebene", "advanced_troubleshooting_mode_description": "Diagnosetools und zusätzliche Steuerelemente für Fehlerbehebungs- und Entwicklungszwecke", "advanced_troubleshooting_mode_title": "Fehlerbehebungsmodus", "advanced_update_ssh_key_button": "SSH-Schlüssel aktualisieren", diff --git a/ui/localization/messages/en.json b/ui/localization/messages/en.json index 93004e07..5088c245 100644 --- a/ui/localization/messages/en.json +++ b/ui/localization/messages/en.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Failed to reset configuration: {error}", "advanced_error_set_dev_channel": "Failed to set dev channel state: {error}", "advanced_error_set_dev_mode": "Failed to set dev mode: {error}", + "advanced_error_set_log_level": "Failed to set log level: {error}", "advanced_error_update_ssh_key": "Failed to update SSH key: {error}", "advanced_error_usb_emulation_disable": "Failed to disable USB emulation: {error}", "advanced_error_usb_emulation_enable": "Failed to enable USB emulation: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Factory reset failed: {error}", "advanced_factory_reset_success": "Factory reset initiated. The device will reboot shortly.", "advanced_factory_reset_title": "Factory Reset", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Error", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Warning", "advanced_loopback_only_description": "Restrict web interface access to localhost only (127.0.0.1)", "advanced_loopback_only_title": "Loopback-Only Mode", "advanced_loopback_warning_before": "Before enabling this feature, make sure you have either:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "Configuration reset to default successfully", "advanced_success_update_ssh_key": "SSH key updated successfully", "advanced_title": "Advanced", + "advanced_troubleshooting_log_level_description": "Adjust log detail for diagnostics. Higher levels may impact performance", + "advanced_troubleshooting_log_level_title": "Log Level", "advanced_troubleshooting_mode_description": "Diagnostic tools and additional controls for troubleshooting and development purposes", "advanced_troubleshooting_mode_title": "Troubleshooting Mode", "advanced_update_ssh_key_button": "Update SSH Key", diff --git a/ui/localization/messages/es.json b/ui/localization/messages/es.json index f75093b0..ae43a5a9 100644 --- a/ui/localization/messages/es.json +++ b/ui/localization/messages/es.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "No se pudo restablecer la configuración: {error}", "advanced_error_set_dev_channel": "No se pudo establecer el estado del canal de desarrollo: {error}", "advanced_error_set_dev_mode": "No se pudo establecer el modo de desarrollo: {error}", + "advanced_error_set_log_level": "No se pudo establecer el nivel de registro: {error}", "advanced_error_update_ssh_key": "No se pudo actualizar la clave SSH: {error}", "advanced_error_usb_emulation_disable": "No se pudo deshabilitar la emulación USB: {error}", "advanced_error_usb_emulation_enable": "No se pudo habilitar la emulación USB: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "El restablecimiento de fábrica falló: {error}", "advanced_factory_reset_success": "Restablecimiento de fábrica iniciado. El dispositivo se reiniciará en breve.", "advanced_factory_reset_title": "Restablecimiento de fábrica", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Error", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Advertencia", "advanced_loopback_only_description": "Restringir el acceso a la interfaz web solo al host local (127.0.0.1)", "advanced_loopback_only_title": "Modo de solo bucle invertido", "advanced_loopback_warning_before": "Antes de habilitar esta función, asegúrese de tener:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "La configuración se restableció a los valores predeterminados correctamente", "advanced_success_update_ssh_key": "Clave SSH actualizada exitosamente", "advanced_title": "Avanzado", + "advanced_troubleshooting_log_level_description": "Ajuste el detalle del registro para diagnósticos. Los niveles altos pueden afectar el rendimiento", + "advanced_troubleshooting_log_level_title": "Nivel de registro", "advanced_troubleshooting_mode_description": "Herramientas de diagnóstico y controles adicionales para resolución de problemas y fines de desarrollo", "advanced_troubleshooting_mode_title": "Modo de solución de problemas", "advanced_update_ssh_key_button": "Actualizar clave SSH", diff --git a/ui/localization/messages/fr.json b/ui/localization/messages/fr.json index 0893d342..d06827fe 100644 --- a/ui/localization/messages/fr.json +++ b/ui/localization/messages/fr.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Échec de la réinitialisation de la configuration : {error}", "advanced_error_set_dev_channel": "Échec de la définition de l'état du canal de développement : {error}", "advanced_error_set_dev_mode": "Échec de la définition du mode de développement : {error}", + "advanced_error_set_log_level": "Échec de la définition du niveau de journalisation : {error}", "advanced_error_update_ssh_key": "Échec de la mise à jour de la clé SSH : {error}", "advanced_error_usb_emulation_disable": "Échec de la désactivation de l'émulation USB : {error}", "advanced_error_usb_emulation_enable": "Échec de l'activation de l'émulation USB : {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Échec de la réinitialisation d'usine : {error}", "advanced_factory_reset_success": "Réinitialisation d'usine lancée. L'appareil redémarrera sous peu.", "advanced_factory_reset_title": "Réinitialisation d'usine", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Erreur", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Avertissement", "advanced_loopback_only_description": "Restreindre l'accès à l'interface Web à l'hôte local uniquement (127.0.0.1)", "advanced_loopback_only_title": "Mode de bouclage uniquement", "advanced_loopback_warning_before": "Avant d'activer cette fonctionnalité, assurez-vous d'avoir :", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "La configuration par défaut a été réinitialisée avec succès", "advanced_success_update_ssh_key": "Clé SSH mise à jour avec succès", "advanced_title": "Avancé", + "advanced_troubleshooting_log_level_description": "Ajustez le détail des journaux pour le diagnostic. Les niveaux élevés peuvent affecter les performances", + "advanced_troubleshooting_log_level_title": "Niveau de journalisation", "advanced_troubleshooting_mode_description": "Outils de diagnostic et contrôles supplémentaires à des fins de dépannage et de développement", "advanced_troubleshooting_mode_title": "Mode de dépannage", "advanced_update_ssh_key_button": "Mettre à jour la clé SSH", diff --git a/ui/localization/messages/it.json b/ui/localization/messages/it.json index 9d551194..f5c0e4e6 100644 --- a/ui/localization/messages/it.json +++ b/ui/localization/messages/it.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Impossibile reimpostare la configurazione: {error}", "advanced_error_set_dev_channel": "Impossibile impostare lo stato del canale di sviluppo: {error}", "advanced_error_set_dev_mode": "Impossibile impostare la modalità di sviluppo: {error}", + "advanced_error_set_log_level": "Impossibile impostare il livello di log: {error}", "advanced_error_update_ssh_key": "Impossibile aggiornare la chiave SSH: {error}", "advanced_error_usb_emulation_disable": "Impossibile disabilitare l'emulazione USB: {error}", "advanced_error_usb_emulation_enable": "Impossibile abilitare l'emulazione USB: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Ripristino di fabbrica non riuscito: {error}", "advanced_factory_reset_success": "Ripristino di fabbrica avviato. Il dispositivo si riavvierà a breve.", "advanced_factory_reset_title": "Ripristino di fabbrica", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Errore", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Avviso", "advanced_loopback_only_description": "Limita l'accesso all'interfaccia web solo a localhost (127.0.0.1)", "advanced_loopback_only_title": "Modalità solo loopback", "advanced_loopback_warning_before": "Prima di abilitare questa funzione, assicurati di avere:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "Configurazione ripristinata ai valori predefiniti con successo", "advanced_success_update_ssh_key": "Chiave SSH aggiornata correttamente", "advanced_title": "Avanzato", + "advanced_troubleshooting_log_level_description": "Regola il dettaglio dei log per la diagnostica. Livelli più alti possono influire sulle prestazioni", + "advanced_troubleshooting_log_level_title": "Livello di log", "advanced_troubleshooting_mode_description": "Strumenti diagnostici e controlli aggiuntivi per la risoluzione dei problemi e lo sviluppo", "advanced_troubleshooting_mode_title": "Modalità di risoluzione dei problemi", "advanced_update_ssh_key_button": "Aggiorna la chiave SSH", diff --git a/ui/localization/messages/ja.json b/ui/localization/messages/ja.json index 85cc72e2..cda5f9c9 100644 --- a/ui/localization/messages/ja.json +++ b/ui/localization/messages/ja.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "設定のリセットに失敗しました: {error}", "advanced_error_set_dev_channel": "Devチャンネル状態の設定に失敗しました: {error}", "advanced_error_set_dev_mode": "開発者モードの設定に失敗しました: {error}", + "advanced_error_set_log_level": "ログレベルの設定に失敗しました: {error}", "advanced_error_update_ssh_key": "SSHキーの更新に失敗しました: {error}", "advanced_error_usb_emulation_disable": "USBエミュレーションの無効化に失敗しました: {error}", "advanced_error_usb_emulation_enable": "USBエミュレーションの有効化に失敗しました: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "工場出荷時リセットに失敗しました: {error}", "advanced_factory_reset_success": "工場出荷時リセットを開始しました。まもなくデバイスが再起動します。", "advanced_factory_reset_title": "工場出荷時リセット", + "advanced_log_level_debug": "デバッグ", + "advanced_log_level_error": "エラー", + "advanced_log_level_info": "情報", + "advanced_log_level_trace": "トレース", + "advanced_log_level_warning": "警告", "advanced_loopback_only_description": "Webインターフェースへのアクセスをlocalhost (127.0.0.1) のみに制限する", "advanced_loopback_only_title": "ループバック専用モード", "advanced_loopback_warning_before": "この機能を有効にする前に、以下のいずれかを確認してください:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "設定が正常にデフォルトにリセットされました", "advanced_success_update_ssh_key": "SSHキーが正常に更新されました", "advanced_title": "詳細設定", + "advanced_troubleshooting_log_level_description": "診断用にログの詳細度を調整します。レベルが高いほどパフォーマンスに影響する場合があります", + "advanced_troubleshooting_log_level_title": "ログレベル", "advanced_troubleshooting_mode_description": "トラブルシューティングおよび開発目的の診断ツールと追加コントロール", "advanced_troubleshooting_mode_title": "トラブルシューティングモード", "advanced_update_ssh_key_button": "SSHキーを更新", diff --git a/ui/localization/messages/nb.json b/ui/localization/messages/nb.json index 48dc3ec8..54188150 100644 --- a/ui/localization/messages/nb.json +++ b/ui/localization/messages/nb.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Kunne ikke tilbakestille konfigurasjonen: {error}", "advanced_error_set_dev_channel": "Klarte ikke å angi tilstanden til utviklerkanalen: {error}", "advanced_error_set_dev_mode": "Kunne ikke angi utviklermodus: {error}", + "advanced_error_set_log_level": "Kunne ikke angi loggnivå: {error}", "advanced_error_update_ssh_key": "Kunne ikke oppdatere SSH-nøkkelen: {error}", "advanced_error_usb_emulation_disable": "Kunne ikke deaktivere USB-emulering: {error}", "advanced_error_usb_emulation_enable": "Kunne ikke aktivere USB-emulering: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Tilbakestilling til fabrikkinnstillinger feilet: {error}", "advanced_factory_reset_success": "Tilbakestilling til fabrikkinnstillinger startet. Enheten starter snart på nytt.", "advanced_factory_reset_title": "Tilbakestill til fabrikkinnstillinger", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Feil", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Advarsel", "advanced_loopback_only_description": "Begrens tilgang til webgrensesnittet kun til lokal vert (127.0.0.1)", "advanced_loopback_only_title": "Kun lokal tilgang", "advanced_loopback_warning_before": "Før du aktiverer denne funksjonen, må du sørge for at du har enten:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "Konfigurasjonen ble tilbakestilt til standard", "advanced_success_update_ssh_key": "SSH-nøkkelen er oppdatert", "advanced_title": "Avansert", + "advanced_troubleshooting_log_level_description": "Juster loggdetaljer for feilsøking. Høyere nivåer kan påvirke ytelsen", + "advanced_troubleshooting_log_level_title": "Loggnivå", "advanced_troubleshooting_mode_description": "Diagnostiske verktøy og tilleggskontroller for feilsøking og utviklingsformål", "advanced_troubleshooting_mode_title": "Feilsøkingsverktøy", "advanced_update_ssh_key_button": "Oppdater SSH-nøkkel", diff --git a/ui/localization/messages/pt.json b/ui/localization/messages/pt.json index ae3c6418..161647af 100644 --- a/ui/localization/messages/pt.json +++ b/ui/localization/messages/pt.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Falha ao redefinir configuração: {error}", "advanced_error_set_dev_channel": "Falha ao definir estado do canal de desenvolvimento: {error}", "advanced_error_set_dev_mode": "Falha ao definir modo de desenvolvimento: {error}", + "advanced_error_set_log_level": "Falha ao definir o nível de registo: {error}", "advanced_error_update_ssh_key": "Falha ao atualizar chave SSH: {error}", "advanced_error_usb_emulation_disable": "Falha ao desativar emulação USB: {error}", "advanced_error_usb_emulation_enable": "Falha ao ativar emulação USB: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Falha na reposição de fábrica: {error}", "advanced_factory_reset_success": "Reposição de fábrica iniciada. O dispositivo irá reiniciar em breve.", "advanced_factory_reset_title": "Reposição de Fábrica", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Erro", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Aviso", "advanced_loopback_only_description": "Restringir o acesso à interface web apenas ao localhost (127.0.0.1)", "advanced_loopback_only_title": "Modo Somente Loopback", "advanced_loopback_warning_before": "Antes de ativar este recurso, certifique-se de ter:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "Configuração redefinida para o padrão com sucesso", "advanced_success_update_ssh_key": "Chave SSH atualizada com sucesso", "advanced_title": "Avançado", + "advanced_troubleshooting_log_level_description": "Ajuste o detalhe dos registos para diagnóstico. Níveis mais elevados podem afetar o desempenho", + "advanced_troubleshooting_log_level_title": "Nível de registo", "advanced_troubleshooting_mode_description": "Ferramentas de diagnóstico e controles adicionais para solução de problemas e fins de desenvolvimento", "advanced_troubleshooting_mode_title": "Modo de Solução de Problemas", "advanced_update_ssh_key_button": "Atualizar Chave SSH", diff --git a/ui/localization/messages/ru.json b/ui/localization/messages/ru.json index 54be1a0d..017b90fb 100644 --- a/ui/localization/messages/ru.json +++ b/ui/localization/messages/ru.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Не удалось сбросить конфигурацию: {error}", "advanced_error_set_dev_channel": "Не удалось изменить состояние dev-канала: {error}", "advanced_error_set_dev_mode": "Не удалось изменить режим разработчика: {error}", + "advanced_error_set_log_level": "Не удалось изменить уровень журналирования: {error}", "advanced_error_update_ssh_key": "Не удалось обновить SSH-ключ: {error}", "advanced_error_usb_emulation_disable": "Не удалось отключить эмуляцию USB: {error}", "advanced_error_usb_emulation_enable": "Не удалось включить эмуляцию USB: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Сброс к заводским настройкам не удался: {error}", "advanced_factory_reset_success": "Сброс к заводским настройкам инициирован. Устройство скоро перезагрузится.", "advanced_factory_reset_title": "Сброс к заводским настройкам", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Ошибка", + "advanced_log_level_info": "Информация", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Предупреждение", "advanced_loopback_only_description": "Ограничить доступ к веб-интерфейсу только с localhost (127.0.0.1)", "advanced_loopback_only_title": "Режим только loopback", "advanced_loopback_warning_before": "Перед включением этой функции убедитесь, что у вас есть:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "Конфигурация успешно сброшена по умолчанию", "advanced_success_update_ssh_key": "SSH-ключ успешно обновлён", "advanced_title": "Дополнительно", + "advanced_troubleshooting_log_level_description": "Настройте детализацию журналов для диагностики. Высокие уровни могут повлиять на производительность", + "advanced_troubleshooting_log_level_title": "Уровень журналирования", "advanced_troubleshooting_mode_description": "Диагностические инструменты и дополнительные элементы управления для устранения неполадок и разработки", "advanced_troubleshooting_mode_title": "Режим устранения неполадок", "advanced_update_ssh_key_button": "Обновить SSH-ключ", diff --git a/ui/localization/messages/sv.json b/ui/localization/messages/sv.json index e59481fa..4cf3597d 100644 --- a/ui/localization/messages/sv.json +++ b/ui/localization/messages/sv.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "Misslyckades med att återställa konfigurationen: {error}", "advanced_error_set_dev_channel": "Misslyckades med att ställa in status för utvecklarkanalen: {error}", "advanced_error_set_dev_mode": "Misslyckades med att ställa in utvecklarläge: {error}", + "advanced_error_set_log_level": "Misslyckades med att ställa in loggnivå: {error}", "advanced_error_update_ssh_key": "Misslyckades med att uppdatera SSH-nyckeln: {error}", "advanced_error_usb_emulation_disable": "Misslyckades med att inaktivera USB-emulering: {error}", "advanced_error_usb_emulation_enable": "Misslyckades med att aktivera USB-emulering: {error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "Fabriksåterställning misslyckades: {error}", "advanced_factory_reset_success": "Fabriksåterställning startad. Enheten startar om inom kort.", "advanced_factory_reset_title": "Fabriksåterställning", + "advanced_log_level_debug": "Debug", + "advanced_log_level_error": "Fel", + "advanced_log_level_info": "Info", + "advanced_log_level_trace": "Trace", + "advanced_log_level_warning": "Varning", "advanced_loopback_only_description": "Begränsa åtkomst till webbgränssnittet endast till lokal värd (127.0.0.1)", "advanced_loopback_only_title": "Loopback-läge", "advanced_loopback_warning_before": "Innan du aktiverar den här funktionen, se till att du har antingen:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "Konfigurationen återställdes till standardinställningarna", "advanced_success_update_ssh_key": "SSH-nyckeln har uppdaterats", "advanced_title": "Avancerat", + "advanced_troubleshooting_log_level_description": "Justera loggdetaljer för felsökning. Högre nivåer kan påverka prestandan", + "advanced_troubleshooting_log_level_title": "Loggnivå", "advanced_troubleshooting_mode_description": "Diagnostikverktyg och ytterligare kontroller för felsökning och utvecklingsändamål", "advanced_troubleshooting_mode_title": "Felsökningsläge", "advanced_update_ssh_key_button": "Uppdatera SSH-nyckel", diff --git a/ui/localization/messages/zh-tw.json b/ui/localization/messages/zh-tw.json index 73756f67..94baa932 100644 --- a/ui/localization/messages/zh-tw.json +++ b/ui/localization/messages/zh-tw.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "重設設定失敗:{error}", "advanced_error_set_dev_channel": "設定開發頻道狀態失敗:{error}", "advanced_error_set_dev_mode": "設定開發模式失敗:{error}", + "advanced_error_set_log_level": "設定日誌級別失敗:{error}", "advanced_error_update_ssh_key": "更新 SSH 金鑰失敗:{error}", "advanced_error_usb_emulation_disable": "停用 USB 模擬失敗:{error}", "advanced_error_usb_emulation_enable": "啟用 USB 模擬失敗:{error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "恢復出廠設定失敗:{error}", "advanced_factory_reset_success": "已啟動恢復出廠設定。裝置將在稍後重新啟動。", "advanced_factory_reset_title": "恢復出廠設定", + "advanced_log_level_debug": "除錯", + "advanced_log_level_error": "錯誤", + "advanced_log_level_info": "資訊", + "advanced_log_level_trace": "追蹤", + "advanced_log_level_warning": "警告", "advanced_loopback_only_description": "將網頁介面存取限制為僅限 localhost (127.0.0.1)", "advanced_loopback_only_title": "單機回送 (Loopback-Only) 模式", "advanced_loopback_warning_before": "在啟用此功能之前,請確保您已具備:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "設定已成功重設為預設值", "advanced_success_update_ssh_key": "SSH 金鑰更新成功", "advanced_title": "進階", + "advanced_troubleshooting_log_level_description": "調整日誌詳細程度以便診斷。較高級別可能影響效能", + "advanced_troubleshooting_log_level_title": "日誌級別", "advanced_troubleshooting_mode_description": "用於故障排除和開發目的的診斷工具及額外控制項", "advanced_troubleshooting_mode_title": "故障排除模式", "advanced_update_ssh_key_button": "更新 SSH 金鑰", diff --git a/ui/localization/messages/zh.json b/ui/localization/messages/zh.json index 9d5b9c1f..703ffefe 100644 --- a/ui/localization/messages/zh.json +++ b/ui/localization/messages/zh.json @@ -77,6 +77,7 @@ "advanced_error_reset_config": "重置配置失败:{error}", "advanced_error_set_dev_channel": "设置开发者通道状态失败:{error}", "advanced_error_set_dev_mode": "设置开发者模式失败:{error}", + "advanced_error_set_log_level": "设置日志级别失败:{error}", "advanced_error_update_ssh_key": "更新 SSH 密钥失败:{error}", "advanced_error_usb_emulation_disable": "禁用 USB 模拟失败:{error}", "advanced_error_usb_emulation_enable": "启用 USB 模拟失败:{error}", @@ -89,6 +90,11 @@ "advanced_factory_reset_error": "恢复出厂设置失败:{error}", "advanced_factory_reset_success": "出厂设置恢复已启动,设备即将重启。", "advanced_factory_reset_title": "恢复出厂设置", + "advanced_log_level_debug": "调试", + "advanced_log_level_error": "错误", + "advanced_log_level_info": "信息", + "advanced_log_level_trace": "跟踪", + "advanced_log_level_warning": "警告", "advanced_loopback_only_description": "将 Web 访问限制为仅本地主机 (127.0.0.1)。", "advanced_loopback_only_title": "环回模式", "advanced_loopback_warning_before": "在启用此功能之前,请确保您已具备以下任一条件:", @@ -112,6 +118,8 @@ "advanced_success_reset_config": "配置已成功恢复为默认设置。", "advanced_success_update_ssh_key": "SSH 密钥更新成功。", "advanced_title": "高级设置", + "advanced_troubleshooting_log_level_description": "调整日志详细程度以便诊断。较高级别可能影响性能", + "advanced_troubleshooting_log_level_title": "日志级别", "advanced_troubleshooting_mode_description": "用于故障排查和开发的诊断工具及额外控制选项。", "advanced_troubleshooting_mode_title": "故障排查模式", "advanced_update_ssh_key_button": "更新 SSH 密钥", diff --git a/ui/package.json b/ui/package.json index 9ae6a949..174dfe07 100644 --- a/ui/package.json +++ b/ui/package.json @@ -92,7 +92,8 @@ }, "lint-staged": { "*.{ts,tsx}": "oxlint --fix --deny-warnings", - "*.{ts,tsx,js,jsx,json,css,md}": "oxfmt" + "*.{ts,tsx,js,jsx,json,css,md}": "oxfmt", + "localization/messages/*.json": "npm run i18n:resort" }, "engines": { "node": "^22.21.1" diff --git a/ui/src/routes/devices.$id.settings.advanced.tsx b/ui/src/routes/devices.$id.settings.advanced.tsx index 282822b7..b3f4ab25 100644 --- a/ui/src/routes/devices.$id.settings.advanced.tsx +++ b/ui/src/routes/devices.$id.settings.advanced.tsx @@ -28,6 +28,7 @@ export default function SettingsAdvancedRoute() { const [sshKey, setSSHKey] = useState(""); const { setDeveloperMode } = useSettingsStore(); const [devChannel, setDevChannel] = useState(false); + const [defaultLogLevel, setDefaultLogLevel] = useState("WARN"); const [usbEmulationEnabled, setUsbEmulationEnabled] = useState(false); const [showLoopbackWarning, setShowLoopbackWarning] = useState(false); const [localLoopbackOnly, setLocalLoopbackOnly] = useState(false); @@ -66,6 +67,11 @@ export default function SettingsAdvancedRoute() { if ("error" in resp) return; setLocalLoopbackOnly(resp.result as boolean); }); + + send("getDefaultLogLevel", {}, (resp: JsonRpcResponse) => { + if ("error" in resp) return; + setDefaultLogLevel(resp.result as string); + }); }, [send, setDeveloperMode]); const getUsbEmulationState = useCallback(() => { @@ -454,6 +460,37 @@ export default function SettingsAdvancedRoute() { {settings.debugMode && ( + + { + const level = e.target.value; + const previousLevel = defaultLogLevel; + setDefaultLogLevel(level); + send("setDefaultLogLevel", { level }, (resp: JsonRpcResponse) => { + if ("error" in resp) { + setDefaultLogLevel(previousLevel); + notifications.error( + m.advanced_error_set_log_level({ error: resp.error.data || m.unknown_error() }), + ); + return; + } + }); + }} + /> + +