Commit e984e3170c4d44990f2f042a3ecd8525068033be

Commits
[COMMIT BEGIN]
commit e984e3170c4d44990f2f042a3ecd8525068033be
Author: 0x4248 <[email protected]>
Date:   Mon Jan 12 23:58:43 2026 +0000

    orion: Add logging functions
    
    Signed-off-by: 0x4248 <[email protected]>

diff --git a/lab/orion/commands/system/open.py b/lab/orion/commands/system/open.py
index 726db9d..e37a3d8 100644
--- a/lab/orion/commands/system/open.py
+++ b/lab/orion/commands/system/open.py
@@ -23,9 +23,27 @@ def open_page(request: Request, name: str = ""):
 
     return RedirectResponse(f"/command/{name}", status_code=303)
 
+def goto(request: Request, name: str = ""):
+    return RedirectResponse(f"/{name}", status_code=303)
+
 registry.register(Command(
     name="open",
     handler=open_page,
     summary="Open a UI page",
     mode="cli",
 ))
+
+
+registry.register(Command(
+    name="goto",
+    handler=goto,
+    summary="Jumps to a url",
+    mode="cli",
+))
+
+registry.register(Command(
+    name="g",
+    handler=goto,
+    summary="Jumps to a url",
+    mode="cli",
+))
diff --git a/lab/orion/core/console.py b/lab/orion/core/console.py
new file mode 100644
index 0000000..8932e9d
--- /dev/null
+++ b/lab/orion/core/console.py
@@ -0,0 +1,85 @@
+import datetime
+from typing import Dict
+import traceback
+
+from core.page import message
+
+global logger
+global log_db
+
+import sys
+
+def _get_caller():
+    f = sys._getframe(2)
+    module = f.f_globals.get("__name__", "<unknown>")
+    func = f.f_code.co_name
+    return f"{module}.{func}()"
+
+
+class LogDatabase:
+    def __init__(self):
+        self.logs = {}
+
+    def add_entry(self, level: str, caller: str, message: str) -> int:
+        log_id = len(self.logs) + 1
+        timestamp = datetime.datetime.now().isoformat()
+        self.logs[log_id] = {
+            "id": log_id,
+            "timestamp": timestamp,
+            "level": level,
+            "caller": caller,
+            "message": message
+        }
+        return log_id
+    
+class Logger:
+    def __init__(self, bark: bool = True, log_db_inp: LogDatabase | None = None):
+        self.bark = bark
+        self.log_db = log_db_inp
+    def log(self, caller: str = "Unknown", m: str | None = None, level: str = "INFO") -> int:
+        if self.log_db is None:
+            raise ValueError("No log database provided")
+        if m is None:
+            m = "No message provided"
+        if self.bark:
+            print(f"[{level}] {caller}: {m}")
+        log_id = log_db.add_entry(level, caller, m)
+        return log_id
+    
+    def debug(self, caller: str | None = None, m: str | None = None) -> int:
+        if caller is None:
+            caller = _get_caller()
+        return self.log(caller, m, "DEBUG")
+
+    def info(self, caller: str | None = None, m: str | None = None) -> int:
+        if caller is None:
+            caller = _get_caller()
+        return self.log(caller, m, "INFO")
+    
+    def warning(self, caller: str | None = None, m: str | None = None) -> int:
+        if caller is None:
+            caller = _get_caller()
+        return self.log(caller, m, "WARNING")
+    
+    def error(self, caller: str | None = None, m: str | None = None) -> int:
+        if caller is None:
+            caller = _get_caller()
+        return self.log(caller, m, "ERROR")
+    
+    def critical(self, caller: str | None = None, m: str | None = None) -> int:
+        if caller is None:
+            caller = _get_caller()
+        return self.log(caller, m, "CRITICAL")
+    
+    def alarm(self, caller: str | None = None, m: str | None = None) -> int:
+        if caller is None:
+            caller = _get_caller()
+        return self.log(caller, m, "ALARM")
+
+# If already imported dont reinit
+if 'logger' not in globals():
+    log_db = LogDatabase()
+    logger = Logger(bark=True, log_db_inp=log_db)
+    logger.info(m="Logger initialized successfully")
+else:
+    logger.info(m="Logger already initialized, skipping reinitialization")
\ No newline at end of file
diff --git a/lab/orion/core/layout.py b/lab/orion/core/layout.py
index 083bb2b..29c3183 100644
--- a/lab/orion/core/layout.py
+++ b/lab/orion/core/layout.py
@@ -66,6 +66,47 @@ label {
   text-transform: uppercase;
 }
 
+
+.gray-span {
+  color: gray;
+  font-style: italic;
+}
+
+.log-debug {
+  color: gray;
+}
+
+.log-info {
+  color: #4da6ff;
+}
+.log-warning {
+  color: black;
+  background-color: yellow;
+}
+.log-error {
+  color: white;
+  background-color: red;
+}
+
+.log-error-flash {
+  background-color: red;
+  color: white;
+  padding-top: 0.5em;
+  padding-bottom: 0.5em;
+  animation: flash-text 1s infinite;
+}
+
+.flash {
+  animation: flash-text 1s infinite;
+}
+
+@keyframes flash-text {
+  0% { opacity: 1; }
+  49% { opacity: 1; }
+  50% { opacity: 0; }
+  100% { opacity: 0; }
+}
+
 .error {
   background-color: red;
   color: white;
@@ -74,6 +115,14 @@ label {
   animation: pulse_error 1s;
 }
 
+.error-flash {
+  background-color: red;
+  color: white;
+  padding-top: 0.5em;
+  padding-bottom: 0.5em;
+  animation: flash-text 1s infinite;
+}
+
 @keyframes pulse_error {
   0% { background-color: #ff8f8f; }
   100% { background-color: red; }
diff --git a/lab/orion/core/logbridge.py b/lab/orion/core/logbridge.py
new file mode 100644
index 0000000..b005ac5
--- /dev/null
+++ b/lab/orion/core/logbridge.py
@@ -0,0 +1,17 @@
+import logging
+
+class logBridge(logging.Handler):
+    def __init__(self, orionLoggerBridge):
+        super().__init__()
+        self.orionLoggerBridge = orionLoggerBridge
+
+    def emit(self, record: logging.LogRecord):
+        try:
+            msg = self.format(record)
+            self.orionLoggerBridge.log(
+                f"BRIDGE -> {record.name}.{record.funcName}()",
+                msg,
+                record.levelname,
+            )
+        except Exception:
+            self.handleError(record)
diff --git a/lab/orion/main.py b/lab/orion/main.py
index 53d82db..f080ba8 100644
--- a/lab/orion/main.py
+++ b/lab/orion/main.py
@@ -1,19 +1,39 @@
 from fastapi import FastAPI, Request
-from fastapi.responses import FileResponse, RedirectResponse
+from fastapi.responses import FileResponse
 
-from pages import command,about
-from core import auth
+from core.logbridge import logBridge
+from pages import command, about, console
+from core import auth, console
 from core import page as p
 
-
 import commands.system.open
-
 import commands.system.manual as manual
 import commands.echo
+import logging
 
-app = FastAPI()
+handler = logBridge(console.logger)
+handler.setFormatter(logging.Formatter("%(message)s"))
 
+root = logging.getLogger()
+root.handlers.clear()
+root.addHandler(handler)
+root.setLevel(logging.DEBUG)
 
+for name in (
+    "uvicorn",
+    "uvicorn.error",
+    "uvicorn.access",
+    "fastapi",
+):
+    log = logging.getLogger(name)
+    log.handlers.clear()
+    log.addHandler(handler)
+    log.propagate = False
+
+
+app = FastAPI()
+
+console.logger.info(m="Starting Orion Web Application")
 
 app.middleware("http")(auth.auth_middleware)
 
@@ -22,6 +42,8 @@ app.include_router(command.router)
 app.include_router(about.router)
 app.include_router(manual.router)
 
+console.logger.info(m=app.router.routes)
+
 @app.exception_handler(404)
 async def not_found(request: Request, exc):
     return p.static(
@@ -37,4 +59,10 @@ async def favicon():
 
 if __name__ == "__main__":
     import uvicorn
-    uvicorn.run(app, host="0.0.0.0", port=8000)
+    uvicorn.run(
+        app,
+        host="0.0.0.0",
+        port=8000,
+        log_config=None,
+        access_log=True,
+    )
[COMMIT END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.