- 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
323 lines
8.5 KiB
Bash
Executable File
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}"
|