Files
shell/examples/enhanced-plex-backup-with-metrics.sh
Peter Wood 6d726cb015 feat: Add base HTML template and implement dashboard, logs, and service views
- Created a base HTML template for consistent layout across pages.
- Developed a dashboard page to display backup service metrics and statuses.
- Implemented a log viewer for detailed log file inspection.
- Added error handling page for better user experience during failures.
- Introduced service detail page to show specific service metrics and actions.
- Enhanced log filtering and viewing capabilities.
- Integrated auto-refresh functionality for real-time updates on metrics.
- Created integration and unit test scripts for backup metrics functionality.
2025-06-18 08:06:08 -04:00

429 lines
15 KiB
Bash

#!/bin/bash
################################################################################
# Enhanced Plex Backup Script with Real-time JSON Metrics
################################################################################
#
# This example shows how to integrate the unified metrics system into the
# existing Plex backup script with minimal changes while maintaining
# backward compatibility with the current performance tracking system.
#
# Key Integration Points:
# 1. Initialize metrics at script start
# 2. Update status during key operations
# 3. Track file-by-file progress
# 4. Record performance phases
# 5. Complete session with final status
#
################################################################################
# Load the unified metrics library
source "$(dirname "$(readlink -f "$0")")/lib/unified-backup-metrics.sh"
# Original script variables (unchanged)
BACKUP_ROOT="/mnt/share/media/backups/plex"
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
LOCAL_LOG_ROOT="${SCRIPT_DIR}/logs"
PERFORMANCE_LOG_FILE="${LOCAL_LOG_ROOT}/plex-backup-performance.json"
# Original Plex files configuration (unchanged)
declare -A PLEX_FILES=(
["database"]="/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db"
["blobs"]="/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.blobs.db"
["preferences"]="/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Preferences.xml"
)
# Colors (unchanged)
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Original logging functions (unchanged - metrics run in parallel)
log_message() {
local message="$1"
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo -e "${BLUE}[${timestamp}]${NC} ${message}"
mkdir -p "$LOCAL_LOG_ROOT"
echo "[${timestamp}] $message" >> "${LOCAL_LOG_ROOT}/plex-backup-$(date '+%Y-%m-%d').log" 2>/dev/null || true
}
log_success() {
local message="$1"
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo -e "${GREEN}[${timestamp}] SUCCESS:${NC} ${message}"
mkdir -p "$LOCAL_LOG_ROOT"
echo "[${timestamp}] SUCCESS: $message" >> "${LOCAL_LOG_ROOT}/plex-backup-$(date '+%Y-%m-%d').log" 2>/dev/null || true
}
log_error() {
local message="$1"
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo -e "${RED}[${timestamp}] ERROR:${NC} ${message}"
mkdir -p "$LOCAL_LOG_ROOT"
echo "[${timestamp}] ERROR: $message" >> "${LOCAL_LOG_ROOT}/plex-backup-$(date '+%Y-%m-%d').log" 2>/dev/null || true
}
log_warning() {
local message="$1"
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo -e "${YELLOW}[${timestamp}] WARNING:${NC} ${message}"
mkdir -p "$LOCAL_LOG_ROOT"
echo "[${timestamp}] WARNING: $message" >> "${LOCAL_LOG_ROOT}/plex-backup-$(date '+%Y-%m-%d').log" 2>/dev/null || true
}
# Original performance tracking function (unchanged - metrics system integrates)
track_performance() {
local operation="$1"
local start_time="$2"
local end_time="${3:-$(date +%s)}"
local duration=$((end_time - start_time))
# Initialize performance log if it doesn't exist
if [ ! -f "$PERFORMANCE_LOG_FILE" ]; then
mkdir -p "$(dirname "$PERFORMANCE_LOG_FILE")"
echo "[]" > "$PERFORMANCE_LOG_FILE"
fi
# Add performance entry
local entry
entry=$(jq -n \
--arg operation "$operation" \
--arg duration "$duration" \
--arg timestamp "$(date -Iseconds)" \
'{
operation: $operation,
duration_seconds: ($duration | tonumber),
timestamp: $timestamp
}')
jq --argjson entry "$entry" '. += [$entry]' "$PERFORMANCE_LOG_FILE" > "${PERFORMANCE_LOG_FILE}.tmp" && \
mv "${PERFORMANCE_LOG_FILE}.tmp" "$PERFORMANCE_LOG_FILE"
log_message "Performance: $operation completed in ${duration}s"
}
# Enhanced service management with metrics integration
manage_plex_service() {
local action="$1"
local operation_start
operation_start=$(date +%s)
log_message "Managing Plex service: $action"
# Update metrics status
metrics_update_status "running" "${action}_service"
case "$action" in
stop)
if sudo systemctl stop plexmediaserver.service; then
log_success "Plex service stopped"
# Wait for clean shutdown with progress indicator
local wait_time=0
local max_wait=15
while [ $wait_time -lt $max_wait ]; do
if ! sudo systemctl is-active --quiet plexmediaserver.service; then
log_success "Plex service confirmed stopped (${wait_time}s)"
# Track performance in both systems
track_performance "service_stop" "$operation_start"
metrics_time_phase "service_stop" "$operation_start"
return 0
fi
sleep 1
wait_time=$((wait_time + 1))
echo -n "."
done
echo
log_warning "Plex service may not have stopped cleanly after ${max_wait}s"
metrics_warning "Service stop took longer than expected (${max_wait}s)"
return 1
else
log_error "Failed to stop Plex service"
metrics_error "Failed to stop Plex service"
return 1
fi
;;
start)
if sudo systemctl start plexmediaserver.service; then
log_success "Plex service start command issued"
# Wait for service to be fully running with progress indicator
local wait_time=0
local max_wait=30
while [ $wait_time -lt $max_wait ]; do
if sudo systemctl is-active --quiet plexmediaserver.service; then
log_success "Plex service confirmed running (${wait_time}s)"
# Track performance in both systems
track_performance "service_start" "$operation_start"
metrics_time_phase "service_start" "$operation_start"
return 0
fi
sleep 1
wait_time=$((wait_time + 1))
echo -n "."
done
echo
log_error "Plex service failed to start within ${max_wait}s"
metrics_error "Service failed to start within ${max_wait}s"
return 1
else
log_error "Failed to start Plex service"
metrics_error "Failed to start Plex service"
return 1
fi
;;
*)
log_error "Invalid service action: $action"
metrics_error "Invalid service action: $action"
return 1
;;
esac
}
# Enhanced backup copy with file-by-file tracking
backup_file_with_metrics() {
local nickname="$1"
local source_file="$2"
local backup_file="$3"
log_message "Backing up $(basename "$source_file")..."
if [ ! -f "$source_file" ]; then
log_warning "File not found: $source_file"
metrics_add_file "$source_file" "skipped" "0" "" "File not found"
return 1
fi
# Get source file size for metrics
local file_size
file_size=$(stat -c%s "$source_file" 2>/dev/null || echo "0")
# Copy file
if cp "$source_file" "$backup_file"; then
# Verify the copy
if [ -f "$backup_file" ]; then
# Calculate checksum for verification
local checksum
checksum=$(md5sum "$backup_file" 2>/dev/null | cut -d' ' -f1 || echo "")
log_success "Backed up: $(basename "$source_file") (${file_size} bytes)"
metrics_add_file "$source_file" "success" "$file_size" "$checksum"
return 0
else
log_error "Verification failed: $(basename "$source_file")"
metrics_add_file "$source_file" "failed" "0" "" "Verification failed after copy"
return 1
fi
else
log_error "Failed to copy: $(basename "$source_file")"
metrics_add_file "$source_file" "failed" "0" "" "Copy operation failed"
return 1
fi
}
# Main backup function with metrics integration
main() {
local overall_start
overall_start=$(date +%s)
log_message "Starting enhanced Plex backup process at $(date)"
# Initialize metrics system
local session_id="plex_backup_$(date +%Y%m%d_%H%M%S)"
if ! metrics_init "plex" "$BACKUP_ROOT" "$session_id"; then
log_warning "JSON metrics initialization failed, continuing with legacy tracking only"
local metrics_enabled=false
else
local metrics_enabled=true
log_message "JSON metrics enabled - session: $session_id"
# Set total files count for progress tracking
metrics_set_total_files "${#PLEX_FILES[@]}" "0"
# Start the backup session
metrics_start_backup
fi
# Create necessary directories
mkdir -p "${BACKUP_ROOT}"
mkdir -p "${LOCAL_LOG_ROOT}"
local backup_errors=0
local files_backed_up=0
local backed_up_files=()
local BACKUP_PATH="${BACKUP_ROOT}"
# Ensure backup root directory exists
mkdir -p "$BACKUP_PATH"
# Update status: stopping service
if [ "$metrics_enabled" = true ]; then
metrics_update_status "running" "stopping_service"
fi
# Stop Plex service
if ! manage_plex_service stop; then
log_error "Failed to stop Plex service, aborting backup"
if [ "$metrics_enabled" = true ]; then
metrics_complete_backup "failed" "Failed to stop Plex service"
fi
exit 1
fi
# Update status: starting backup phase
if [ "$metrics_enabled" = true ]; then
metrics_update_status "running" "backing_up_files"
fi
# Backup files with individual file tracking
local backup_phase_start
backup_phase_start=$(date +%s)
for nickname in "${!PLEX_FILES[@]}"; do
local file="${PLEX_FILES[$nickname]}"
local backup_file="${BACKUP_PATH}/$(basename "$file")"
if backup_file_with_metrics "$nickname" "$file" "$backup_file"; then
files_backed_up=$((files_backed_up + 1))
# Add friendly filename to backed up files list
case "$(basename "$file")" in
"com.plexapp.plugins.library.db") backed_up_files+=("library.db") ;;
"com.plexapp.plugins.library.blobs.db") backed_up_files+=("blobs.db") ;;
"Preferences.xml") backed_up_files+=("Preferences.xml") ;;
*) backed_up_files+=("$(basename "$file")") ;;
esac
else
backup_errors=$((backup_errors + 1))
fi
done
# Track backup phase performance
track_performance "backup" "$backup_phase_start"
if [ "$metrics_enabled" = true ]; then
metrics_time_phase "backup" "$backup_phase_start"
fi
# Update status: creating archive
if [ "$metrics_enabled" = true ]; then
metrics_update_status "running" "creating_archive"
fi
# Create archive if files were backed up
local archive_created=false
if [ "$files_backed_up" -gt 0 ]; then
local compression_start
compression_start=$(date +%s)
local archive_name="plex-backup-$(date +%Y%m%d_%H%M%S).tar.gz"
local archive_path="${BACKUP_ROOT}/${archive_name}"
log_message "Creating compressed archive: $archive_name"
if cd "$BACKUP_PATH" && tar -czf "$archive_path" *.db *.xml 2>/dev/null; then
log_success "Created archive: $archive_name"
archive_created=true
# Track compression performance
track_performance "compression" "$compression_start"
if [ "$metrics_enabled" = true ]; then
metrics_time_phase "compression" "$compression_start"
fi
# Clean up individual files after successful archive creation
rm -f "$BACKUP_PATH"/*.db "$BACKUP_PATH"/*.xml 2>/dev/null || true
# Get archive information for metrics
if [ "$metrics_enabled" = true ]; then
local archive_size
archive_size=$(stat -c%s "$archive_path" 2>/dev/null || echo "0")
local archive_checksum
archive_checksum=$(md5sum "$archive_path" 2>/dev/null | cut -d' ' -f1 || echo "")
metrics_add_file "$archive_path" "success" "$archive_size" "$archive_checksum"
fi
else
log_error "Failed to create archive"
backup_errors=$((backup_errors + 1))
if [ "$metrics_enabled" = true ]; then
metrics_error "Failed to create compressed archive"
fi
fi
fi
# Update status: starting service
if [ "$metrics_enabled" = true ]; then
metrics_update_status "running" "starting_service"
fi
# Start Plex service
manage_plex_service start
# Update status: cleaning up
if [ "$metrics_enabled" = true ]; then
metrics_update_status "running" "cleaning_up"
fi
# Cleanup old backups
local cleanup_start
cleanup_start=$(date +%s)
log_message "Cleaning up old backups..."
# [Original cleanup logic here - unchanged]
track_performance "cleanup" "$cleanup_start"
if [ "$metrics_enabled" = true ]; then
metrics_time_phase "cleanup" "$cleanup_start"
fi
# Track overall backup performance
track_performance "total_script" "$overall_start"
# Final summary
local total_time=$(($(date +%s) - overall_start))
log_message "Backup process completed at $(date)"
log_message "Total execution time: ${total_time}s"
log_message "Files backed up: $files_backed_up"
log_message "Errors encountered: $backup_errors"
# Complete metrics session
if [ "$metrics_enabled" = true ]; then
local final_status="success"
local completion_message="Backup completed successfully"
if [ "$backup_errors" -gt 0 ]; then
final_status="partial"
completion_message="Backup completed with $backup_errors errors"
elif [ "$files_backed_up" -eq 0 ]; then
final_status="failed"
completion_message="No files were backed up"
fi
metrics_complete_backup "$final_status" "$completion_message"
log_message "JSON metrics session completed: $session_id"
fi
# Exit with appropriate code
if [ "$backup_errors" -gt 0 ]; then
exit 1
else
exit 0
fi
}
# Run main function
main "$@"