Sync all scripts from website downloads — 352 scripts total

Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
This commit is contained in:
2026-05-25 03:31:08 +02:00
parent dbd6bf0324
commit a1a17e81a1
332 changed files with 174509 additions and 1106 deletions
+726
View File
@@ -0,0 +1,726 @@
#! /bin/bash
#############################################################
#### Expose metrics from PCOIP for Prometheus ####
#### Redhat/Amazon/Ubuntu Workstations. ####
#### ####
#### Author: Phil Connor 03/27/2024 ####
#### Contact: contact@mylinux.work ####
#### Version 2.18.20250731 ####
#############################################################
# This script extracts metrics from PCoIP (PC over IP) log files and formats them
# for consumption by Prometheus node_exporter. It monitors virtual desktop performance
# including memory usage, image quality, bandwidth, network latency, and packet loss.
#### System Variables ####
pcoip_log='/var/log/pcoip-agent' # PCOIP Log file (Default is /var/log/pcoip-agent)
DEBUG="${DEBUG:-0}" # Debug mode (Default is 0) - Set to 1 to enable debug logging
#### Defaults ####
# Function to declare default values for all configuration variables
# These can be overridden by environment variables
declare_defaults() {
{
CRONTAB_USER="${CRONTAB_USER:-root}" # User to run cron jobs as (Default is root)
CRON_NAME="${CRON_NAME:-pcoip_metric.sh}" # Cron job name (Default is directory_size)
UPDATE_INTERVAL="${UPDATE_INTERVAL:-*/3 * * * * }" # Cron interval (Default is every 3 minutes)
NODE_EXPORTER_DIR="${NODE_EXPORTER_DIR:-/var/lib/node_exporter}" # Node Exporter textfile directory for .prom files
PROMETHEUS_USER="${PROMETHEUS_USER:-prometheus}" # System user that runs Prometheus/node_exporter
LOCK_DIR="${LOCK_DIR:-/var/run}" # Directory for lock files to prevent concurrent runs
SCRIPT_PATH="$(readlink -f "$0")" # Full path to this script for cron installation
}
}
#### Error logging functions ####
# Centralized error handling function that logs to stderr and exits
handle_error() {
{
local err_msg="$1"
local exit_code="${2:-1}" # Default exit code is 1 if not specified
echo "ERROR: $err_msg" >&2
exit "$exit_code"
}
}
# Logging function with level-based filtering
# DEBUG messages only appear when DEBUG=1 environment variable is set
log() {
{
local level="$1"
local message="$2"
# Only show DEBUG messages when debug mode is enabled
if [[ "$level" != "DEBUG" || "$DEBUG" -eq 1 ]]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" >&2
fi
}
}
#### Testing Log validation ####
# Function to validate that log files exist and match the expected pattern
# Returns 1 if no files found, 0 if files exist
validate_log_file() {
{
local log_dir="$1"
local pattern="$2"
local silent="${3:-false}"
# Enable nullglob to handle empty glob matches safely
# This prevents the pattern from expanding to itself if no matches
shopt -s nullglob
local files=("$log_dir"/$pattern)
shopt -u nullglob
# Check if any files were found matching the pattern
if [[ ${#files[@]} -eq 0 ]]; then
if [[ "$silent" != "true" ]]; then
log "WARNING" "No valid log files found matching $log_dir/$pattern"
fi
return 1
fi
return 0
}
}
#### Testing Timeout function (log) ####
# Function to execute commands with a timeout to prevent hanging
# Used for log processing commands that might get stuck
timeout_command() {
{
local timeout_seconds="$1"
local command="$2"
# Use the timeout command to limit execution time
timeout "$timeout_seconds" bash -c "$command" || {
log "WARNING" "Command timed out after $timeout_seconds seconds: $command"
return 1
}
}
}
### System Check ###
# Ensure script is running as root for proper file access and cron installation
if [ ! "$(id -u)" -eq 0 ]; then handle_error "This script must be run as root" 1; fi
#### Create, Check and Delete Lock File ###
# Create a temporary lock file to prevent multiple instances running simultaneously
LOCKFILE=$(mktemp -p "$LOCK_DIR" pcoip_stats.XXXXXX) || handle_error "Failed to create lock file" 1
exec 9>"$LOCKFILE" # Open file descriptor 9 for the lock file
# Try to acquire an exclusive, non-blocking lock
if ! flock -n 9; then
handle_error "Script is already running (unable to acquire lock)" 1
fi
# Clean up any stale lock files older than 60 minutes
find "$LOCKFILE" -mmin +60 -delete 2>/dev/null
# Cleanup function to release lock and remove lock file on exit
cleanup() {
{
flock -u 9 # Unlock the file
exec 9>&- # Close the file descriptor
rm -f "$LOCKFILE" # Remove the lock file
# log "Cleanup completed"
}
}
# Set up trap to ensure cleanup runs on script exit/termination
trap cleanup EXIT INT TERM PIPE
#### Code Starts Here ####
declare_defaults # Initialize default variables
# Capture script start time for runtime metric calculation
SCRIPT_START_TIME=$(date +%s)
# Function to find executable commands with fallback paths
# This ensures the script works across different Linux distributions
# where commands might be in different locations
find_command() {
{
local command_name="$1"
local fallback_paths=("${@:2}") # Remaining arguments are fallback paths
local path
# First try to find command in PATH
path=$(command -v "$command_name")
if [ -z "$path" ]; then
# If not found in PATH, try fallback locations
for path in "${fallback_paths[@]}"; do
if [ -x "$path/$command_name" ]; then
echo "$path/$command_name"
return 0
fi
done
handle_error "Could not find '$command_name' executable (even after fallback)." 1
fi
# Verify the found command is executable
if [ ! -x "$path" ]; then
handle_error "Found '$command_name' at '$path' but it's not executable." 1
fi
echo "$path"
}
}
# Find and validate all required command paths
# This section locates all Unix utilities needed for log parsing and metric extraction
AWK_PATH=$(find_command awk /usr/bin)
if [ -z "$AWK_PATH" ]; then handle_error "awk path is empty" 1; fi
CUT_PATH=$(find_command cut /usr/bin)
if [ -z "$CUT_PATH" ]; then handle_error "cut path is empty" 1; fi
GREP_PATH=$(find_command grep /usr/bin)
if [ -z "$GREP_PATH" ]; then handle_error "grep path is empty" 1; fi
REALPATH_PATH=$(find_command realpath /usr/bin)
if [ -z "$REALPATH_PATH" ]; then handle_error "realpath path is empty" 1; fi
SED_PATH=$(find_command sed /usr/bin)
if [ -z "$SED_PATH" ]; then handle_error "sed path is empty" 1; fi
TAIL_PATH=$(find_command tail /usr/bin)
if [ -z "$TAIL_PATH" ]; then handle_error "tail path is empty" 1; fi
TR_PATH=$(find_command tr /usr/bin)
if [ -z "$TR_PATH" ]; then handle_error "tr path is empty" 1; fi
# Validation for critical environment variables
[[ -z "$NODE_EXPORTER_DIR" || -z "$PROMETHEUS_USER" ]] && handle_error "Required environment variables not set" 1
[[ -z "$NODE_EXPORTER_DIR" || ! -d "$NODE_EXPORTER_DIR" ]] && handle_error "NODE_EXPORTER_DIR is not set or not a valid directory" 1
#### Validate Lockfile ####
# Ensure the lock file we created still exists (sanity check)
if [[ ! -f $LOCKFILE ]]; then
handle_error "No lockfile exists" 1
fi
### Check for .prom Directory ####
# Create the node_exporter textfile directory if it doesn't exist
if [ ! -d "$NODE_EXPORTER_DIR" ]; then
if [ "$(id -u)" = "0" ]; then # Check if running as root
mkdir -p "$NODE_EXPORTER_DIR"
# Set ownership to prometheus user for proper access
chown prometheus:prometheus "$NODE_EXPORTER_DIR" 2>/dev/null || true
fi
fi
# Verify we can write to the output directory
if [ ! -w "$NODE_EXPORTER_DIR" ]; then
handle_error "$NODE_EXPORTER_DIR is not writable." 1
fi
#### Check for Cron Job ####
# Auto-install cron job if this script exists and cron entry is missing
if [ -f "$SCRIPT_PATH" ] && ! crontab -l | grep -q "$SCRIPT_PATH"; then
# Attempt to add cron job to run script at specified interval
if ! (echo -e "$(crontab -u "$CRONTAB_USER" -l 2>/dev/null || echo '')\n$UPDATE_INTERVAL $SCRIPT_PATH > $NODE_EXPORTER_DIR/pcoip_metrics.prom 2>/dev/null" | crontab -u "$CRONTAB_USER" -); then
log "WARNING" "Failed to install cron job: $CRON_NAME. Verify permissions for user: $CRONTAB_USER."
else
log "INFO" "Cron job installed successfully: $CRON_NAME."
fi
fi
#### Metrics output functions ####
# Function to sanitize text for UTF-8 compliance and remove control characters
# Ensures Prometheus can properly parse the output
sanitize_utf8() {
{
local input="$1"
# Remove non-UTF8 characters and control characters except newlines
echo "$input" | iconv -f utf-8 -t utf-8 -c | tr -d '\r' | sed 's/[[:cntrl:]]//g'
}
}
# Function to output Prometheus metrics in the correct format
# Follows the Prometheus exposition format specification
output_metric() {
{
local metric_name="$1"
local metric_value="$2"
local help_text="$3"
local metric_type="${4:-gauge}" # Default to gauge if type not specified
# Sanitize all text for UTF-8 compliance
metric_name="$(sanitize_utf8 "$metric_name")"
help_text="$(sanitize_utf8 "$help_text")"
# Ensure metric value is numeric and valid, default to 0 if invalid
if [[ ! "$metric_value" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
metric_value="0"
fi
# Output in Prometheus format: HELP, TYPE, then the metric
echo "# HELP $metric_name $help_text"
echo "# TYPE $metric_name $metric_type"
echo "$metric_name $metric_value"
}
}
# Function to validate and sanitize metric values
# Returns a default value if the input is not a valid number
validate_metric_value() {
{
local value="$1"
local default="${2:-0}" # Default to 0 if no default specified
# Check if value is empty or not a valid number
if [[ -z "$value" || ! "$value" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
echo "$default"
else
echo "$value"
fi
}
}
# Function to collect memory-related metrics from PCoIP logs
# Extracts available and total memory information
collect_memory_metrics() {
{
local log_pattern="$1"
local default_values="${2:-false}"
if [[ "$default_values" == "true" ]]; then
# Output default metrics when logs are not available
output_metric "node_teradici_pcoip_memory_mb_avail" "0" "PCoIP Mbytes Available Memory."
output_metric "node_teradici_pcoip_memory_mb_total" "0" "PCoIP MBytes Total Memory."
return
fi
# Extract memory statistics: grep for "memory", clean up formatting, get latest entry
local mem_stats="$($GREP_PATH memory "$log_pattern" | $SED_PATH 's/.*memory =[\t ]*//;s/,//g' | $TR_PATH "/" " " | $TAIL_PATH -n 1)"
if [[ -n "$mem_stats" ]]; then
# Parse available memory (first field, remove MB suffix)
local mem_avail="$(echo "$mem_stats" | $AWK_PATH '{gsub(/MB/,"",$1)} {print $1}')"
# Parse total memory (second field, remove MB suffix)
local mem_total="$(echo "$mem_stats" | $AWK_PATH '{gsub(/MB/,"",$2)} {print $2}')"
# Validate and sanitize the extracted values
mem_avail="$(validate_metric_value "$mem_avail")"
mem_total="$(validate_metric_value "$mem_total")"
# Output the memory metrics
output_metric "node_teradici_pcoip_memory_mb_avail" "$mem_avail" "PCoIP Mbytes Available Memory."
output_metric "node_teradici_pcoip_memory_mb_total" "$mem_total" "PCoIP MBytes Total Memory."
else
# Output default metrics when no data found in logs
output_metric "node_teradici_pcoip_memory_mb_avail" "0" "PCoIP Mbytes Available Memory."
output_metric "node_teradici_pcoip_memory_mb_total" "0" "PCoIP MBytes Total Memory."
fi
}
}
# Function to collect image quality and performance metrics from PCoIP logs
# Extracts frame rates, image quality, pixel throughput, and RTT statistics
collect_image_quality_metrics() {
{
local log_pattern="$1"
local default_values="${2:-false}"
if [[ "$default_values" == "true" ]]; then
# Output default metrics when logs are not available
output_metric "node_teradici_pcoip_imaging_frames_persec" "0" "PCoIP active image Frames Per Second."
output_metric "node_teradici_pcoip_imaging_active_min_quality" "0" "PCoIP Min active image quality Percent."
output_metric "node_teradici_pcoip_imaging_pixel_persec" "0" "PCoIP image Pixel PerSec."
output_metric "node_teradici_pcoip_imaging_bits_persec" "0" "PCoIP image Bits PerSec."
output_metric "node_teradici_pcoip_imaging_megapixel_persec" "0" "PCoIP image MegaPixel PerSec."
output_metric "node_teradici_pcoip_imaging_rtt_last" "0" "PCoIP image RTT Last value."
output_metric "node_teradici_pcoip_imaging_rtt_min" "0" "PCoIP image RTT Min value."
output_metric "node_teradici_pcoip_imaging_rtt_max" "0" "PCoIP image RTT Max value."
output_metric "node_teradici_pcoip_imaging_rtt_avg" "0" "PCoIP image RTT AVG value."
return
fi
# Extract different types of image-related log entries
local img_bits="$($GREP_PATH bits/pixel "$log_pattern" | $SED_PATH 's/.*(SoftIPC): [\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
local img_stats="$($GREP_PATH fps "$log_pattern" | $SED_PATH 's/.*(SoftIPC): [\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
local img_rtt="$($GREP_PATH Imaging "$log_pattern" | $SED_PATH 's/.*:Imaging [\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
# Process frame rate and quality statistics
if [[ -n "$img_stats" ]]; then
# Extract frames per second (4th field) and image quality (6th field)
local img_frames="$(echo "$img_stats" | $AWK_PATH '{print $4}')"
local img_quality="$(echo "$img_stats" | $AWK_PATH '{print $6}')"
img_frames="$(validate_metric_value "$img_frames")"
img_quality="$(validate_metric_value "$img_quality")"
output_metric "node_teradici_pcoip_imaging_frames_persec" "$img_frames" "PCoIP active image Frames Per Second."
output_metric "node_teradici_pcoip_imaging_active_min_quality" "$img_quality" "PCoIP Min active image quality Percent."
else
output_metric "node_teradici_pcoip_imaging_frames_persec" "0" "PCoIP active image Frames Per Second."
output_metric "node_teradici_pcoip_imaging_active_min_quality" "0" "PCoIP Min active image quality Percent."
fi
# Process pixel and bandwidth statistics
if [[ -n "$img_bits" ]]; then
# Extract pixel rate, bits rate, and megapixel rate from different fields
local img_pixel="$(echo "$img_bits" | $AWK_PATH '{print $3}')"
local img_imgb="$(echo "$img_bits" | $AWK_PATH '{print $6}')"
local img_mpix="$(echo "$img_bits" | $AWK_PATH '{print $9}')"
img_pixel="$(validate_metric_value "$img_pixel")"
img_imgb="$(validate_metric_value "$img_imgb")"
img_mpix="$(validate_metric_value "$img_mpix")"
output_metric "node_teradici_pcoip_imaging_pixel_persec" "$img_pixel" "PCoIP image Pixel PerSec."
output_metric "node_teradici_pcoip_imaging_bits_persec" "$img_imgb" "PCoIP image Bits PerSec."
output_metric "node_teradici_pcoip_imaging_megapixel_persec" "$img_mpix" "PCoIP image MegaPixel PerSec."
else
output_metric "node_teradici_pcoip_imaging_pixel_persec" "0" "PCoIP image Pixel PerSec."
output_metric "node_teradici_pcoip_imaging_bits_persec" "0" "PCoIP image Bits PerSec."
output_metric "node_teradici_pcoip_imaging_megapixel_persec" "0" "PCoIP image MegaPixel PerSec."
fi
# Process round-trip time (RTT) statistics for imaging
if [[ -n "$img_rtt" ]]; then
# Extract RTT metrics: last, min, max, and average values
local rtt_last="$(echo "$img_rtt" | $AWK_PATH '{print $3}')"
local rtt_min="$(echo "$img_rtt" | $AWK_PATH '{print $5}')"
local rtt_max="$(echo "$img_rtt" | $AWK_PATH '{print $7}')"
local rtt_avg="$(echo "$img_rtt" | $AWK_PATH '{print $9}')"
rtt_last="$(validate_metric_value "$rtt_last")"
rtt_min="$(validate_metric_value "$rtt_min")"
rtt_max="$(validate_metric_value "$rtt_max")"
rtt_avg="$(validate_metric_value "$rtt_avg")"
output_metric "node_teradici_pcoip_imaging_rtt_last" "$rtt_last" "PCoIP image RTT Last value."
output_metric "node_teradici_pcoip_imaging_rtt_min" "$rtt_min" "PCoIP image RTT Min value."
output_metric "node_teradici_pcoip_imaging_rtt_max" "$rtt_max" "PCoIP image RTT Max value."
output_metric "node_teradici_pcoip_imaging_rtt_avg" "$rtt_avg" "PCoIP image RTT AVG value."
else
output_metric "node_teradici_pcoip_imaging_rtt_last" "0" "PCoIP image RTT Last value."
output_metric "node_teradici_pcoip_imaging_rtt_min" "0" "PCoIP image RTT Min value."
output_metric "node_teradici_pcoip_imaging_rtt_max" "0" "PCoIP image RTT Max value."
output_metric "node_teradici_pcoip_imaging_rtt_avg" "0" "PCoIP image RTT AVG value."
fi
}
}
# Function to collect bandwidth and loss-related metrics from PCoIP logs
# Extracts bandwidth utilization, packet loss, and adaptive bandwidth control data
collect_bandwidth_metrics() {
{
local log_pattern="$1"
local default_values="${2:-false}"
if [[ "$default_values" == "true" ]]; then
# Output default metrics when logs are not available
output_metric "node_teradici_pcoip_imaging_loss_percent" "0" "PCoIP image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_current_kbit_persec" "0" "PCoIP Current image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_active_send_kbit_persec" "0" "PCoIP Active Send image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_active_recv_kbit_persec" "0" "PCoIP Active Recv image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_adjust_factor_percent" "0" "PCoIP image Loss Adjust Factor value."
output_metric "node_teradici_pcoip_imaging_loss_floor_kbit_persec" "0" "PCoIP image Loss Floor value."
return
fi
# Extract bandwidth decrease/control statistics from ubs-BW-decr log entries
local img_bits="$($GREP_PATH bits/pixel "$pcoip_log"/server*.log | $SED_PATH 's/.*(SoftIPC): [\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
local img_decr_stats="$($GREP_PATH :ubs-BW-decr: "$log_pattern" | $SED_PATH 's/.*:ubs-BW-decr: [\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
local img_rtt="$($GREP_PATH Imaging "$pcoip_log"/server*.log | $SED_PATH 's/.*:Imaging [\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
local img_stats="$($GREP_PATH fps "$pcoip_log"/server*.log | $SED_PATH 's/.*(SoftIPC): [\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
if [[ -n "$img_decr_stats" ]]; then
# Parse complex bandwidth control log entry with multiple metrics
# Extract packet loss percentage (remove % symbol)
local img_decr="$(echo "$img_decr_stats" | $SED_PATH 's/.*loss=[\t ]*//;s/,//g' | $AWK_PATH -F '\\ current' '{gsub(/\%/,"",$1)} {print $1}')"
# Extract current bandwidth usage in kbit/s
local img_decr_cur="$(echo "$img_decr_stats" | $SED_PATH 's/.*current\[kbit\/s\]=[\t ]*//;s/,//g' | $AWK_PATH -F '\\ active' '{print $1}')"
# Extract active send bandwidth in kbit/s
local img_decr_sact="$(echo "$img_decr_stats" | $SED_PATH 's/.*active\[kbit\/s\]=[\t ]*//;s/,//g' | $AWK_PATH -F '\\ ->' '{print $1}')"
# Extract active receive bandwidth in kbit/s
local img_decr_ract="$(echo "$img_decr_stats" | $SED_PATH 's/.*-> [\t ]*//;s/,//g' | $AWK_PATH -F '\\ adjust' '{print $1}')"
# Extract bandwidth adjustment factor percentage
local img_decr_adj="$(echo "$img_decr_stats" | $SED_PATH 's/.*factor=[\t ]*//;s/,//g' | $AWK_PATH -F '\\ floor' '{gsub(/\%/,"",$1)} {print $1}')"
# Extract minimum bandwidth floor in kbit/s
local img_decr_floor="$(echo "$img_decr_stats" | $SED_PATH 's/^.*floor\[kbit\/s\]=[\t ]*//;s/,//g' | $AWK_PATH '{print $1}')"
# Validate all extracted values and provide defaults for percentages
img_decr="$(validate_metric_value "$img_decr" "0.00")"
img_decr_cur="$(validate_metric_value "$img_decr_cur" "0")"
img_decr_sact="$(validate_metric_value "$img_decr_sact" "0")"
img_decr_ract="$(validate_metric_value "$img_decr_ract" "0")"
img_decr_adj="$(validate_metric_value "$img_decr_adj" "0.00")"
img_decr_floor="$(validate_metric_value "$img_decr_floor" "0")"
# Output all bandwidth and loss control metrics
output_metric "node_teradici_pcoip_imaging_loss_percent" "$img_decr" "PCoIP image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_current_kbit_persec" "$img_decr_cur" "PCoIP Current image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_active_send_kbit_persec" "$img_decr_sact" "PCoIP Active Send image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_active_recv_kbit_persec" "$img_decr_ract" "PCoIP Active Recv image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_adjust_factor_percent" "$img_decr_adj" "PCoIP image Loss Adjust Factor value."
output_metric "node_teradici_pcoip_imaging_loss_floor_kbit_persec" "$img_decr_floor" "PCoIP image Loss Floor value."
else
# Output default metrics when no data found in logs
output_metric "node_teradici_pcoip_imaging_loss_percent" "0" "PCoIP image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_current_kbit_persec" "0" "PCoIP Current image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_active_send_kbit_persec" "0" "PCoIP Active Send image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_active_recv_kbit_persec" "0" "PCoIP Active Recv image Loss value."
output_metric "node_teradici_pcoip_imaging_loss_adjust_factor_percent" "0" "PCoIP image Loss Adjust Factor value."
output_metric "node_teradici_pcoip_imaging_loss_floor_kbit_persec" "0" "PCoIP image Loss Floor value."
fi
}
}
# Function to collect network performance metrics from PCoIP logs
# Extracts bandwidth limits, throughput averages, and round-trip time statistics
collect_network_metrics() {
{
local log_pattern="$1"
local default_values="${2:-false}"
if [[ "$default_values" == "true" ]]; then
# Output default metrics when logs are not available
output_metric "node_teradici_pcoip_tx_bw_limit_kbit_persec" "0" "PCoIP Network TX Limit."
output_metric "node_teradici_pcoip_avg_tx_kbit_persec" "0" "PCoIP Average TX kbits per second."
output_metric "node_teradici_pcoip_avg_rx_kbit_persec" "0" "PCoIP Average RX kbits per second."
output_metric "node_teradici_pcoip_round_trip_latency_ms" "0" "PCoIP Round Trip Latency."
output_metric "node_teradici_pcoip_round_trip_latency_max_ms" "0" "Pciop Round Trip Latency Max"
output_metric "node_teradici_pcoip_round_trip_variance_ms" "0" "PCoIP Round Trip Variance."
return
fi
# Extract network bandwidth limit and throughput statistics
local net_stats="$($GREP_PATH limit "$log_pattern" | $SED_PATH 's/.*limit =[\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
# Extract round-trip time measurements
local rtt_stats="$($GREP_PATH "round trip" "$log_pattern" | $SED_PATH 's/.*(ms) =[\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
# Process bandwidth and throughput metrics
if [[ -n "$net_stats" ]]; then
# Extract bandwidth limit (1st field)
local net_limit="$(echo "$net_stats" | $AWK_PATH '{print $1}')"
# Extract average TX throughput (5th field)
local tx_avg="$(echo "$net_stats" | $AWK_PATH '{print $5}')"
# Extract average RX throughput (note: using same field as TX - may need adjustment)
local rx_avg="$(echo "$net_stats" | $AWK_PATH '{print $5}')"
# Validate extracted network values
net_limit="$(validate_metric_value "$net_limit")"
tx_avg="$(validate_metric_value "$tx_avg")"
rx_avg="$(validate_metric_value "$rx_avg")"
# Output network throughput metrics
output_metric "node_teradici_pcoip_tx_bw_limit_kbit_persec" "$net_limit" "PCoIP Network TX Limit."
output_metric "node_teradici_pcoip_avg_tx_kbit_persec" "$tx_avg" "PCoIP Average TX kbits per second."
output_metric "node_teradici_pcoip_avg_rx_kbit_persec" "$rx_avg" "PCoIP Average RX kbits per second."
else
# Output default metrics when no data found in logs
output_metric "node_teradici_pcoip_tx_bw_limit_kbit_persec" "0" "PCoIP Network TX Limit."
output_metric "node_teradici_pcoip_avg_tx_kbit_persec" "0" "PCoIP Average TX kbits per second."
output_metric "node_teradici_pcoip_avg_rx_kbit_persec" "0" "PCoIP Average RX kbits per second."
fi
# Process round-trip time (latency) metrics
if [[ -n "$rtt_stats" ]]; then
# Extract RTT latency (1st field) and variance (5th field)
local rtt_latency="$(echo "$rtt_stats" | $AWK_PATH '{print $1}')"
local rtt_variance="$(echo "$rtt_stats" | $AWK_PATH '{print $5}')"
local rtt_rto="$(echo "$rtt_stats" | $AWK_PATH '{print $7}')"
local rtt_last="$(echo "$rtt_stats" | $AWK_PATH '{print $10}')"
local rtt_min="$(echo "$rtt_stats" | $AWK_PATH '{print $12}')"
local rtt_max="$(echo "$rtt_stats" | $AWK_PATH '{print $13}')"
# Validate RTT values
rtt_latency="$(validate_metric_value "$rtt_latency")"
rtt_variance="$(validate_metric_value "$rtt_variance")"
rtt_variance_max="$(validate_metric_value "$rtt_variance_max")"
rtt_rto="$(validate_metric_value "$rtt_rto")"
rtt_last="$(validate_metric_value "$rtt_last")"
rtt_min="$(validate_metric_value "$rtt_min")"
rtt_max="$(validate_metric_value "$rtt_max")"
# Output network latency metrics
output_metric "node_teradici_pcoip_round_trip_latency_ms" "$rtt_latency" "PCoIP Round Trip Latency."
output_metric "node_teradici_pcoip_round_trip_variance_ms" "$rtt_variance" "PCoIP Round Trip Variance."
output_metric "node_teradici_pcoip_round_trip_rto_ms" "$rtt_rto" "PCoIP Round Trip RTO."
output_metric "node_teradici_pcoip_round_trip_last_ms" "$rtt_last" "PCoIP Round Trip Last."
output_metric "node_teradici_pcoip_round_trip_min_ms" "$rtt_min" "PCoIP Round Trip Min."
output_metric "node_teradici_pcoip_round_trip_max_ms" "$rtt_max" "PCoIP Round Trip Max."
else
# Output default metrics when no data found in logs
output_metric "node_teradici_pcoip_round_trip_latency_ms" "0" "PCoIP Round Trip Latency."
output_metric "node_teradici_pcoip_round_trip_variance_ms" "0" "PCoIP Round Trip Variance."
output_metric "node_teradici_pcoip_round_trip_rto_ms" "0" "PCoIP Round Trip RTO."
output_metric "node_teradici_pcoip_round_trip_last_ms" "0" "PCoIP Round Trip Last."
output_metric "node_teradici_pcoip_round_trip_min_ms" "0" "PCoIP Round Trip Min."
output_metric "node_teradici_pcoip_round_trip_max_ms" "0" "PCoIP Round Trip Max."
fi
}
}
# Function to collect VGM (Virtual Graphics Management) packet loss metrics
# Extracts detailed packet loss statistics for different packet types (Audio, Image, Other)
collect_vgm_metrics() {
{
local log_pattern="$1"
local default_values="${2:-false}"
if [[ "$default_values" == "true" ]]; then
# Output default metrics when logs are not available
output_metric "node_teradici_pcoip_rx_packet_loss_percent" "0" "PCoIP RX Packet loss Percent."
output_metric "node_teradici_pcoip_tx_packet_loss_percent" "0" "PCoIP TX Packet loss Percent."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_a" "0" "PCoIP VGM RX Packet loss A."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_i" "0" "PCoIP VGM RX Packet loss I."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_o" "0" "PCoIP VGM RX Packet loss O."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_a" "0" "PCoIP VGM TX Packet loss A."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_i" "0" "PCoIP VGM TX Packet loss I."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_o" "0" "PCoIP VGM TX Packet loss O."
return
fi
# Extract VGM statistics from VGMAC log entries
local vgm_stats="$($GREP_PATH VGMAC "$log_pattern" | $SED_PATH 's/.*Stat: =[\t ]*//;s/,//g' | $TAIL_PATH -n 1)"
if [[ -n "$vgm_stats" ]]; then
# Extract basic packet loss percentages (convert "/" to space for parsing)
local pkt_loss="$(echo "$vgm_stats" | $SED_PATH 's/.*Loss=[\t ]*//;s/,//g' | $AWK_PATH '{gsub(/\//," ",$1)}1 ')"
# Extract detailed RX loss statistics
local vgm_loss_rx="$(echo "$vgm_stats" | $SED_PATH 's/.*R=[\t ]*//;s/,//g')"
# Extract detailed TX loss statistics
local vgm_loss_tx="$(echo "$vgm_stats" | $SED_PATH 's/.*T=[\t ]*//;s/,//g')"
# Process basic packet loss percentages
if [[ -n "$pkt_loss" ]]; then
# Split packet loss string by % symbol to get RX and TX percentages
local rx_pkt="$(echo "$pkt_loss" | $AWK_PATH '{split($0,a,"%")} {print a[1]}')"
local tx_pkt="$(echo "$pkt_loss" | $AWK_PATH '{split($0,a,"%")} {print a[2]}')"
rx_pkt="$(validate_metric_value "$rx_pkt")"
tx_pkt="$(validate_metric_value "$tx_pkt")"
# Output basic packet loss metrics
output_metric "node_teradici_pcoip_rx_packet_loss_percent" "$rx_pkt" "PCoIP RX Packet loss Percent."
output_metric "node_teradici_pcoip_tx_packet_loss_percent" "$tx_pkt" "PCoIP TX Packet loss Percent."
else
# Output default metrics when no packet loss data found
output_metric "node_teradici_pcoip_rx_packet_loss_percent" "0" "PCoIP RX Packet loss Percent."
output_metric "node_teradici_pcoip_tx_packet_loss_percent" "0" "PCoIP TX Packet loss Percent."
fi
# Process detailed VGM RX packet loss by type (A=Audio, I=Image, O=Other)
if [[ -n "$vgm_loss_rx" ]]; then
# Extract first 20 characters and split by "/" to get A/I/O values
local vgm_rx_a="$(echo "$vgm_loss_rx" | $CUT_PATH -b 1-20 | $AWK_PATH '{split($0,a,"/")} {print a[1]}')"
local vgm_rx_i="$(echo "$vgm_loss_rx" | $CUT_PATH -b 1-20 | $AWK_PATH '{split($0,a,"/")} {print a[2]}')"
local vgm_rx_o="$(echo "$vgm_loss_rx" | $CUT_PATH -b 1-20 | $AWK_PATH '{split($0,a,"/")} {print a[3]}')"
vgm_rx_a="$(validate_metric_value "$vgm_rx_a")"
vgm_rx_i="$(validate_metric_value "$vgm_rx_i")"
vgm_rx_o="$(validate_metric_value "$vgm_rx_o")"
# Output detailed RX packet loss metrics by type
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_a" "$vgm_rx_a" "PCoIP VGM RX Packet loss A."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_i" "$vgm_rx_i" "PCoIP VGM RX Packet loss I."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_o" "$vgm_rx_o" "PCoIP VGM RX Packet loss O."
else
# Output default metrics when no RX data found
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_a" "0" "PCoIP VGM RX Packet loss A."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_i" "0" "PCoIP VGM RX Packet loss I."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_o" "0" "PCoIP VGM RX Packet loss O."
fi
# Process detailed VGM TX packet loss by type (A=Audio, I=Image, O=Other)
if [[ -n "$vgm_loss_tx" ]]; then
# Extract first 20 characters and split by "/" to get A/I/O values
local vgm_tx_a="$(echo "$vgm_loss_tx" | $CUT_PATH -b 1-20 | $AWK_PATH '{split($0,a,"/")} {print a[1]}')"
local vgm_tx_i="$(echo "$vgm_loss_tx" | $CUT_PATH -b 1-20 | $AWK_PATH '{split($0,a,"/")} {print a[2]}')"
local vgm_tx_o="$(echo "$vgm_loss_tx" | $CUT_PATH -b 1-20 | $AWK_PATH '{split($0,a,"/")} {print a[3]}')"
vgm_tx_a="$(validate_metric_value "$vgm_tx_a")"
vgm_tx_i="$(validate_metric_value "$vgm_tx_i")"
vgm_tx_o="$(validate_metric_value "$vgm_tx_o")"
# Output detailed TX packet loss metrics by type
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_a" "$vgm_tx_a" "PCoIP VGM TX Packet loss A."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_i" "$vgm_tx_i" "PCoIP VGM TX Packet loss I."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_o" "$vgm_tx_o" "PCoIP VGM TX Packet loss O."
else
# Output default metrics when no TX data found
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_a" "0" "PCoIP VGM TX Packet loss A."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_i" "0" "PCoIP VGM TX Packet loss I."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_o" "0" "PCoIP VGM TX Packet loss O."
fi
else
# Output default metrics when no VGM data found in logs
output_metric "node_teradici_pcoip_rx_packet_loss_percent" "0" "PCoIP RX Packet loss Percent."
output_metric "node_teradici_pcoip_tx_packet_loss_percent" "0" "PCoIP TX Packet loss Percent."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_a" "0" "PCoIP VGM RX Packet loss A."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_i" "0" "PCoIP VGM RX Packet loss I."
output_metric "node_teradici_pcoip_vgm_rx_packet_loss_o" "0" "PCoIP VGM RX Packet loss O."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_a" "0" "PCoIP VGM TX Packet loss A."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_i" "0" "PCoIP VGM TX Packet loss I."
output_metric "node_teradici_pcoip_vgm_tx_packet_loss_o" "0" "PCoIP VGM TX Packet loss O."
fi
}
}
#### Process all PCoIP metrics ####
# Main function to orchestrate the collection of all PCoIP metrics
# Validates log files exist, then calls individual metric collection functions
process_pcoip_metrics() {
{
# Enable nullglob to handle empty glob matches safely
# This prevents the glob pattern from expanding to itself if no files match
shopt -s nullglob
local log_files=("$pcoip_log"/server*.log)
# If no server*.log files found, try looking for any server* files without .log extension
if [[ ${#log_files[@]} -eq 0 ]]; then
log_files=("$pcoip_log"/server*)
fi
shopt -u nullglob
# Check if PCoIP log files exist
if [[ ${#log_files[@]} -eq 0 ]] || ! validate_log_file "$pcoip_log" "server*" "true"; then
# Silently handle missing logs to prevent warning in metrics file
# Output status metric indicating PCoIP service is unavailable
output_metric "node_teradici_pcoip_status" "0" "PCoIP service status (0=unavailable, 1=active)"
# Collect all metrics with default values (0) when logs are not available
collect_memory_metrics "" "true"
collect_image_quality_metrics "" "true"
collect_bandwidth_metrics "" "true"
collect_network_metrics "" "true"
collect_vgm_metrics "" "true"
return 0 # Return success since we've output all metrics
fi
# Use the first (most recent) log file found
local log_pattern="${log_files[0]}"
log "INFO" "Processing PCoIP metrics from $log_pattern"
# Output status metric indicating PCoIP service is active and logs are available
output_metric "node_teradici_pcoip_status" "1" "PCoIP service status (0=unavailable, 1=active)"
# Collect all metrics by calling individual collection functions
collect_memory_metrics "$log_pattern"
collect_image_quality_metrics "$log_pattern"
collect_bandwidth_metrics "$log_pattern"
collect_network_metrics "$log_pattern"
collect_vgm_metrics "$log_pattern"
}
}
#####################
#### PCoIP Stats ####
#####################
# Main execution: Process all PCoIP metrics
process_pcoip_metrics
# Calculate and output script execution time as a metric
# This helps monitor script performance and detect issues
SCRIPT_END_TIME=$(date +%s)
SCRIPT_RUNTIME=$((SCRIPT_END_TIME - SCRIPT_START_TIME))
output_metric "node_teradici_pcoip_script_runtime_seconds" "$SCRIPT_RUNTIME" "PCoIP metrics script execution time in seconds"