Updating Files
هذا الالتزام موجود في:
@@ -332,3 +332,6 @@
|
|||||||
2025-09-30 23:08:22,398 - INFO - REQUEST: GET /docs - From 127.0.0.1
|
2025-09-30 23:08:22,398 - INFO - REQUEST: GET /docs - From 127.0.0.1
|
||||||
2025-09-30 23:08:22,399 - INFO - RESPONSE: GET /docs - Status 404
|
2025-09-30 23:08:22,399 - INFO - RESPONSE: GET /docs - Status 404
|
||||||
2025-09-30 23:08:22,399 - INFO - 127.0.0.1 - - [30/Sep/2025 23:08:22] "[33mGET /docs HTTP/1.1[0m" 404 -
|
2025-09-30 23:08:22,399 - INFO - 127.0.0.1 - - [30/Sep/2025 23:08:22] "[33mGET /docs HTTP/1.1[0m" 404 -
|
||||||
|
2025-09-30 23:59:59 - METHOD:GET - ENDPOINT:/fruits - STATUS:500 - ERROR: db not connected
|
||||||
|
2025-09-30 23:59:59 - METHOD:GET - ENDPOINT:/fruits - STATUS:400 - ERROR: db not connected
|
||||||
|
2025-09-30 23:59:59 - METHOD:GET - ENDPOINT:/fruits - STATUS:400 - ERROR: db not connected
|
||||||
|
@@ -1,26 +1,32 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/bash
|
||||||
|
|
||||||
LOG_FILE="fruit_api.log"
|
LOG_FILE="fruit_api.log"
|
||||||
|
# ALERT_URL="https://gahymah.systems.com"
|
||||||
|
|
||||||
if [[ ! -f "$LOG_FILE" ]]; then
|
tail -Fn0 "$LOG_FILE" | while read line; do
|
||||||
echo "❌ Log file $LOG_FILE not found!"
|
if echo "$line" | grep -qiE "STATUS:(4[0-9]{2}|5[0-9]{2})|failed|timeout|error|exception"; then
|
||||||
exit 1
|
echo "🚨 Error detected: $line"
|
||||||
fi
|
|
||||||
|
|
||||||
echo "📊 Fruit API Logs Report (last 2 hours) - $(date)"
|
IP=$(hostname -I | awk '{print $1}')
|
||||||
echo "--------------------------------------------------"
|
CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print $2"%"}')
|
||||||
|
RAM=$(free -m | awk '/Mem:/ {print $4"MB"}')
|
||||||
|
DISK=$(df -h / | awk 'NR==2 {print $4}')
|
||||||
|
|
||||||
# Get timestamps from last 2 hours
|
payload=$(cat <<EOF
|
||||||
time_filter=$(date --date='2 hours ago' +"%Y-%m-%d %H")
|
{
|
||||||
|
"error": "$line",
|
||||||
|
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
|
||||||
|
"message": "Error detected in Fruit API logs",
|
||||||
|
"server_metrics": {
|
||||||
|
"ip": "$IP",
|
||||||
|
"cpu_usage": "$CPU",
|
||||||
|
"ram_available": "$RAM",
|
||||||
|
"disk_space": "$DISK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
echo "$payload"
|
||||||
|
|
||||||
# Show all logs from last 2 hours
|
curl -s -X POST -H "Content-Type: application/json" -d "$payload" "$ALERT_URL"
|
||||||
echo "🔹 Raw logs (last 2 hours):"
|
fi
|
||||||
grep "$time_filter" "$LOG_FILE"
|
done
|
||||||
|
|
||||||
echo "--------------------------------------------------"
|
|
||||||
echo "🔹 Status Codes Summary:"
|
|
||||||
grep "$time_filter" "$LOG_FILE" | grep "RESPONSE" | awk '{print $NF}' | sort | uniq -c | sort -nr
|
|
||||||
|
|
||||||
echo "--------------------------------------------------"
|
|
||||||
echo "🔹 Users & IPs:"
|
|
||||||
grep "$time_filter" "$LOG_FILE" | grep "REQUEST" | awk '{for(i=1;i<=NF;i++){if($i ~ /^ip=/){print $i}}}' | sort | uniq -c | sort -nr
|
|
||||||
|
80
test_api.sh
80
test_api.sh
@@ -1,57 +1,39 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
# test_api.sh
|
echo "🚀 Running API tests at $(date)"
|
||||||
# Script to test Fruit API endpoints and log responses
|
echo "======================================"
|
||||||
|
|
||||||
API_URL="http://localhost:5000"
|
BASE_URL="http://localhost:5000"
|
||||||
LOG_FILE="test_results.log"
|
LOG_FILE="test_results.log"
|
||||||
|
|
||||||
echo "🚀 Running API tests at $(date)" | tee -a "$LOG_FILE"
|
check_status() {
|
||||||
echo "======================================" | tee -a "$LOG_FILE"
|
local status=$1
|
||||||
|
if [[ "$status" == "200" || "$status" == "201" ]]; then
|
||||||
|
echo "✅ Status: $status"
|
||||||
|
else
|
||||||
|
echo "❌ Status: $status"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# 1. Health Check
|
# Health
|
||||||
echo "🔹 Testing /health" | tee -a "$LOG_FILE"
|
status=$(curl -s -o /dev/null -w "%{http_code}" $BASE_URL/health)
|
||||||
curl -s -w "\nStatus: %{http_code}\n" "$API_URL/health" | tee -a "$LOG_FILE"
|
echo "🔹 Testing /health"
|
||||||
echo "--------------------------------------" | tee -a "$LOG_FILE"
|
check_status $status | tee -a $LOG_FILE
|
||||||
|
|
||||||
# 2. Get all fruits
|
# GET fruits
|
||||||
echo "🔹 Testing GET /fruits" | tee -a "$LOG_FILE"
|
status=$(curl -s -o /dev/null -w "%{http_code}" $BASE_URL/fruits)
|
||||||
curl -s -w "\nStatus: %{http_code}\n" "$API_URL/fruits" | tee -a "$LOG_FILE"
|
echo "🔹 Testing GET /fruits"
|
||||||
echo "--------------------------------------" | tee -a "$LOG_FILE"
|
check_status $status | tee -a $LOG_FILE
|
||||||
|
|
||||||
# 3. Get fruit by ID (1)
|
# GET fruit 1
|
||||||
echo "🔹 Testing GET /fruits/1" | tee -a "$LOG_FILE"
|
status=$(curl -s -o /dev/null -w "%{http_code}" $BASE_URL/fruits/1)
|
||||||
curl -s -w "\nStatus: %{http_code}\n" "$API_URL/fruits/1" | tee -a "$LOG_FILE"
|
echo "🔹 Testing GET /fruits/1"
|
||||||
echo "--------------------------------------" | tee -a "$LOG_FILE"
|
check_status $status | tee -a $LOG_FILE
|
||||||
|
|
||||||
# 4. Create new fruit
|
# POST fruit
|
||||||
echo "🔹 Testing POST /fruits" | tee -a "$LOG_FILE"
|
status=$(curl -s -o /dev/null -w "%{http_code}" -X POST $BASE_URL/fruits \
|
||||||
curl -s -X POST -H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"name":"Mango","color":"Yellow","price":2.5,"quantity":50,"category":"Tropical"}' \
|
-d '{"name":"Mango","color":"Yellow","price":2.5,"quantity":50,"category":"Tropical"}')
|
||||||
-w "\nStatus: %{http_code}\n" "$API_URL/fruits" | tee -a "$LOG_FILE"
|
echo "🔹 Testing POST /fruits"
|
||||||
echo "--------------------------------------" | tee -a "$LOG_FILE"
|
check_status $status | tee -a $LOG_FILE
|
||||||
|
|
||||||
# 5. Update fruit ID 1
|
|
||||||
echo "🔹 Testing PUT /fruits/1" | tee -a "$LOG_FILE"
|
|
||||||
curl -s -X PUT -H "Content-Type: application/json" \
|
|
||||||
-d '{"name":"Green Apple","price":1.8}' \
|
|
||||||
-w "\nStatus: %{http_code}\n" "$API_URL/fruits/1" | tee -a "$LOG_FILE"
|
|
||||||
echo "--------------------------------------" | tee -a "$LOG_FILE"
|
|
||||||
|
|
||||||
# 6. Delete fruit ID 1
|
|
||||||
echo "🔹 Testing DELETE /fruits/1" | tee -a "$LOG_FILE"
|
|
||||||
curl -s -X DELETE -w "\nStatus: %{http_code}\n" "$API_URL/fruits/1" | tee -a "$LOG_FILE"
|
|
||||||
echo "--------------------------------------" | tee -a "$LOG_FILE"
|
|
||||||
|
|
||||||
# 7. Search fruits
|
|
||||||
echo "🔹 Testing GET /fruits/search?name=apple" | tee -a "$LOG_FILE"
|
|
||||||
curl -s -w "\nStatus: %{http_code}\n" "$API_URL/fruits/search?name=apple" | tee -a "$LOG_FILE"
|
|
||||||
echo "--------------------------------------" | tee -a "$LOG_FILE"
|
|
||||||
|
|
||||||
# 8. Get fruits by category
|
|
||||||
echo "🔹 Testing GET /fruits/category/Tropical" | tee -a "$LOG_FILE"
|
|
||||||
curl -s -w "\nStatus: %{http_code}\n" "$API_URL/fruits/category/Tropical" | tee -a "$LOG_FILE"
|
|
||||||
echo "--------------------------------------" | tee -a "$LOG_FILE"
|
|
||||||
|
|
||||||
echo "✅ Tests completed at $(date)" | tee -a "$LOG_FILE"
|
|
||||||
echo "======================================" | tee -a "$LOG_FILE"
|
|
||||||
|
285
test_results.log
285
test_results.log
@@ -503,3 +503,288 @@ Status: 200
|
|||||||
--------------------------------------
|
--------------------------------------
|
||||||
✅ Tests completed at Tue 30 Sep 2025 11:14:57 PM EEST
|
✅ Tests completed at Tue 30 Sep 2025 11:14:57 PM EEST
|
||||||
======================================
|
======================================
|
||||||
|
🚀 Running API tests at Tue 30 Sep 2025 11:33:16 PM EEST
|
||||||
|
======================================
|
||||||
|
🔹 Testing /health
|
||||||
|
{
|
||||||
|
"service": "fruit-api",
|
||||||
|
"status": "healthy",
|
||||||
|
"timestamp": "2025-09-30T20:33:16.885319"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing GET /fruits
|
||||||
|
{
|
||||||
|
"fruits": [
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Red",
|
||||||
|
"id": 1,
|
||||||
|
"name": "Apple",
|
||||||
|
"price": 1.5,
|
||||||
|
"quantity": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"id": 2,
|
||||||
|
"name": "Banana",
|
||||||
|
"price": 0.75,
|
||||||
|
"quantity": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "Citrus",
|
||||||
|
"color": "Orange",
|
||||||
|
"id": 3,
|
||||||
|
"name": "Orange",
|
||||||
|
"price": 1.2,
|
||||||
|
"quantity": 80
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 3
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing GET /fruits/1
|
||||||
|
{
|
||||||
|
"fruit": {
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Red",
|
||||||
|
"id": 1,
|
||||||
|
"name": "Apple",
|
||||||
|
"price": 1.5,
|
||||||
|
"quantity": 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing POST /fruits
|
||||||
|
{
|
||||||
|
"fruit": {
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"created_at": "2025-09-30T20:33:17.044131",
|
||||||
|
"id": 4,
|
||||||
|
"name": "Mango",
|
||||||
|
"price": 2.5,
|
||||||
|
"quantity": 50
|
||||||
|
},
|
||||||
|
"message": "Fruit created successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 201
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing PUT /fruits/1
|
||||||
|
{
|
||||||
|
"fruit": {
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Red",
|
||||||
|
"id": 1,
|
||||||
|
"name": "Green Apple",
|
||||||
|
"price": 1.8,
|
||||||
|
"quantity": 100,
|
||||||
|
"updated_at": "2025-09-30T20:33:17.097781"
|
||||||
|
},
|
||||||
|
"message": "Fruit updated successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing DELETE /fruits/1
|
||||||
|
{
|
||||||
|
"deleted_fruit": {
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Red",
|
||||||
|
"id": 1,
|
||||||
|
"name": "Green Apple",
|
||||||
|
"price": 1.8,
|
||||||
|
"quantity": 100,
|
||||||
|
"updated_at": "2025-09-30T20:33:17.097781"
|
||||||
|
},
|
||||||
|
"message": "Fruit deleted successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing GET /fruits/search?name=apple
|
||||||
|
{
|
||||||
|
"count": 0,
|
||||||
|
"results": [],
|
||||||
|
"search_term": "apple"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing GET /fruits/category/Tropical
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"count": 2,
|
||||||
|
"fruits": [
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"id": 2,
|
||||||
|
"name": "Banana",
|
||||||
|
"price": 0.75,
|
||||||
|
"quantity": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"created_at": "2025-09-30T20:33:17.044131",
|
||||||
|
"id": 4,
|
||||||
|
"name": "Mango",
|
||||||
|
"price": 2.5,
|
||||||
|
"quantity": 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
✅ Tests completed at Tue 30 Sep 2025 11:33:17 PM EEST
|
||||||
|
======================================
|
||||||
|
🚀 Running API tests at Tue 30 Sep 2025 11:43:33 PM EEST
|
||||||
|
======================================
|
||||||
|
🔹 Testing /health
|
||||||
|
{
|
||||||
|
"service": "fruit-api",
|
||||||
|
"status": "healthy",
|
||||||
|
"timestamp": "2025-09-30T20:43:33.115100"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing GET /fruits
|
||||||
|
{
|
||||||
|
"fruits": [
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"id": 2,
|
||||||
|
"name": "Banana",
|
||||||
|
"price": 0.75,
|
||||||
|
"quantity": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "Citrus",
|
||||||
|
"color": "Orange",
|
||||||
|
"id": 3,
|
||||||
|
"name": "Orange",
|
||||||
|
"price": 1.2,
|
||||||
|
"quantity": 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"created_at": "2025-09-30T20:33:17.044131",
|
||||||
|
"id": 4,
|
||||||
|
"name": "Mango",
|
||||||
|
"price": 2.5,
|
||||||
|
"quantity": 50
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 3
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing GET /fruits/1
|
||||||
|
{
|
||||||
|
"error": "Fruit not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 404
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing POST /fruits
|
||||||
|
{
|
||||||
|
"fruit": {
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"created_at": "2025-09-30T20:43:33.358989",
|
||||||
|
"id": 4,
|
||||||
|
"name": "Mango",
|
||||||
|
"price": 2.5,
|
||||||
|
"quantity": 50
|
||||||
|
},
|
||||||
|
"message": "Fruit created successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 201
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing PUT /fruits/1
|
||||||
|
{
|
||||||
|
"error": "Fruit not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 404
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing DELETE /fruits/1
|
||||||
|
{
|
||||||
|
"error": "Fruit not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 404
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing GET /fruits/search?name=apple
|
||||||
|
{
|
||||||
|
"count": 0,
|
||||||
|
"results": [],
|
||||||
|
"search_term": "apple"
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
🔹 Testing GET /fruits/category/Tropical
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"count": 3,
|
||||||
|
"fruits": [
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"id": 2,
|
||||||
|
"name": "Banana",
|
||||||
|
"price": 0.75,
|
||||||
|
"quantity": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"created_at": "2025-09-30T20:33:17.044131",
|
||||||
|
"id": 4,
|
||||||
|
"name": "Mango",
|
||||||
|
"price": 2.5,
|
||||||
|
"quantity": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "Tropical",
|
||||||
|
"color": "Yellow",
|
||||||
|
"created_at": "2025-09-30T20:43:33.358989",
|
||||||
|
"id": 4,
|
||||||
|
"name": "Mango",
|
||||||
|
"price": 2.5,
|
||||||
|
"quantity": 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
--------------------------------------
|
||||||
|
✅ Tests completed at Tue 30 Sep 2025 11:43:33 PM EEST
|
||||||
|
======================================
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 201
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 201
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 200
|
||||||
|
✅ Status: 201
|
||||||
|
المرجع في مشكلة جديدة
حظر مستخدم