192 lines
6.8 KiB
Bash
Executable File
192 lines
6.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Configuration
|
|
BASE_URL="http://localhost:7130/api/database/records/posts"
|
|
DURATION=600 # 5 minutes in seconds
|
|
CONCURRENT_REQUESTS=10 # Number of concurrent requests
|
|
REQUEST_INTERVAL=0.1 # Seconds between requests per thread
|
|
|
|
# Function to generate random 8-character string (macOS compatible)
|
|
generate_random_string() {
|
|
# Use LC_ALL=C to avoid locale issues with tr on macOS
|
|
LC_ALL=C cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | head -c 8
|
|
}
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Statistics
|
|
TOTAL_REQUESTS=0
|
|
SUCCESS_COUNT=0
|
|
ERROR_COUNT=0
|
|
NOT_MODIFIED_COUNT=0
|
|
ERROR_MESSAGES=""
|
|
START_TIME=$(date +%s)
|
|
END_TIME=$((START_TIME + DURATION))
|
|
|
|
# Create temp directory for logs
|
|
LOG_DIR="/tmp/postgrest-test-$(date +%Y%m%d-%H%M%S)"
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
# Create lock file for thread safety (macOS compatible)
|
|
LOCK_FILE="$LOG_DIR/lock"
|
|
touch "$LOCK_FILE"
|
|
|
|
echo "========================================="
|
|
echo "PostgREST Stability Test"
|
|
echo "========================================="
|
|
echo "Base URL: $BASE_URL"
|
|
echo "Duration: $DURATION seconds (5 minutes)"
|
|
echo "Concurrent requests: $CONCURRENT_REQUESTS"
|
|
echo "Request interval: $REQUEST_INTERVAL seconds"
|
|
echo "Log directory: $LOG_DIR"
|
|
echo "========================================="
|
|
echo ""
|
|
|
|
# Function to make requests
|
|
make_requests() {
|
|
local thread_id=$1
|
|
local log_file="$LOG_DIR/thread-$thread_id.log"
|
|
|
|
while [ $(date +%s) -lt $END_TIME ]; do
|
|
# Generate random 8-character string for query parameter
|
|
RANDOM_STR=$(generate_random_string)
|
|
URL="${BASE_URL}?title=eq.${RANDOM_STR}"
|
|
|
|
# Make request and capture response (macOS compatible)
|
|
RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}\n:TIME:%{time_total}" "$URL" 2>&1)
|
|
HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
|
|
RESPONSE_TIME=$(echo "$RESPONSE" | grep ":TIME:" | cut -d: -f3)
|
|
RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d' | sed '/^:TIME:/d')
|
|
|
|
# Update global counters (using simple file-based locking for macOS)
|
|
while ! mkdir "$LOCK_FILE.lock" 2>/dev/null; do
|
|
sleep 0.01
|
|
done
|
|
|
|
# Read current values
|
|
[ -f "$LOG_DIR/total.cnt" ] && TOTAL_REQUESTS=$(cat "$LOG_DIR/total.cnt") || TOTAL_REQUESTS=0
|
|
[ -f "$LOG_DIR/success.cnt" ] && SUCCESS_COUNT=$(cat "$LOG_DIR/success.cnt") || SUCCESS_COUNT=0
|
|
[ -f "$LOG_DIR/error.cnt" ] && ERROR_COUNT=$(cat "$LOG_DIR/error.cnt") || ERROR_COUNT=0
|
|
[ -f "$LOG_DIR/not_modified.cnt" ] && NOT_MODIFIED_COUNT=$(cat "$LOG_DIR/not_modified.cnt") || NOT_MODIFIED_COUNT=0
|
|
|
|
TOTAL_REQUESTS=$((TOTAL_REQUESTS + 1))
|
|
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Thread $thread_id: SUCCESS (${RESPONSE_TIME}s)" >> "$log_file"
|
|
elif [ "$HTTP_CODE" = "304" ]; then
|
|
NOT_MODIFIED_COUNT=$((NOT_MODIFIED_COUNT + 1))
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Thread $thread_id: NOT MODIFIED (${RESPONSE_TIME}s)" >> "$log_file"
|
|
else
|
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
|
ERROR_MSG="[$(date '+%Y-%m-%d %H:%M:%S')] Thread $thread_id: ERROR - HTTP $HTTP_CODE (${RESPONSE_TIME}s)"
|
|
echo "$ERROR_MSG" >> "$log_file"
|
|
echo "Response: $RESPONSE_BODY" >> "$log_file"
|
|
echo -e "${RED}$ERROR_MSG${NC}"
|
|
|
|
# Log error details to main error file
|
|
echo "$ERROR_MSG" >> "$LOG_DIR/errors.log"
|
|
echo "Response: $RESPONSE_BODY" >> "$LOG_DIR/errors.log"
|
|
echo "---" >> "$LOG_DIR/errors.log"
|
|
fi
|
|
|
|
# Update counter files
|
|
echo $TOTAL_REQUESTS > "$LOG_DIR/total.cnt"
|
|
echo $SUCCESS_COUNT > "$LOG_DIR/success.cnt"
|
|
echo $ERROR_COUNT > "$LOG_DIR/error.cnt"
|
|
echo $NOT_MODIFIED_COUNT > "$LOG_DIR/not_modified.cnt"
|
|
|
|
# Release lock
|
|
rmdir "$LOCK_FILE.lock" 2>/dev/null
|
|
|
|
sleep $REQUEST_INTERVAL
|
|
done
|
|
}
|
|
|
|
# Function to display statistics
|
|
display_stats() {
|
|
while [ $(date +%s) -lt $END_TIME ]; do
|
|
# Read current values
|
|
[ -f "$LOG_DIR/total.cnt" ] && TOTAL_REQUESTS=$(cat "$LOG_DIR/total.cnt")
|
|
[ -f "$LOG_DIR/success.cnt" ] && SUCCESS_COUNT=$(cat "$LOG_DIR/success.cnt")
|
|
[ -f "$LOG_DIR/error.cnt" ] && ERROR_COUNT=$(cat "$LOG_DIR/error.cnt")
|
|
[ -f "$LOG_DIR/not_modified.cnt" ] && NOT_MODIFIED_COUNT=$(cat "$LOG_DIR/not_modified.cnt")
|
|
|
|
ELAPSED=$(($(date +%s) - START_TIME))
|
|
REMAINING=$((END_TIME - $(date +%s)))
|
|
|
|
if [ $TOTAL_REQUESTS -gt 0 ]; then
|
|
SUCCESS_RATE=$(echo "scale=2; $SUCCESS_COUNT * 100 / $TOTAL_REQUESTS" | bc)
|
|
REQ_PER_SEC=$(echo "scale=2; $TOTAL_REQUESTS / $ELAPSED" | bc)
|
|
else
|
|
SUCCESS_RATE=0
|
|
REQ_PER_SEC=0
|
|
fi
|
|
|
|
# Clear line and print stats
|
|
printf "\r${GREEN}[%ds/%ds]${NC} Requests: %d | Success: %d (%.1f%%) | 304s: %d | Errors: %d | Rate: %.1f req/s | Remaining: %ds" \
|
|
"$ELAPSED" "$DURATION" "$TOTAL_REQUESTS" "$SUCCESS_COUNT" "$SUCCESS_RATE" "$NOT_MODIFIED_COUNT" "$ERROR_COUNT" "$REQ_PER_SEC" "$REMAINING"
|
|
|
|
sleep 1
|
|
done
|
|
}
|
|
|
|
# Start concurrent request threads
|
|
echo "Starting $CONCURRENT_REQUESTS concurrent request threads..."
|
|
for i in $(seq 1 $CONCURRENT_REQUESTS); do
|
|
make_requests $i &
|
|
PIDS[$i]=$!
|
|
done
|
|
|
|
# Start statistics display
|
|
display_stats &
|
|
STATS_PID=$!
|
|
|
|
# Wait for all threads to complete
|
|
for pid in ${PIDS[@]}; do
|
|
wait $pid
|
|
done
|
|
|
|
# Kill stats display
|
|
kill $STATS_PID 2>/dev/null
|
|
|
|
# Final statistics
|
|
echo ""
|
|
echo ""
|
|
echo "========================================="
|
|
echo "Test Complete - Final Statistics"
|
|
echo "========================================="
|
|
echo "Total Requests: $TOTAL_REQUESTS"
|
|
echo -e "Successful: ${GREEN}$SUCCESS_COUNT${NC}"
|
|
echo -e "Not Modified (304): ${YELLOW}$NOT_MODIFIED_COUNT${NC}"
|
|
echo -e "Failed: ${RED}$ERROR_COUNT${NC}"
|
|
|
|
if [ $TOTAL_REQUESTS -gt 0 ]; then
|
|
SUCCESS_RATE=$(echo "scale=2; $SUCCESS_COUNT * 100 / $TOTAL_REQUESTS" | bc)
|
|
echo "Success Rate: $SUCCESS_RATE%"
|
|
AVG_REQ_PER_SEC=$(echo "scale=2; $TOTAL_REQUESTS / $DURATION" | bc)
|
|
echo "Average Rate: $AVG_REQ_PER_SEC requests/second"
|
|
fi
|
|
|
|
echo "========================================="
|
|
|
|
# Check for errors
|
|
if [ $ERROR_COUNT -gt 0 ]; then
|
|
echo ""
|
|
echo -e "${YELLOW}⚠️ Errors detected! Check the following files for details:${NC}"
|
|
echo " - Error log: $LOG_DIR/errors.log"
|
|
echo " - Thread logs: $LOG_DIR/thread-*.log"
|
|
echo ""
|
|
echo "First 10 errors:"
|
|
head -n 20 "$LOG_DIR/errors.log" 2>/dev/null || echo "No error details available"
|
|
else
|
|
echo ""
|
|
echo -e "${GREEN}✓ No errors detected during the test!${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Full logs available at: $LOG_DIR" |