Parcourir la source

Show database engine and version on System Information page

  Display the active database backend (SQLite or PostgreSQL) and its
  version in the Database section of the System Info page. SQLite queries
  sqlite_version(), PostgreSQL queries SELECT version() and
  pg_database_size(). Helps users verify which database is in use.
maziggy il y a 1 mois
Parent
commit
0f0fac9b32

+ 1 - 0
CHANGELOG.md

@@ -8,6 +8,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **Optional PostgreSQL Database Support** — Bambuddy can now use an external PostgreSQL database instead of the built-in SQLite. Set the `DATABASE_URL` environment variable (e.g., `postgresql+asyncpg://user:pass@host:5432/bambuddy`) to connect to Postgres. SQLite remains the default when no `DATABASE_URL` is set. All features work with both backends including full-text archive search (FTS5 on SQLite, tsvector+GIN on PostgreSQL), backup/restore (file copy vs pg_dump/pg_restore), health diagnostics, and cross-database restore (import a SQLite backup into PostgreSQL with automatic type conversion and FK handling).
 - **Optional PostgreSQL Database Support** — Bambuddy can now use an external PostgreSQL database instead of the built-in SQLite. Set the `DATABASE_URL` environment variable (e.g., `postgresql+asyncpg://user:pass@host:5432/bambuddy`) to connect to Postgres. SQLite remains the default when no `DATABASE_URL` is set. All features work with both backends including full-text archive search (FTS5 on SQLite, tsvector+GIN on PostgreSQL), backup/restore (file copy vs pg_dump/pg_restore), health diagnostics, and cross-database restore (import a SQLite backup into PostgreSQL with automatic type conversion and FK handling).
 
 
 ### Improved
 ### Improved
+- **Database Engine Info on System Page** — The System Information page now shows the active database engine (SQLite or PostgreSQL) and its version in the Database section, making it easy to verify which backend is in use.
 - **REST Smart Plug: Separate Power/Energy URLs and Unit Multipliers** ([#472](https://github.com/maziggy/bambuddy/issues/472)) — REST/Webhook smart plugs can now use individual URLs for power and energy data instead of requiring all values in a single status response. Each value falls back to the shared Status URL when no separate URL is configured, so existing setups work without changes. Added power and energy multipliers for unit conversion (e.g., set energy multiplier to `0.001` to convert Wh to kWh). Useful for platforms like ioBroker that expose each data point as a separate API endpoint.
 - **REST Smart Plug: Separate Power/Energy URLs and Unit Multipliers** ([#472](https://github.com/maziggy/bambuddy/issues/472)) — REST/Webhook smart plugs can now use individual URLs for power and energy data instead of requiring all values in a single status response. Each value falls back to the shared Status URL when no separate URL is configured, so existing setups work without changes. Added power and energy multipliers for unit conversion (e.g., set energy multiplier to `0.001` to convert Wh to kWh). Useful for platforms like ioBroker that expose each data point as a separate API endpoint.
 
 
 ### Fixed
 ### Fixed

+ 34 - 3
backend/app/api/routes/system.py

@@ -453,9 +453,38 @@ async def get_system_info(
     archive_dir = settings.archive_dir
     archive_dir = settings.archive_dir
     archive_size = get_directory_size(archive_dir) if archive_dir.exists() else 0
     archive_size = get_directory_size(archive_dir) if archive_dir.exists() else 0
 
 
-    # Database file size
-    db_path = settings.base_dir / "bambuddy.db"
-    db_size = db_path.stat().st_size if db_path.exists() else 0
+    # Database info (engine type, version, size)
+    from backend.app.core.db_dialect import is_postgres, is_sqlite
+
+    db_engine_info: dict = {"engine": "unknown", "version": "unknown"}
+    db_size = 0
+    try:
+        if is_postgres():
+            from sqlalchemy import text
+
+            result = await db.execute(text("SELECT version()"))
+            pg_version_full = result.scalar() or "unknown"
+            # e.g. "PostgreSQL 16.2 on x86_64..." → "PostgreSQL 16.2"
+            pg_version = " ".join(pg_version_full.split()[:2])
+            result = await db.execute(text("SELECT pg_database_size(current_database())"))
+            db_size = result.scalar() or 0
+            db_engine_info = {
+                "engine": "PostgreSQL",
+                "version": pg_version,
+            }
+        elif is_sqlite():
+            from sqlalchemy import text
+
+            result = await db.execute(text("SELECT sqlite_version()"))
+            sqlite_ver = result.scalar() or "unknown"
+            db_path = settings.base_dir / "bambuddy.db"
+            db_size = db_path.stat().st_size if db_path.exists() else 0
+            db_engine_info = {
+                "engine": "SQLite",
+                "version": f"SQLite {sqlite_ver}",
+            }
+    except Exception:
+        pass
 
 
     # Disk usage
     # Disk usage
     disk = psutil.disk_usage(str(settings.base_dir))
     disk = psutil.disk_usage(str(settings.base_dir))
@@ -475,6 +504,8 @@ async def get_system_info(
             "archive_dir": str(archive_dir),
             "archive_dir": str(archive_dir),
         },
         },
         "database": {
         "database": {
+            "engine": db_engine_info["engine"],
+            "version": db_engine_info["version"],
             "archives": archive_count,
             "archives": archive_count,
             "archives_completed": completed_count,
             "archives_completed": completed_count,
             "archives_failed": failed_count,
             "archives_failed": failed_count,

+ 2 - 0
frontend/src/__tests__/pages/SystemInfoPage.test.tsx

@@ -30,6 +30,8 @@ const mockSystemInfo = {
     archive_dir: '/opt/bambuddy/archives',
     archive_dir: '/opt/bambuddy/archives',
   },
   },
   database: {
   database: {
+    engine: 'SQLite',
+    version: 'SQLite 3.45.1',
     archives: 150,
     archives: 150,
     archives_completed: 140,
     archives_completed: 140,
     archives_failed: 8,
     archives_failed: 8,

+ 2 - 0
frontend/src/api/client.ts

@@ -4473,6 +4473,8 @@ export interface SystemInfo {
     archive_dir: string;
     archive_dir: string;
   };
   };
   database: {
   database: {
+    engine: string;
+    version: string;
     archives: number;
     archives: number;
     archives_completed: number;
     archives_completed: number;
     archives_failed: number;
     archives_failed: number;

+ 12 - 0
frontend/src/pages/SystemInfoPage.tsx

@@ -357,6 +357,18 @@ export function SystemInfoPage() {
 
 
       {/* Database Stats */}
       {/* Database Stats */}
       <Section title={t('system.database', 'Database')} icon={Database}>
       <Section title={t('system.database', 'Database')} icon={Database}>
+        <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
+          <StatCard
+            icon={Database}
+            label={t('system.dbEngine', 'Database Engine')}
+            value={systemInfo.database.engine || 'SQLite'}
+          />
+          <StatCard
+            icon={Database}
+            label={t('system.dbVersion', 'Version')}
+            value={systemInfo.database.version || 'unknown'}
+          />
+        </div>
         <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
         <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
           <StatCard
           <StatCard
             icon={Archive}
             icon={Archive}

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
static/assets/index-Bexverg5.js


+ 1 - 1
static/index.html

@@ -23,7 +23,7 @@
 
 
     <!-- Splash screens for iOS -->
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-CQTlViGa.js"></script>
+    <script type="module" crossorigin src="/assets/index-Bexverg5.js"></script>
     <link rel="stylesheet" crossorigin href="/assets/index-BGA3I7Jb.css">
     <link rel="stylesheet" crossorigin href="/assets/index-BGA3I7Jb.css">
   </head>
   </head>
   <body>
   <body>

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff