Files
sf-cli-wrapper/sf-logs-tail
reynold 4020d881f1 fix: resolve sf-logs-tail utils.sh dependency by reorganizing directory structure
- Renamed misc/ directory to utils/ for better organization
- Updated sf-logs-tail to source utils/utils.sh correctly
- This fixes the 'No such file or directory' error when running sf-logs-tail
- The utils directory contains cross-platform timeout functions needed for macOS compatibility
2025-08-28 22:57:07 +08:00

323 lines
8.5 KiB
Bash
Executable File

#!/bin/bash
# Debug logs tail wrapper for Salesforce CLI
# Provides real-time debug log monitoring with filtering and formatting
# Source utilities for cross-platform compatibility
source "$(dirname "$0")/utils/utils.sh"
# Color codes for output formatting
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[0;33m'
readonly BLUE='\033[0;34m'
readonly CYAN='\033[0;36m'
readonly GRAY='\033[0;37m'
readonly MAGENTA='\033[0;35m'
readonly NC='\033[0m' # No Color
# Function to display usage information
show_usage() {
echo -e "${BLUE}sf-logs-tail - Debug Logs Tail Wrapper for Salesforce CLI${NC}"
echo ""
echo "USAGE:"
echo " sf-logs-tail [OPTIONS]"
echo ""
echo "OPTIONS:"
echo " -to Target org username or alias"
echo " -ui Specific user ID to monitor (default: current user)"
echo " -lv Log level: ERROR, WARN, INFO, DEBUG, FINE, FINER, FINEST"
echo " -dr How long to tail logs in minutes (default: 30)"
echo " -ft Filter log entries containing pattern"
echo " -ax Show only Apex-related log entries"
echo " -nc Disable colored output"
echo " -ve Enable verbose output with timestamps"
echo " -hp Show this help message"
echo ""
echo "EXAMPLES:"
echo " sf-logs-tail -to MYORG # Tail logs for specified org"
echo " sf-logs-tail -to MYORG -lv DEBUG -dr 60 # Debug level for 1 hour"
echo " sf-logs-tail -to MYORG -ft \"MyClass\" -ax # Filter Apex logs for MyClass"
echo " sf-logs-tail -to sandbox -ui USER123 # Specific org and user"
echo ""
echo "KEYBOARD SHORTCUTS:"
echo " Ctrl+C Stop tailing logs and exit"
echo ""
echo "This script automatically checks for Salesforce CLI installation."
}
# Function to check if Salesforce CLI is installed
check_salesforce_cli() {
if ! command -v sf &> /dev/null; then
return 1
fi
return 0
}
# Function to run sf-check diagnostics
run_salesforce_check() {
if [[ -f "sf-check" ]]; then
echo -e "${YELLOW}Running Salesforce CLI diagnostics...${NC}"
./sf-check
elif [[ -f "sf-check.sh" ]]; then
echo -e "${YELLOW}Running Salesforce CLI diagnostics...${NC}"
bash sf-check.sh
elif [[ -f "sf-check.ps1" ]]; then
echo -e "${YELLOW}Running Salesforce CLI diagnostics...${NC}"
pwsh sf-check.ps1
else
echo -e "${RED}Salesforce CLI not found and no diagnostic script available.${NC}"
echo -e "${RED}Please install the Salesforce CLI: https://developer.salesforce.com/tools/salesforcecli${NC}"
fi
}
# Function to colorize log level
colorize_log_level() {
local level="$1"
case "$level" in
*ERROR*) echo -e "${RED}$level${NC}" ;;
*WARN*) echo -e "${YELLOW}$level${NC}" ;;
*INFO*) echo -e "${GREEN}$level${NC}" ;;
*DEBUG*) echo -e "${CYAN}$level${NC}" ;;
*FINE*) echo -e "${BLUE}$level${NC}" ;;
*APEX*) echo -e "${MAGENTA}$level${NC}" ;;
*) echo "$level" ;;
esac
}
# Function to format log entry
format_log_entry() {
local line="$1"
local show_colors="$2"
local show_timestamp="$3"
if [[ "$show_colors" == true ]]; then
# Add timestamp if verbose
if [[ "$show_timestamp" == true ]]; then
local timestamp=$(date '+%H:%M:%S')
echo -e "${GRAY}[$timestamp]${NC} $line"
else
# Try to colorize based on content
if [[ "$line" =~ (ERROR|EXCEPTION|FATAL) ]]; then
echo -e "${RED}$line${NC}"
elif [[ "$line" =~ (WARN|WARNING) ]]; then
echo -e "${YELLOW}$line${NC}"
elif [[ "$line" =~ (DEBUG|FINE) ]]; then
echo -e "${CYAN}$line${NC}"
elif [[ "$line" =~ (APEX|USER_DEBUG) ]]; then
echo -e "${MAGENTA}$line${NC}"
else
echo "$line"
fi
fi
else
echo "$line"
fi
}
# Function to filter log entry
should_show_log_entry() {
local line="$1"
local filter_pattern="$2"
local apex_only="$3"
# Apply apex-only filter
if [[ "$apex_only" == true ]]; then
if [[ ! "$line" =~ (APEX|USER_DEBUG|EXCEPTION|METHOD_|CONSTRUCTOR_|DML_|SOQL_|VALIDATION_|FLOW_) ]]; then
return 1
fi
fi
# Apply custom filter
if [[ -n "$filter_pattern" ]]; then
if [[ ! "$line" =~ $filter_pattern ]]; then
return 1
fi
fi
return 0
}
# Function to setup signal handlers
setup_signal_handlers() {
trap 'echo -e "\n${YELLOW}Stopping log tail...${NC}"; exit 0' INT TERM
}
# Initialize variables
TARGET_ORG=""
USER_ID=""
LOG_LEVEL=""
DURATION="30"
FILTER_PATTERN=""
APEX_ONLY=false
NO_COLORS=false
VERBOSE=false
# Show help if no arguments provided
if [[ $# -eq 0 ]]; then
show_usage
exit 0
fi
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-to)
TARGET_ORG="$2"
shift 2
;;
-ui)
USER_ID="$2"
shift 2
;;
-lv)
LOG_LEVEL="$2"
shift 2
;;
-dr)
DURATION="$2"
shift 2
;;
-ft)
FILTER_PATTERN="$2"
shift 2
;;
-ax)
APEX_ONLY=true
shift
;;
-nc)
NO_COLORS=true
shift
;;
-ve)
VERBOSE=true
shift
;;
-hp)
show_usage
exit 0
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
echo ""
show_usage
exit 1
;;
esac
done
# Silently check for Salesforce CLI
if ! check_salesforce_cli; then
run_salesforce_check
exit 1
fi
# Validate log level if specified
if [[ -n "$LOG_LEVEL" ]]; then
case "$LOG_LEVEL" in
ERROR|WARN|INFO|DEBUG|FINE|FINER|FINEST) ;;
*)
echo -e "${RED}Error: Invalid log level '$LOG_LEVEL'${NC}"
echo -e "${YELLOW}Valid levels: ERROR, WARN, INFO, DEBUG, FINE, FINER, FINEST${NC}"
exit 1
;;
esac
fi
# Validate duration
if ! [[ "$DURATION" =~ ^[0-9]+$ ]]; then
echo -e "${RED}Error: Duration must be a number (minutes)${NC}"
exit 1
fi
# Build the sf command
SF_ARGS=("apex" "tail" "log")
# Add optional parameters
if [[ -n "$TARGET_ORG" ]]; then
SF_ARGS+=("--target-org" "$TARGET_ORG")
fi
if [[ -n "$USER_ID" ]]; then
SF_ARGS+=("--user-id" "$USER_ID")
fi
if [[ -n "$LOG_LEVEL" ]]; then
SF_ARGS+=("--debug-level" "$LOG_LEVEL")
fi
# Set up signal handlers
setup_signal_handlers
# Display log tail information
echo -e "${BLUE}📡 Starting Debug Log Tail${NC}"
echo -e "${BLUE}===========================${NC}"
if [[ -n "$TARGET_ORG" ]]; then
echo -e "${CYAN}Target org: $TARGET_ORG${NC}"
fi
if [[ -n "$USER_ID" ]]; then
echo -e "${CYAN}User ID: $USER_ID${NC}"
else
echo -e "${CYAN}User: Current user${NC}"
fi
if [[ -n "$LOG_LEVEL" ]]; then
echo -e "${CYAN}Log level: $(colorize_log_level "$LOG_LEVEL")${NC}"
fi
echo -e "${CYAN}Duration: $DURATION minutes${NC}"
if [[ -n "$FILTER_PATTERN" ]]; then
echo -e "${CYAN}Filter: $FILTER_PATTERN${NC}"
fi
if [[ "$APEX_ONLY" == true ]]; then
echo -e "${YELLOW}Mode: Apex-only logs${NC}"
fi
if [[ "$VERBOSE" == true ]]; then
echo -e "${YELLOW}Verbose: Enabled (with timestamps)${NC}"
fi
# Color settings
SHOW_COLORS=true
if [[ "$NO_COLORS" == true ]]; then
SHOW_COLORS=false
echo -e "${GRAY}Colors: Disabled${NC}"
fi
echo ""
echo -e "${YELLOW}Press Ctrl+C to stop tailing logs${NC}"
echo ""
# Display the command being run
if [[ "$VERBOSE" == true ]]; then
echo -e "${GRAY}Executing: sf ${SF_ARGS[*]}${NC}"
echo ""
fi
# Start the log tailing with timeout
portable_timeout "$DURATION" sf "${SF_ARGS[@]}" 2>/dev/null | while IFS= read -r line; do
if should_show_log_entry "$line" "$FILTER_PATTERN" "$APEX_ONLY"; then
format_log_entry "$line" "$SHOW_COLORS" "$VERBOSE"
fi
done
# Check the exit status
EXIT_CODE=${PIPESTATUS[0]}
echo ""
if [[ $EXIT_CODE -eq 124 ]]; then
echo -e "${YELLOW}⏰ Log tail timed out after $DURATION minutes${NC}"
elif [[ $EXIT_CODE -eq 0 ]]; then
echo -e "${GREEN}✅ Log tail completed successfully${NC}"
else
echo -e "${RED}❌ Log tail failed with exit code: $EXIT_CODE${NC}"
echo -e "${YELLOW}💡 Check org connectivity and user permissions${NC}"
fi
echo -e "${GRAY}Tip: Use different filters to focus on specific log types${NC}"