Initial commit: Momentry Core v0.1

- Rust-based digital asset management system
- Video analysis: ASR, OCR, YOLO, Face, Pose
- RAG capabilities with Qdrant vector database
- Multi-database support: PostgreSQL, Redis, MongoDB
- Monitoring system with launchd plists
- n8n workflow automation integration
This commit is contained in:
accusys
2026-03-16 15:07:33 +08:00
commit de14bd6afa
101 changed files with 19858 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
#!/bin/bash
# Momentry MongoDB 監控 (Layer 5)
# 路徑: /Users/accusys/momentry_core_0.1/monitor/database/mongodb_monitor.sh
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_DIR="/Users/accusys/momentry/log/monitor"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/mongodb_check.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
MONGO_USER="accusys"
MONGO_PASS="Test3200Test3200"
record_metric() {
psql -U accusys -h localhost -d momentry << EOF 2>/dev/null
INSERT INTO monitor_databases (db_type, db_name, metric_name, metric_value, checked_at)
VALUES ('mongodb', 'mongodb', '$1', '$2', NOW());
EOF
}
get_status() {
mongosh --quiet --username "$MONGO_USER" --password "$MONGO_PASS" --authenticationDatabase admin --eval "JSON.stringify(db.adminCommand({ replSetGetStatus: 1 }))" 2>/dev/null || echo "{}"
}
get_server_status() {
mongosh --quiet --username "$MONGO_USER" --password "$MONGO_PASS" --authenticationDatabase admin --eval "JSON.stringify(db.serverStatus()))" 2>/dev/null || echo "{}"
}
get_databases() {
mongosh --quiet --username "$MONGO_USER" --password "$MONGO_PASS" --authenticationDatabase admin --eval "JSON.stringify(db.adminCommand({ listDatabases: 1 }))" 2>/dev/null || echo "{}"
}
echo "========================================"
echo "Layer 5: MongoDB Monitoring"
echo "Time: $(date)"
echo "========================================"
echo ""
if ! mongosh --quiet --username "$MONGO_USER" --password "$MONGO_PASS" --authenticationDatabase admin --eval "db.adminCommand('ping')" > /dev/null 2>&1; then
echo "MongoDB 不可用"
log "MongoDB unavailable"
exit 1
fi
echo "✓ MongoDB 連接正常"
echo ""
echo "資料庫:"
echo "----------------------------------------"
databases=$(get_databases)
echo "$databases" | jq -r '.databases[] | " \(.name): \(.sizeOnDisk / 1024 / 1024 | floor)MB"' 2>/dev/null || echo " 無法獲取資料庫列表"
echo ""
echo "伺服器狀態:"
echo "----------------------------------------"
server_status=$(get_server_status)
connections=$(echo "$server_status" | jq -r '.connections.current' 2>/dev/null || echo "N/A")
active_connections=$(echo "$server_status" | jq -r '.connections.active' 2>/dev/null || echo "N/A")
uptime=$(echo "$server_status" | jq -r '.uptime' 2>/dev/null || echo "N/A")
mem_resident=$(echo "$server_status" | jq -r '.mem.resident' 2>/dev/null || echo "N/A")
echo " 當前連接: $connections"
echo " 活躍連接: $active_connections"
echo " 運行時間: ${uptime}"
echo " 記憶體使用: ${mem_resident}MB"
record_metric "connections" "$connections"
record_metric "active_connections" "$active_connections"
record_metric "uptime" "$uptime"
record_metric "mem_resident" "$mem_resident"
echo ""
log "MongoDB check completed: connections=$connections"
echo "========================================"
echo "完成"
echo "========================================"

View File

@@ -0,0 +1,130 @@
#!/bin/bash
# Momentry PostgreSQL 監控 (Layer 5)
# 路徑: /Users/accusys/momentry_core_0.1/monitor/database/postgres_monitor.sh
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MONITOR_DIR="$(dirname "$SCRIPT_DIR")"
LOG_DIR="/Users/accusys/momentry/log/monitor"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/postgres_check.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 記錄指標
record_metric() {
local db_type="postgresql"
local db_name=$1
local metric_name=$2
local value=$3
psql -U accusys -h localhost -d momentry << EOF 2>/dev/null
INSERT INTO monitor_databases (db_type, db_name, metric_name, metric_value, checked_at)
VALUES ('$db_type', '$db_name', '$metric_name', '$value', NOW());
EOF
}
# 獲取資料庫列表
get_databases() {
psql -U accusys -h localhost -t -A -c "SELECT datname FROM pg_database WHERE datistemplate = false;" 2>/dev/null
}
# 獲取表大小
get_table_sizes() {
local db=$1
psql -U accusys -h localhost -d "$db" -t -A -c "
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size,
n_live_tup as rows
FROM pg_stat_user_tables
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 10;
" 2>/dev/null
}
# 獲取連線數
get_connections() {
psql -U accusys -h localhost -t -A -c "
SELECT state, count(*)
FROM pg_stat_activity
WHERE datname = current_database()
GROUP BY state;
" 2>/dev/null
}
# 獲取慢查詢
get_slow_queries() {
psql -U accusys -h localhost -t -A -c "
SELECT query, calls, mean_time
FROM pg_stat_statements
WHERE query NOT LIKE '%pg_stat_statements%'
ORDER BY mean_time DESC
LIMIT 5;
" 2>/dev/null
}
# 主程序
echo "========================================"
echo "Layer 5: PostgreSQL Database Monitoring"
echo "Time: $(date)"
echo "========================================"
echo ""
# 檢查 PostgreSQL 是否可用
if ! pg_isready -h localhost -p 5432 -U accusys > /dev/null 2>&1; then
echo "PostgreSQL 不可用"
log "PostgreSQL unavailable"
exit 1
fi
# 記錄連線數
connections=$(get_connections)
echo "連線狀態:"
echo "$connections"
echo ""
# 記錄指標
record_metric "postgres" "connections" "'$connections'"
# 檢查各資料庫
echo "資料庫表:"
echo "----------------------------------------"
for db in $(get_databases); do
echo ""
echo "資料庫: $db"
table_count=$(psql -U accusys -h localhost -d "$db" -t -A -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null || echo "0")
echo " 表數量: $table_count"
record_metric "$db" "table_count" "$table_count"
# 顯示大表
echo " 大表:"
get_table_sizes "$db" | while read -r schema table size rows; do
[ -z "$table" ] && continue
echo " - $table: $size ($rows rows)"
done
done
# 檢查慢查詢(如果 pg_stat_statements 可用)
echo ""
echo "慢查詢 (如有):"
slow_queries=$(get_slow_queries)
if [ -n "$slow_queries" ]; then
echo "$slow_queries" | while read -r query calls time; do
[ -z "$query" ] && continue
echo " - ${time}ms (調用 $calls 次)"
done
else
echo " (pg_stat_statements 未啟用)"
fi
echo ""
echo "========================================"
log "PostgreSQL check completed"

View File

@@ -0,0 +1,124 @@
#!/bin/bash
# Momentry Qdrant 監控 (Layer 5)
# 路徑: /Users/accusys/momentry_core_0.1/monitor/database/qdrant_monitor.sh
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_DIR="/Users/accusys/momentry/log/monitor"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/qdrant_check.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
QDRANT_HOST="http://localhost:6333"
QDRANT_API_KEY="Test3200Test3200Test3200"
# 記錄指標
record_metric() {
local collection=$1
local metric_name=$2
local value=$3
psql -U accusys -h localhost -d momentry << EOF 2>/dev/null
INSERT INTO monitor_databases (db_type, db_name, metric_name, metric_value, checked_at)
VALUES ('qdrant', '$collection', '$metric_name', '$value', NOW());
EOF
}
# 記錄 Collection
record_collection() {
local name=$1
local vectors=$2
local points=$3
local disk_size=$4
local status=$5
psql -U accusys -h localhost -d momentry << EOF 2>/dev/null
INSERT INTO monitor_qdrant_collections (collection_name, vectors_count, points_count, disk_size_bytes, status, snapshot_at)
VALUES ('$name', $vectors, $points, $disk_size, '$status', NOW())
ON CONFLICT (collection_name) DO UPDATE SET
vectors_count = EXCLUDED.vectors_count,
points_count = EXCLUDED.points_count,
disk_size_bytes = EXCLUDED.disk_size_bytes,
status = EXCLUDED.status,
snapshot_at = NOW();
EOF
}
# 主程序
echo "========================================"
echo "Layer 5: Qdrant Vector Database Monitoring"
echo "Time: $(date)"
echo "========================================"
echo ""
# 檢查 Qdrant 是否可用
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
-H "api-key: $QDRANT_API_KEY" \
"$QDRANT_HOST/collections" 2>/dev/null || echo "000")
if [ "$http_code" = "000" ]; then
echo "Qdrant 不可用"
log "Qdrant unavailable"
exit 1
fi
echo "Qdrant 狀態: HTTP $http_code"
echo ""
# 獲取 Collection 列表
collections=$(curl -s -H "api-key: $QDRANT_API_KEY" "$QDRANT_HOST/collections" 2>/dev/null)
if [ "$http_code" = "200" ]; then
collection_count=$(echo "$collections" | jq '.result.collections | length' 2>/dev/null || echo "0")
echo "Collection 數量: $collection_count"
echo ""
# 遍歷每個 Collection
echo "Collections:"
echo "----------------------------------------"
for i in $(seq 0 $((collection_count - 1))); do
name=$(echo "$collections" | jq -r ".result.collections[$i].name")
# 獲取 Collection 詳情
details=$(curl -s -H "api-key: $QDRANT_API_KEY" "$QDRANT_HOST/collections/$name" 2>/dev/null)
vectors_count=$(echo "$details" | jq -r '.result.indexed_vectors_count // 0' 2>/dev/null || echo "0")
points_count=$(echo "$details" | jq -r '.result.points_count // 0' 2>/dev/null || echo "0")
disk_size=$(echo "$details" | jq -r '.result.disk_size_bytes // 0' 2>/dev/null || echo "0")
status=$(echo "$details" | jq -r '.result.status // "unknown"' 2>/dev/null || echo "unknown")
# 格式化大小
if [ "$disk_size" -gt 1073741824 ]; then
size_str="$((disk_size / 1073741824))GB"
elif [ "$disk_size" -gt 1048576 ]; then
size_str="$((disk_size / 1048576))MB"
elif [ "$disk_size" -gt 1024 ]; then
size_str="$((disk_size / 1024))KB"
else
size_str="${disk_size}B"
fi
echo " - $name"
echo " 狀態: $status"
echo " Vectors: $vectors_count"
echo " Points: $points_count"
echo " 大小: $size_str"
# 記錄到資料庫
record_collection "$name" "$vectors_count" "$points_count" "$disk_size" "$status"
record_metric "$name" "vectors_count" "$vectors_count"
record_metric "$name" "points_count" "$points_count"
record_metric "$name" "disk_size" "$disk_size"
done
else
echo "無法獲取 Collection 列表"
log "Failed to get collections: HTTP $http_code"
fi
echo ""
echo "========================================"
log "Qdrant check completed"

111
monitor/database/redis_monitor.sh Executable file
View File

@@ -0,0 +1,111 @@
#!/bin/bash
# Momentry Redis 監控 (Layer 5)
# 路徑: /Users/accusys/momentry_core_0.1/monitor/database/redis_monitor.sh
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_DIR="/Users/accusys/momentry/log/monitor"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/redis_check.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
REDIS_PASS="accusys"
# 記錄指標
record_metric() {
local value=$1
psql -U accusys -h localhost -d momentry << EOF 2>/dev/null
INSERT INTO monitor_databases (db_type, db_name, metric_name, metric_value, checked_at)
VALUES ('redis', 'redis', '$1', '$2', NOW());
EOF
}
# 獲取 Redis INFO
get_info() {
redis-cli -a "$REDIS_PASS" INFO 2>/dev/null
}
# 主程序
echo "========================================"
echo "Layer 5: Redis Monitoring"
echo "Time: $(date)"
echo "========================================"
echo ""
# 檢查 Redis 是否可用
if ! redis-cli -a "$REDIS_PASS" ping > /dev/null 2>&1; then
echo "Redis 不可用"
log "Redis unavailable"
exit 1
fi
info=$(get_info)
# 提取關鍵指標
echo "關鍵指標:"
echo "----------------------------------------"
# 內存使用
used_memory=$(echo "$info" | grep "^used_memory_human:" | cut -d: -f2 | tr -d '\r')
echo " 內存使用: $used_memory"
# 連線數
connected_clients=$(echo "$info" | grep "^connected_clients:" | cut -d: -f2 | tr -d '\r')
echo " 客戶端連線: $connected_clients"
# 命中率
keyspace_hits=$(echo "$info" | grep "^keyspace_hits:" | cut -d: -f2 | tr -d '\r')
keyspace_misses=$(echo "$info" | grep "^keyspace_misses:" | cut -d: -f2 | tr -d '\r')
total_ops=$((keyspace_hits + keyspace_misses))
if [ $total_ops -gt 0 ]; then
hit_rate=$((keyspace_hits * 100 / total_ops))
echo " 命中率: ${hit_rate}%"
else
echo " 命中率: N/A"
fi
# 持久化
rdb_changes=$(echo "$info" | grep "^rdb_changes_since_last_save:" | cut -d: -f2 | tr -d '\r')
echo " RDB 變更: $rdb_changes"
# 總鍵數
echo ""
echo "鍵數據庫:"
db0_info=$(echo "$info" | grep "^db0:" | head -1)
if [ -n "$db0_info" ]; then
keys=$(echo "$db0_info" | sed 's/.*keys=\([0-9]*\).*/\1/')
expires=$(echo "$db0_info" | sed 's/.*expires=\([0-9]*\).*/\1/')
echo " db0: $keys keys, $expires 有過期時間"
fi
# 記錄到資料庫
record_metric "used_memory" "'$used_memory'"
record_metric "connected_clients" "$connected_clients"
record_metric "keyspace_hits" "$keyspace_hits"
record_metric "keyspace_misses" "$keyspace_misses"
# 檢查閾值
echo ""
echo "閾值檢查:"
memory_percent=$(echo "$info" | grep "^used_memory:" | cut -d: -f2)
maxmemory=$(redis-cli -a "$REDIS_PASS" CONFIG GET maxmemory 2>/dev/null | tail -1)
if [ -n "$maxmemory" ] && [ "$maxmemory" -gt 0 ]; then
mem_pct=$((memory_percent * 100 / maxmemory))
echo " 內存使用: ${mem_pct}%"
if [ $mem_pct -gt 80 ]; then
echo " ⚠️ 內存使用超過 80%"
fi
fi
if [ $connected_clients -gt 100 ]; then
echo " ⚠️ 客戶端連線過多"
fi
echo ""
echo "========================================"
log "Redis check completed"

492
monitor/database/schema.sql Normal file
View File

@@ -0,0 +1,492 @@
-- Momentry 監控系統數據庫表
-- 使用方式: psql -U accusys -h localhost -d momentry -f schema.sql
-- ============================================================
-- Layer 2: Service 監控
-- ============================================================
CREATE TABLE IF NOT EXISTS monitor_services (
id SERIAL PRIMARY KEY,
service_name VARCHAR(50) NOT NULL,
service_type VARCHAR(20),
port INTEGER,
status VARCHAR(20) CHECK (status IN ('up', 'down', 'degraded', 'unknown')),
response_time_ms INTEGER,
error_message TEXT,
checked_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_monitor_services_name ON monitor_services(service_name);
CREATE INDEX idx_monitor_services_time ON monitor_services(checked_at);
-- ============================================================
-- Layer 3: n8n Workflow 監控
-- ============================================================
CREATE TABLE IF NOT EXISTS monitor_workflows (
id SERIAL PRIMARY KEY,
workflow_id VARCHAR(50) NOT NULL,
workflow_name VARCHAR(255),
workflow_type VARCHAR(50),
is_active BOOLEAN DEFAULT FALSE,
last_executed_at TIMESTAMP,
execution_count INTEGER DEFAULT 0,
success_count INTEGER DEFAULT 0,
failure_count INTEGER DEFAULT 0,
avg_duration_ms INTEGER,
has_schedule BOOLEAN DEFAULT FALSE,
has_webhook BOOLEAN DEFAULT FALSE,
idle_days INTEGER,
suggestion VARCHAR(100),
checked_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_monitor_workflows_id ON monitor_workflows(workflow_id);
CREATE INDEX idx_monitor_workflows_active ON monitor_workflows(is_active);
CREATE INDEX idx_monitor_workflows_idle ON monitor_workflows(idle_days);
-- ============================================================
-- Layer 4: WordPress Portal 監控
-- ============================================================
CREATE TABLE IF NOT EXISTS monitor_portal_pages (
id SERIAL PRIMARY KEY,
page_url VARCHAR(500) NOT NULL,
page_type VARCHAR(20),
is_accessible BOOLEAN,
response_time_ms INTEGER,
http_status INTEGER,
error_message TEXT,
checked_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS monitor_portal_users (
id SERIAL PRIMARY KEY,
user_id BIGINT,
username VARCHAR(100),
email VARCHAR(255),
role VARCHAR(50),
is_active BOOLEAN,
last_login TIMESTAMP,
created_at TIMESTAMP,
detected_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_monitor_portal_pages_url ON monitor_portal_pages(page_url);
CREATE INDEX idx_monitor_portal_users_username ON monitor_portal_users(username);
-- ============================================================
-- Layer 5: Database 監控
-- ============================================================
CREATE TABLE IF NOT EXISTS monitor_databases (
id SERIAL PRIMARY KEY,
db_type VARCHAR(20) NOT NULL CHECK (db_type IN ('postgresql', 'redis', 'qdrant', 'mariadb', 'mongodb')),
db_name VARCHAR(50),
metric_name VARCHAR(50) NOT NULL,
metric_value JSONB,
checked_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_monitor_databases_type ON monitor_databases(db_type);
CREATE INDEX idx_monitor_databases_time ON monitor_databases(checked_at);
-- PostgreSQL 表結構快照
CREATE TABLE IF NOT EXISTS monitor_pg_tables (
id SERIAL PRIMARY KEY,
database_name VARCHAR(50),
schema_name VARCHAR(50),
table_name VARCHAR(100),
table_type VARCHAR(20),
row_count BIGINT,
table_size_bytes BIGINT,
index_size_bytes BIGINT,
snapshot_at TIMESTAMP DEFAULT NOW()
);
-- 表結構變更記錄
CREATE TABLE IF NOT EXISTS monitor_pg_schema_changes (
id SERIAL PRIMARY KEY,
database_name VARCHAR(50),
schema_name VARCHAR(50),
table_name VARCHAR(100),
change_type VARCHAR(20) CHECK (change_type IN ('table_created', 'table_dropped', 'column_added', 'column_removed', 'column_type_changed')),
column_name VARCHAR(100),
old_value TEXT,
new_value TEXT,
detected_at TIMESTAMP DEFAULT NOW()
);
-- Qdrant Collection 監控
CREATE TABLE IF NOT EXISTS monitor_qdrant_collections (
id SERIAL PRIMARY KEY,
collection_name VARCHAR(100),
vectors_count BIGINT,
points_count BIGINT,
disk_size_bytes BIGINT,
status VARCHAR(20),
snapshot_at TIMESTAMP DEFAULT NOW()
);
-- ============================================================
-- Layer 6: 使用者監控
-- ============================================================
-- 連線會話追蹤
CREATE TABLE IF NOT EXISTS monitor_sessions (
id SERIAL PRIMARY KEY,
session_type VARCHAR(20) CHECK (session_type IN ('ssh', 'web', 'db', 'sftp', 'rdp')),
service_name VARCHAR(50),
username VARCHAR(100),
source_ip VARCHAR(45),
source_port INTEGER,
connected_at TIMESTAMP,
last_activity_at TIMESTAMP,
disconnected_at TIMESTAMP,
bytes_sent BIGINT,
bytes_received BIGINT,
status VARCHAR(20) CHECK (status IN ('active', 'disconnected', 'timeout'))
);
-- 登入歷史
CREATE TABLE IF NOT EXISTS monitor_logins (
id SERIAL PRIMARY KEY,
user_type VARCHAR(20) CHECK (user_type IN ('system', 'wordpress', 'n8n', 'gitea', 'sftpgo', 'database')),
username VARCHAR(100),
source_ip VARCHAR(45),
user_agent TEXT,
login_method VARCHAR(20),
success BOOLEAN,
failure_reason VARCHAR(200),
login_at TIMESTAMP DEFAULT NOW()
);
-- sudo 命令記錄
CREATE TABLE IF NOT EXISTS monitor_sudo_history (
id SERIAL PRIMARY KEY,
username VARCHAR(100),
command TEXT,
run_as VARCHAR(100),
tty VARCHAR(50),
source_ip VARCHAR(45),
exit_code INTEGER,
executed_at TIMESTAMP DEFAULT NOW()
);
-- 資源使用追蹤
CREATE TABLE IF NOT EXISTS monitor_resource_usage (
id SERIAL PRIMARY KEY,
user_type VARCHAR(20),
username VARCHAR(100),
service_name VARCHAR(50),
cpu_percent DECIMAL(5,2),
memory_mb INTEGER,
disk_io_read_mb BIGINT,
disk_io_write_mb BIGINT,
network_rx_mb BIGINT,
network_tx_mb BIGINT,
recorded_at TIMESTAMP DEFAULT NOW()
);
-- 異常檢測記錄
CREATE TABLE IF NOT EXISTS monitor_anomalies (
id SERIAL PRIMARY KEY,
anomaly_type VARCHAR(50) CHECK (anomaly_type IN ('brute_force', 'privilege_escalation', 'unusual_access', 'unusual_time', 'excessive_queries', 'idle_session', 'schema_change')),
severity VARCHAR(20) CHECK (severity IN ('low', 'medium', 'high', 'critical')),
source_type VARCHAR(20),
username VARCHAR(100),
source_ip VARCHAR(45),
description TEXT,
details JSONB,
detected_at TIMESTAMP DEFAULT NOW(),
resolved BOOLEAN DEFAULT FALSE,
resolved_at TIMESTAMP
);
CREATE INDEX idx_monitor_sessions_type ON monitor_sessions(session_type);
CREATE INDEX idx_monitor_sessions_username ON monitor_sessions(username);
CREATE INDEX idx_monitor_logins_type ON monitor_logins(user_type);
CREATE INDEX idx_monitor_logins_time ON monitor_logins(login_at);
CREATE INDEX idx_monitor_anomalies_type ON monitor_anomalies(anomaly_type);
CREATE INDEX idx_monitor_anomalies_severity ON monitor_anomalies(severity);
CREATE INDEX idx_monitor_anomalies_time ON monitor_anomalies(detected_at);
-- ============================================================
-- Layer 7: Storage 監控
-- ============================================================
-- 檔案註冊表
CREATE TABLE IF NOT EXISTS file_registry (
file_uuid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
file_name VARCHAR(255) NOT NULL,
file_path TEXT NOT NULL,
file_path_hash VARCHAR(64) NOT NULL,
file_size BIGINT NOT NULL,
file_hash VARCHAR(64),
mime_type VARCHAR(100),
user_cluster VARCHAR(50) CHECK (user_cluster IN ('family', 'work', 'wordpress', 'shared', 'system')),
owner_id VARCHAR(100),
storage_tier VARCHAR(20) DEFAULT 'hot' CHECK (storage_tier IN ('hot', 'warm', 'cold')),
storage_location VARCHAR(500),
status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'temporary', 'archived', 'deleted')),
is_registered BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
last_accessed_at TIMESTAMP,
access_count INTEGER DEFAULT 0,
archived_at TIMESTAMP,
archive_location VARCHAR(500),
retention_until TIMESTAMP,
UNIQUE(file_path_hash)
);
-- 存儲使用統計
CREATE TABLE IF NOT EXISTS storage_usage_stats (
id SERIAL PRIMARY KEY,
user_cluster VARCHAR(50),
storage_tier VARCHAR(20),
file_count BIGINT,
total_size_bytes BIGINT,
record_time TIMESTAMP DEFAULT NOW()
);
-- 文件訪問日誌
CREATE TABLE IF NOT EXISTS storage_access_logs (
id SERIAL PRIMARY KEY,
user_cluster VARCHAR(50),
owner_id VARCHAR(100),
file_path TEXT,
access_type VARCHAR(20) CHECK (access_type IN ('read', 'write', 'delete', 'download', 'move')),
access_time TIMESTAMP DEFAULT NOW(),
client_ip VARCHAR(45),
access_method VARCHAR(20)
);
-- 文件生命週期
CREATE TABLE IF NOT EXISTS file_lifecycle (
id SERIAL PRIMARY KEY,
file_uuid UUID REFERENCES file_registry(file_uuid),
file_path TEXT,
user_cluster VARCHAR(50),
storage_tier VARCHAR(20),
created_at TIMESTAMP,
last_accessed_at TIMESTAMP,
last_modified_at TIMESTAMP,
access_count INTEGER DEFAULT 0,
current_status VARCHAR(20) DEFAULT 'active',
tier_migration_count INTEGER DEFAULT 0,
migrated_at TIMESTAMP
);
CREATE INDEX idx_file_registry_cluster ON file_registry(user_cluster);
CREATE INDEX idx_file_registry_tier ON file_registry(storage_tier);
CREATE INDEX idx_file_registry_status ON file_registry(status);
CREATE INDEX idx_storage_usage_cluster ON storage_usage_stats(user_cluster);
CREATE INDEX idx_storage_usage_time ON storage_usage_stats(record_time);
-- ============================================================
-- 外部監控 (Layer 1)
-- ============================================================
CREATE TABLE IF NOT EXISTS monitor_external (
id SERIAL PRIMARY KEY,
target_name VARCHAR(50) NOT NULL,
target_type VARCHAR(20) CHECK (target_type IN ('ddns', 'gateway', 'internet', 'api')),
target_host VARCHAR(255),
is_reachable BOOLEAN,
response_time_ms INTEGER,
dns_resolved_ip VARCHAR(45),
error_message TEXT,
checked_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_monitor_external_name ON monitor_external(target_name);
CREATE INDEX idx_monitor_external_time ON monitor_external(checked_at);
-- ============================================================
-- 監控配置表
-- ============================================================
CREATE TABLE IF NOT EXISTS monitor_config (
id SERIAL PRIMARY KEY,
config_key VARCHAR(50) UNIQUE NOT NULL,
config_value TEXT,
description VARCHAR(255),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 插入默認配置
INSERT INTO monitor_config (config_key, config_value, description) VALUES
('check_interval', '300', '監控檢查間隔(秒)'),
('retention_days', '30', '歷史數據保留天數'),
('idle_threshold_days', '30', 'Workflow 閒置天數閾值'),
('alert_threshold_bruteforce', '5', '暴力破解嘗試次數閾值'),
('alert_threshold_slow_response', '3000', '響應時間閾值(毫秒)')
ON CONFLICT (config_key) DO NOTHING;
-- ============================================================
-- 視圖定義
-- ============================================================
-- 服務健康狀態視圖
CREATE OR REPLACE VIEW v_service_health AS
SELECT
service_name,
status,
COUNT(*) as check_count,
COUNT(*) FILTER (WHERE status = 'up') as up_count,
COUNT(*) FILTER (WHERE status = 'down') as down_count,
AVG(response_time_ms) as avg_response_time,
MAX(checked_at) as last_check
FROM monitor_services
WHERE checked_at > NOW() - INTERVAL '24 hours'
GROUP BY service_name, status;
-- 最近異常視圖
CREATE OR REPLACE VIEW v_recent_anomalies AS
SELECT
anomaly_type,
severity,
username,
source_ip,
description,
detected_at
FROM monitor_anomalies
WHERE detected_at > NOW() - INTERVAL '24 hours'
ORDER BY detected_at DESC;
-- 閒置 Workflow 視圖
CREATE OR REPLACE VIEW v_idle_workflows AS
SELECT
workflow_name,
idle_days,
suggestion,
last_executed_at
FROM monitor_workflows
WHERE idle_days > 30 AND is_active = TRUE
ORDER BY idle_days DESC;
-- 存儲使用概況視圖
CREATE OR REPLACE VIEW v_storage_overview AS
SELECT
user_cluster,
storage_tier,
COUNT(*) as file_count,
SUM(file_size) as total_size
FROM file_registry
WHERE status = 'active'
GROUP BY user_cluster, storage_tier;
-- ============================================================
-- 備份監控 (Layer 7 Extension)
-- ============================================================
-- 備份註冊表
CREATE TABLE IF NOT EXISTS backup_registry (
id SERIAL PRIMARY KEY,
service_name VARCHAR(50) NOT NULL,
backup_file VARCHAR(500) NOT NULL,
backup_size_bytes BIGINT,
backup_type VARCHAR(20) CHECK (backup_type IN ('daily', 'weekly', 'monthly', 'archive', 'full', 'incremental')),
backup_method VARCHAR(20) CHECK (backup_method IN ('pg_dump', 'mysqldump', 'tar', 'snapshot', 'dump')),
status VARCHAR(20) CHECK (status IN ('pending', 'running', 'completed', 'failed', 'verified')),
compression_ratio DECIMAL(5,2),
verification_result BOOLEAN,
error_message TEXT,
started_at TIMESTAMP DEFAULT NOW(),
completed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
-- 備份存儲統計
CREATE TABLE IF NOT EXISTS backup_storage_stats (
id SERIAL PRIMARY KEY,
tier VARCHAR(20) CHECK (tier IN ('daily', 'weekly', 'monthly', 'archive', 'total')),
file_count BIGINT,
total_size_bytes BIGINT,
record_time TIMESTAMP DEFAULT NOW()
);
-- 備份歷史
CREATE TABLE IF NOT EXISTS backup_history (
id SERIAL PRIMARY KEY,
service_name VARCHAR(50) NOT NULL,
operation VARCHAR(20) CHECK (operation IN ('backup', 'restore', 'tier_migration', 'cleanup', 'verify')),
backup_file VARCHAR(500),
backup_tier VARCHAR(20),
source_tier VARCHAR(20),
dest_tier VARCHAR(20),
file_count BIGINT,
size_bytes BIGINT,
duration_seconds INTEGER,
status VARCHAR(20) CHECK (status IN ('success', 'failed', 'partial')),
error_message TEXT,
executed_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_backup_registry_service ON backup_registry(service_name);
CREATE INDEX idx_backup_registry_time ON backup_registry(created_at);
CREATE INDEX idx_backup_storage_stats_tier ON backup_storage_stats(tier);
CREATE INDEX idx_backup_storage_stats_time ON backup_storage_stats(record_time);
CREATE INDEX idx_backup_history_service ON backup_history(service_name);
CREATE INDEX idx_backup_history_time ON backup_history(executed_at);
-- ============================================================
-- Node.js 版本基線監控
-- ============================================================
CREATE TABLE IF NOT EXISTS node_version_baseline (
id SERIAL PRIMARY KEY,
runtime_name VARCHAR(50) NOT NULL,
required_version VARCHAR(20) NOT NULL,
current_version VARCHAR(20),
process_name VARCHAR(100),
process_path TEXT,
is_compliant BOOLEAN,
locked_path VARCHAR(500),
checked_at TIMESTAMP DEFAULT NOW()
);
-- Node.js 進程追蹤
CREATE TABLE IF NOT EXISTS node_process_tracking (
id SERIAL PRIMARY KEY,
process_name VARCHAR(100) NOT NULL,
pid INTEGER,
command VARCHAR(500),
node_version VARCHAR(20),
is_managed BOOLEAN DEFAULT FALSE,
started_at TIMESTAMP,
checked_at TIMESTAMP DEFAULT NOW()
);
-- ============================================================
-- Python 版本基線監控
-- ============================================================
CREATE TABLE IF NOT EXISTS python_version_baseline (
id SERIAL PRIMARY KEY,
runtime_name VARCHAR(50) NOT NULL,
required_version VARCHAR(20) NOT NULL,
current_version VARCHAR(20),
interpreter_path VARCHAR(500),
is_compliant BOOLEAN,
checked_at TIMESTAMP DEFAULT NOW()
);
-- Python 腳本追蹤
CREATE TABLE IF NOT EXISTS python_script_tracking (
id SERIAL PRIMARY KEY,
script_path TEXT NOT NULL,
shebang_version VARCHAR(20),
actual_version VARCHAR(20),
is_compliant BOOLEAN DEFAULT FALSE,
last_run_at TIMESTAMP,
exit_code INTEGER,
error_output TEXT,
checked_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_node_version_name ON node_version_baseline(runtime_name);
CREATE INDEX idx_node_process_name ON node_process_tracking(process_name);
CREATE INDEX idx_python_version_name ON python_version_baseline(runtime_name);
CREATE INDEX idx_python_script_path ON python_script_tracking(script_path);