Files
ewoooc/scripts/tools/database_exporter.py
ogt 1b4f3a7bbe
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
feat: EwoooC 初始化 — 完整專案推版至 Gitea
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml)
- 部署模式: rsync Python 檔案至 188 → docker restart (volume mount)
- Dockerfile/requirements 變動時自動重建 Docker image
- 部署通知: Telegram (開始/成功/失敗)
- 健康檢查: https://mo.wooo.work/health (最多 5 次重試)
- 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:21:13 +08:00

128 lines
4.3 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SQLite 資料庫監控腳本
收集資料庫狀態、大小、查詢效能等指標
"""
import sqlite3
import os
import time
from datetime import datetime
from flask import Flask
from prometheus_client import Gauge, Counter, Histogram, generate_latest, REGISTRY
app = Flask(__name__)
# 定義 Prometheus 指標
db_size_bytes = Gauge('sqlite_database_size_bytes', '資料庫檔案大小bytes', ['database'])
db_record_count = Gauge('sqlite_record_count', '資料表記錄總數', ['database', 'table'])
db_query_duration = Histogram('sqlite_query_duration_seconds', '查詢執行時間', ['query_type'])
db_connection_errors = Counter('sqlite_connection_errors_total', '連接錯誤總數')
db_slow_queries = Counter('sqlite_slow_queries_total', '慢查詢總數(>1秒', ['table'])
# 資料庫路徑
DATABASE_PATH = '/home/ogt/momo_pro_system/data/momo_database.db'
def get_db_size():
"""獲取資料庫檔案大小"""
try:
if os.path.exists(DATABASE_PATH):
size = os.path.getsize(DATABASE_PATH)
db_size_bytes.labels(database='momo').set(size)
return size
return 0
except Exception as e:
print(f"Error getting database size: {e}")
return 0
def get_table_counts():
"""獲取各資料表的記錄數"""
try:
conn = sqlite3.connect(DATABASE_PATH, timeout=5)
cursor = conn.cursor()
# 獲取所有資料表
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'")
tables = cursor.fetchall()
for (table_name,) in tables:
try:
start_time = time.time()
cursor.execute(f"SELECT COUNT(*) FROM {table_name}")
count = cursor.fetchone()[0]
duration = time.time() - start_time
# 記錄指標
db_record_count.labels(database='momo', table=table_name).set(count)
db_query_duration.labels(query_type='count').observe(duration)
# 檢測慢查詢
if duration > 1.0:
db_slow_queries.labels(table=table_name).inc()
except Exception as e:
print(f"Error counting table {table_name}: {e}")
conn.close()
except Exception as e:
print(f"Database connection error: {e}")
db_connection_errors.inc()
def measure_query_performance():
"""測試常見查詢的效能"""
try:
conn = sqlite3.connect(DATABASE_PATH, timeout=5)
cursor = conn.cursor()
# 測試查詢 1最近銷售數據
start_time = time.time()
cursor.execute("SELECT * FROM realtime_sales_monthly ORDER BY 日期 DESC LIMIT 100")
cursor.fetchall()
duration = time.time() - start_time
db_query_duration.labels(query_type='recent_sales').observe(duration)
if duration > 1.0:
db_slow_queries.labels(table='realtime_sales_monthly').inc()
# 測試查詢 2商品統計
start_time = time.time()
cursor.execute("SELECT 品牌, COUNT(*) FROM realtime_sales_monthly GROUP BY 品牌 LIMIT 50")
cursor.fetchall()
duration = time.time() - start_time
db_query_duration.labels(query_type='brand_stats').observe(duration)
conn.close()
except Exception as e:
print(f"Query performance test error: {e}")
db_connection_errors.inc()
@app.route('/metrics')
def metrics():
"""Prometheus metrics endpoint"""
# 收集最新指標
get_db_size()
get_table_counts()
measure_query_performance()
# 返回 Prometheus 格式的指標
return generate_latest(REGISTRY)
@app.route('/health')
def health():
"""健康檢查端點"""
try:
if os.path.exists(DATABASE_PATH):
conn = sqlite3.connect(DATABASE_PATH, timeout=2)
conn.close()
return 'OK', 200
return 'Database file not found', 503
except Exception as e:
return f'Error: {str(e)}', 503
if __name__ == '__main__':
print(f"Starting Database Exporter on http://127.0.0.1:9120/metrics")
app.run(host='127.0.0.1', port=9120)