#!/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 "$@"