mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-18 12:49:40 +02:00
📈 feat(monitoring): upgrade to VictoriaMetrics + DuckDB analytics
- Replace Prometheus with VictoriaMetrics (2-year retention) - Add DuckDB analytics module for business KPIs (unlimited retention) - Add master overview dashboard combining all metrics - Add business metrics dashboard for user growth tracking - Add backup script for VictoriaMetrics snapshots and DuckDB - Add ADR documentation for monitoring stack decision Analytics API endpoints: - GET /api/v1/analytics/health - Service health - GET /api/v1/analytics/latest - Latest metrics snapshot - GET /api/v1/analytics/growth - User growth over time - GET /api/v1/analytics/monthly - Monthly aggregates - POST /api/v1/analytics/snapshot - Manual snapshot trigger
This commit is contained in:
parent
2e7378710f
commit
9dfad0128a
17 changed files with 2901 additions and 18 deletions
130
scripts/backup-monitoring.sh
Executable file
130
scripts/backup-monitoring.sh
Executable file
|
|
@ -0,0 +1,130 @@
|
|||
#!/bin/bash
|
||||
# Backup script for ManaCore Monitoring Stack
|
||||
# - VictoriaMetrics (2 years of metrics)
|
||||
# - DuckDB (Business KPIs)
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
BACKUP_DIR="${BACKUP_DIR:-/backup/monitoring}"
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
RETENTION_DAYS="${RETENTION_DAYS:-30}" # Keep backups for 30 days
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# Create backup directory
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# ============================================
|
||||
# Backup VictoriaMetrics
|
||||
# ============================================
|
||||
backup_victoriametrics() {
|
||||
log_info "Creating VictoriaMetrics snapshot..."
|
||||
|
||||
# Create snapshot via API
|
||||
SNAPSHOT_RESPONSE=$(curl -s -X POST "http://localhost:8428/snapshot/create")
|
||||
SNAPSHOT_NAME=$(echo "$SNAPSHOT_RESPONSE" | grep -o '"snapshot":"[^"]*"' | cut -d'"' -f4)
|
||||
|
||||
if [ -z "$SNAPSHOT_NAME" ]; then
|
||||
log_error "Failed to create VictoriaMetrics snapshot"
|
||||
echo "$SNAPSHOT_RESPONSE"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "Snapshot created: $SNAPSHOT_NAME"
|
||||
|
||||
# Copy snapshot to backup directory
|
||||
# Note: Adjust path based on your volume mount
|
||||
VM_DATA_PATH="/var/lib/docker/volumes/manacore-victoriametrics/_data"
|
||||
SNAPSHOT_PATH="$VM_DATA_PATH/snapshots/$SNAPSHOT_NAME"
|
||||
|
||||
if [ -d "$SNAPSHOT_PATH" ]; then
|
||||
BACKUP_FILE="$BACKUP_DIR/victoriametrics-$DATE.tar.gz"
|
||||
log_info "Compressing snapshot to $BACKUP_FILE..."
|
||||
tar -czf "$BACKUP_FILE" -C "$VM_DATA_PATH/snapshots" "$SNAPSHOT_NAME"
|
||||
log_info "VictoriaMetrics backup complete: $BACKUP_FILE"
|
||||
|
||||
# Delete snapshot after backup
|
||||
curl -s -X POST "http://localhost:8428/snapshot/delete?snapshot=$SNAPSHOT_NAME"
|
||||
log_info "Snapshot deleted from VictoriaMetrics"
|
||||
else
|
||||
log_warn "Snapshot directory not found at $SNAPSHOT_PATH"
|
||||
log_warn "If using Docker, you may need to run this inside the container"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Backup DuckDB
|
||||
# ============================================
|
||||
backup_duckdb() {
|
||||
log_info "Backing up DuckDB analytics database..."
|
||||
|
||||
# DuckDB is a single file, so we can just copy it
|
||||
DUCKDB_PATH="/var/lib/docker/volumes/manacore-analytics/_data/metrics.duckdb"
|
||||
|
||||
if [ -f "$DUCKDB_PATH" ]; then
|
||||
BACKUP_FILE="$BACKUP_DIR/analytics-$DATE.duckdb"
|
||||
cp "$DUCKDB_PATH" "$BACKUP_FILE"
|
||||
log_info "DuckDB backup complete: $BACKUP_FILE"
|
||||
|
||||
# Also export to Parquet for long-term archival
|
||||
PARQUET_FILE="$BACKUP_DIR/analytics-$DATE.parquet"
|
||||
if command -v duckdb &> /dev/null; then
|
||||
duckdb "$DUCKDB_PATH" -c "COPY daily_metrics TO '$PARQUET_FILE' (FORMAT PARQUET)"
|
||||
log_info "Parquet export complete: $PARQUET_FILE"
|
||||
else
|
||||
log_warn "duckdb CLI not found, skipping Parquet export"
|
||||
fi
|
||||
else
|
||||
log_warn "DuckDB file not found at $DUCKDB_PATH"
|
||||
|
||||
# Try alternative: backup via API
|
||||
log_info "Attempting backup via API..."
|
||||
curl -s "http://localhost:3001/api/analytics/latest" > "$BACKUP_DIR/analytics-latest-$DATE.json"
|
||||
curl -s "http://localhost:3001/api/analytics/growth?days=365" > "$BACKUP_DIR/analytics-growth-$DATE.json"
|
||||
log_info "API backup complete"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Cleanup old backups
|
||||
# ============================================
|
||||
cleanup_old_backups() {
|
||||
log_info "Cleaning up backups older than $RETENTION_DAYS days..."
|
||||
find "$BACKUP_DIR" -type f -mtime +$RETENTION_DAYS -delete
|
||||
log_info "Cleanup complete"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Main
|
||||
# ============================================
|
||||
main() {
|
||||
log_info "Starting ManaCore Monitoring Backup"
|
||||
log_info "Backup directory: $BACKUP_DIR"
|
||||
log_info "Date: $DATE"
|
||||
echo ""
|
||||
|
||||
backup_victoriametrics
|
||||
echo ""
|
||||
|
||||
backup_duckdb
|
||||
echo ""
|
||||
|
||||
cleanup_old_backups
|
||||
echo ""
|
||||
|
||||
log_info "All backups complete!"
|
||||
log_info "Files in $BACKUP_DIR:"
|
||||
ls -lh "$BACKUP_DIR"
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
|
|
@ -607,6 +607,30 @@ const APP_CONFIGS = [
|
|||
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.TECHBASE_BACKEND_PORT || '3021'}`,
|
||||
},
|
||||
},
|
||||
|
||||
// Zitare Telegram Bot
|
||||
{
|
||||
path: 'services/telegram-zitare-bot/.env',
|
||||
vars: {
|
||||
NODE_ENV: () => 'development',
|
||||
PORT: (env) => env.ZITARE_BOT_PORT || '3303',
|
||||
TELEGRAM_BOT_TOKEN: (env) => env.ZITARE_BOT_TELEGRAM_TOKEN,
|
||||
DATABASE_URL: (env) => env.ZITARE_BOT_DATABASE_URL,
|
||||
},
|
||||
},
|
||||
|
||||
// Todo Telegram Bot
|
||||
{
|
||||
path: 'services/telegram-todo-bot/.env',
|
||||
vars: {
|
||||
NODE_ENV: () => 'development',
|
||||
PORT: (env) => env.TODO_BOT_PORT || '3304',
|
||||
TELEGRAM_BOT_TOKEN: (env) => env.TODO_BOT_TELEGRAM_TOKEN,
|
||||
DATABASE_URL: (env) => env.TODO_BOT_DATABASE_URL,
|
||||
TODO_API_URL: (env) => env.TODO_BOT_API_URL || 'http://localhost:3018',
|
||||
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
function main() {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ ALL_DATABASES=(
|
|||
"planta"
|
||||
"nutriphi"
|
||||
"projectdoc"
|
||||
"zitare_bot"
|
||||
"todo_bot"
|
||||
"nutriphi_bot"
|
||||
)
|
||||
|
||||
# Check if specific service requested
|
||||
|
|
@ -160,9 +163,21 @@ setup_service() {
|
|||
create_db_if_not_exists "projectdoc"
|
||||
push_schema "@manacore/telegram-project-doc-bot" "projectdoc"
|
||||
;;
|
||||
zitare_bot|zitare-bot)
|
||||
create_db_if_not_exists "zitare_bot"
|
||||
push_schema "@manacore/telegram-zitare-bot" "zitare-bot"
|
||||
;;
|
||||
todo_bot|todo-bot)
|
||||
create_db_if_not_exists "todo_bot"
|
||||
push_schema "@manacore/telegram-todo-bot" "todo-bot"
|
||||
;;
|
||||
nutriphi_bot|nutriphi-bot)
|
||||
create_db_if_not_exists "nutriphi_bot"
|
||||
push_schema "@manacore/telegram-nutriphi-bot" "nutriphi-bot"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Unknown service: $service${NC}"
|
||||
echo "Available services: auth, chat, zitare, contacts, calendar, clock, todo, manadeck, mail, moodlit, finance, voxel-lava, figgos, planta, nutriphi, presi, storage"
|
||||
echo "Available services: auth, chat, zitare, contacts, calendar, clock, todo, manadeck, mail, moodlit, finance, voxel-lava, figgos, planta, nutriphi, presi, storage, projectdoc, zitare_bot, todo_bot, nutriphi_bot"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue