welcome ghaymah

هذا الالتزام موجود في:
2026-07-27 23:06:16 +03:00
التزام 76f658bfab
17 ملفات معدلة مع 704 إضافات و0 حذوفات

1
README.md Normal file
عرض الملف

@@ -0,0 +1 @@
https://qabilah.com/profile/abdulrahmanabdalla88/professional-profile

عرض الملف

@@ -0,0 +1,35 @@
# مقترح تكامل: منصة إدارة المشاريع "فريقي" مع مزود السحابة "غيمة" (Ghaymah.systems)
## 1. وصف المنتج المختار
**"فريقي"** هي منصة عربية متكاملة لإدارة المشاريع والمهام، صُممت لتمنح الفرق العربية طريقة أوضح وأكثر سلاسة للعمل معًا، تنظيم المهام، ومتابعة الإنتاجية دون تعقيد.
## 2. كيف يتكامل مع ghaymah.systems
يمكن ربط منصة "فريقي" مع البنية التحتية لمنصة **غيمة (Ghaymah.systems)** السحابية بالآلية التالية:
* **نشر البيئات التلقائي (Automated Environment Provisioning):** ربط مهام المشروع داخل منصة "فريقي" (مثل حالة المهام عند انتقالها إلى "تم التنفيذ") بإطلاق حاويات تطوير أو بيئات اختبار (Testing Environments) مباشرة على سيرفرات "غيمة" عبر الـ Webhooks والـ APIs.
* **مزامنة الموارد السحابية:** تتبع استهلاك الموارد المخصصة لكل مشروع فريق واستعراض مؤشراتها داخل لوحة تحكم "فريقي".
## 3. القيمة المضافة للمستخدم النهائي
* **ربط دورة حياة التطوير بإدارة المهام:** الانتقال السلس من تخطيط المهام وبنائها إلى نشرها واختبارها على السحابة بضغطة زر واحدة.
* **توفير الوقت والجهد:** إلغاء الحاجة للتدخل اليدوي لإعداد خوادم التطوير، مما يعزز كفاءة فرق الـ DevOps والـ Developers العرب.
* **متابعة موحدة:** رؤية شاملة لمدير المشروع تشمل حالة المهام وحالة السيرفرات المستضافة على "غيمة" في مكان واحد.
## 4. رسم بسيط يوضح التكامل (Architecture Sketch)
+-----------------------------------+
| منصة إدارة المشاريع "فريقي" |
| (Task & Team Management) |
+-----------------------------------+
|
v (Trigger via Webhook / API)
+-----------------------------------+
| منصة غيمة (Ghaymah.systems) |
| (Cloud Provider & Docker) |
+-----------------------------------+
|
v (Provisioning & Deployment)
+-----------------------------------+
| بيئات العمل والخوادم السحابية |
+-----------------------------------+
## 5. التحديات التقنية أو التجارية المحتملة
* **التحديات التقنية:** إدارة صلاحيات الوصول وتأمين مفاتيح الربط (API Tokens) بين منصة إدارة المهام ومزود السحابة لمنع أي وصول غير مصرح به.
* **التحديات التجارية:** إدارة استهلاك الموارد السحابية المرتبطة بالمهام وضمان تسعيرها بشكل عادل يتناسب مع باقات المستخدمين على المنصتين.

عرض الملف

@@ -0,0 +1,40 @@
# مقترح تكامل: واجهة "إسأل مرتكز" مع محرك البحث العربي "ميثال" (Mithal.space)
## 1. وصف المنتج المختار
**"إسأل مرتكز"** هي أداة استعلام ذكية تعتمد على استخراج وتحليل بيانات المشاريع والمطورين العرب المسجلين على منصة مرتكز. تقدم الأداة تقارير مبسطة ومرئية وسهلة الهضم (مثل التوزيع النسبي للفئات، المشاريع الداعمة للقضايا، وأكثر المطورين نشاطاً) بدلاً من إغراق المستخدم بكميات البيانات الخام.
## 2. كيف يتكامل مع mithal.space
تعتمد منصة **ميثال (mithal.space)** كـ محرك بحث عربي متقدم، ويمكن تحقيق التكامل بالآلية التالية:
* **موتور البحث الخلفي (Search & RAG Backend):** يتم ربط واجهة استعلام "إسأل مرتكز" بمحرك بحث "ميثال" عبر واجهات البرمجة (RESTful APIs) بحيث تُرسل استفسارات المستخدمين (مثل البحث عن مطورين أو مشاريع معينة) لتتم معالجتها وفهرستها عبر محرك "ميثال".
* **الفهرسة الدلالية (Semantic Indexing):** يقوم محرك "ميثال" بفهرسة البيانات الوصفية للمشاريع (Metadata) وأوصافها باللغة العربية بدقة عالية، مما يرفع سرعة واستجابة استعلامات "إسأل مرتكز".
## 3. القيمة المضافة للمستخدم النهائي
* **دقة وسرعة الاستعلام:** الاستفادة من قوة محرك بحث "ميثال" في معالجة النصوص العربية لاسترجاع النتائج بدقة فائقة وفورية.
* **إثراء المحتوى التقني العربي:** مساعدة الباحثين والمطورين في الوصول إلى المشاريع المفتوحة المصدر وأصحابها بضغطة زر واحدة ومن خلال واجهة محادثة ذكية مبسطة.
* **تجربة مستخدم تفاعلية:** دمج تقارير "مرتكز" الإحصائية والمرئية مع قوة الفهرسة البحثية لـ "ميثال".
## 4. رسم بسيط يوضح التكامل (Architecture Sketch)
+-----------------------------------+
| مستخدم منصة "مرتكز" |
| (User Query / Interface) |
+-----------------------------------+
|
v
+-----------------------------------+
| واجهة "إسأل مرتكز" (API) |
+-----------------------------------+
| (HTTP JSON Request)
v
+-----------------------------------+
| محرك البحث العربي "ميثال" |
| (Mithal.space Core) |
+-----------------------------------+
| (Data Retrieval & RAG)
v
+-----------------------------------+
| قاعدة البيانات وفهرسة المشاريع |
+-----------------------------------+
## 5. التحديات التقنية أو التجارية المحتملة
* **التحديات التقنية:** معالجة الغموض اللغوي في استعلامات البحث باللغة العربية وضمان توافق زمن الاستجابة (Latency) مع التحديثات المستمرة للبيانات.
* **التحديات التجارية:** ضمان استدامة الموارد الحسابية لموتور البحث مع تزايد عدد المشاريع والمستخدمين المسجلين على منصة مرتكز.

عرض الملف

@@ -0,0 +1 @@
https://qabilah.com/profile/abdulrahmanabdalla88/professional-profile

عرض الملف

@@ -0,0 +1,17 @@
# Use an official lightweight Python image
FROM python:3.9-slim
# Set the working directory inside the container
WORKDIR /app
# Install required dependencies
RUN pip install --no-cache-dir fastapi uvicorn
# Copy all project files into the container
COPY . /app
# Expose the application port
EXPOSE 8000
# Command to run the application using Uvicorn server
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

31
q1-deploy-monitor/app.py Normal file
عرض الملف

@@ -0,0 +1,31 @@
import time
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
app = FastAPI()
# Global counter to track total requests
request_count = 0
@app.middleware("http")
async def count_requests(request: Request, call_next):
global request_count
request_count += 1
start_time = time.time()
response = await call_next(request)
process_time = (time.time() - start_time) * 1000
response.headers["X-Process-Time"] = f"{process_time:.2f}ms"
return response
# 3. Health Endpoint required by the task
@app.get("/health")
def health_check():
return {"status": "healthy", "requests": request_count}
# 5. Dashboard Endpoint serving the HTML file
@app.get("/", response_class=HTMLResponse)
def get_dashboard():
with open("dashboard.html", "r", encoding="utf-8") as f:
return f.read()

عرض الملف

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ghaymah App Dashboard</title>
<style>
body { font-family: Arial, sans-serif; background: #0f172a; color: #fff; text-align: center; padding-top: 50px; }
.card { background: #1e293b; padding: 20px; margin: 15px auto; width: 320px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.3); }
h3 { color: #38bdf8; margin-bottom: 5px; }
p { font-size: 20px; font-weight: bold; margin: 0; }
</style>
</head>
<body>
<h1>Application Monitoring Dashboard</h1>
<div class="card">
<h3>Status</h3>
<p id="status" style="color: #4ade80;">Loading...</p>
</div>
<div class="card">
<h3>Total Requests</h3>
<p id="count">0</p>
</div>
<div class="card">
<h3>Response Time</h3>
<p id="time">0 ms</p>
</div>
<script>
async function fetchMetrics() {
const start = performance.now();
try {
const response = await fetch('/health');
const end = performance.now();
const data = await response.json();
document.getElementById('status').innerText = data.status;
document.getElementById('count').innerText = data.requests;
document.getElementById('time').innerText = (end - start).toFixed(2) + ' ms';
} catch (error) {
document.getElementById('status').innerText = 'Down';
document.getElementById('status').style.color = '#f87171';
}
}
// Fetch metrics every 30 seconds as required
setInterval(fetchMetrics, 30000);
fetchMetrics();
</script>
</body>
</html>

عرض الملف

@@ -0,0 +1,20 @@
#!/bin/bash
URL="http://localhost:8000/health"
echo "Starting application monitoring. Checking every 30 seconds..."
while true; do
# Send HTTP GET request and get the status code
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" $URL)
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
if [ "$RESPONSE" -eq 200 ]; then
echo "[$TIMESTAMP] Status: HEALTHY (HTTP 200)"
else
echo "[$TIMESTAMP] Status: DOWN (HTTP $RESPONSE)"
fi
# Wait for 30 seconds before the next check
sleep 30
done

عرض الملف

@@ -0,0 +1,44 @@
# Incident Postmortem: Application Frequent Crashes (OOMKilled)
---
## 1. Incident Overview & Summary
- **Incident Date:** July 26, 2026
- **Impact:** The application deployed on Ghaymah Cloud suffered from repeated crashes every 45 minutes, causing service downtime for users.
- **Root Cause:** **OOMKilled (Out Of Memory)** error triggered because the container exceeded its allocated memory limit due to unoptimized resource configuration or a potential memory leak.
---
## 2. Timeline
- **00:00** - Application deployed and running normally.
- **00:30** - Memory consumption gradually increases as traffic and background tasks accumulate.
- **00:45** - Memory usage reaches 100% of the container limit; the Linux kernel terminates the process (`OOMKilled`).
- **00:46** - Container restarts automatically, and the cycle repeats precisely every 45 minutes.
---
## 3. Root Cause Analysis
1. **Resource Limits:** The container was assigned insufficient RAM limits in its deployment configuration.
2. **Memory Leak / Garbage Collection:** Long-running background jobs or unclosed database connections failed to release memory back to the system, leading to a steady upward trend until exhaustion.
---
## 4. Preventive Actions & Recommendations
- **Increase Container RAM:** Scale up the memory limits in the deployment configuration on Ghaymah Cloud.
- **Code Optimization:** Audit the application code to fix any memory leaks and ensure proper resource disposal.
- **Health & Memory Probes:** Implement stricter liveness and readiness probes.
---
## 5. Auto-Scaling Policy Design
To prevent recurring downtime under high load, an auto-scaling policy should be configured on Ghaymah Cloud:
- **Trigger Metric:** Memory Utilization or CPU Utilization.
- **Scale-Up Threshold:** Automatically add a new container instance (replica) when memory usage exceeds **75%** for 5 consecutive minutes.
- **Max Instances:** Set a cap of 3 instances to handle traffic spikes safely without exhausting cluster resources.
---
## 6. Early Detection & Monitoring Setup
Using Ghaymah Cloud monitoring tools to detect the issue proactively before crashes occur:
- **Custom Alerts:** Set up an alerting rule (via Webhook/Email) to notify the DevOps team when container memory usage crosses **70%**.
- **Real-Time Dashboards:** Monitor memory trends continuously using the metrics dashboard to spot gradual upward slopes before hitting the OOM threshold.

14
q3-cicd/README.md Normal file
عرض الملف

@@ -0,0 +1,14 @@
# --- Q3 Theoretical Documentation ---
## 1. Difference Between Staging and Production Environments:
- **Staging Environment:** A pre-production, isolated environment identical to production, used exclusively for testing updates, running integration tests, and catching bugs safely before real users see them.
- **Production Environment:** The live, primary environment accessed by end-users, where stability, high availability, and security are critical.
## 2. Ghaymah CLI Integration & Connection:
To link and authenticate with Ghaymah CLI locally or in pipelines:
1. Install the CLI tool:
`curl -sL https://cli.ghaymah.systems/install.sh | bash`
2. Authenticate using your API token:
`ghaymah auth login --token <YOUR_API_TOKEN>`
3. Verify connection status:
`ghaymah cluster status`

55
q3-cicd/workflow.yml Normal file
عرض الملف

@@ -0,0 +1,55 @@
name: CI/CD Pipeline to Ghaymah
on:
push:
branches: [ "main" ]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Log in to Ghaymah Container Registry
uses: docker/login-action@v3
with:
registry: registry.ghaymah.systems
username: ${{ secrets.GHAYMAH_USERNAME }}
password: ${{ secrets.GHAYMAH_TOKEN }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: registry.ghaymah.systems/abdulrahman/deploy-monitor:latest
staging-deploy:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Deploy to Staging Environment
run: |
echo "Deploying the built image to Staging server for testing..."
# ghaymah CLI command example for staging
production-approval:
needs: staging-deploy
runs-on: ubuntu-latest
environment: production # This triggers the GitHub Manual Approval gate
steps:
- name: Approved for Production
run: echo "Manual approval passed. Proceeding to production deployment."
production-deploy:
needs: production-approval
runs-on: ubuntu-latest
steps:
- name: Deploy to Production
run: |
echo "Deploying application to live Production server..."
# ghaymah CLI command example for production

ثنائية
q4-scalability/architecture.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 75 KiB

عرض الملف

@@ -0,0 +1,33 @@
# Q4: Scalability Sizing Calculations & Strategy
---
## 1. Container Capacity Calculation (Sizing)
- **Total Incoming Traffic:** $15,000 \text{ req/s}$
- **Single Container Capacity:** $500 \text{ req/s}$
- **Base Containers Required:**
$$\frac{15,000}{500} = 30 \text{ containers}$$
- **Safety Margin (30% buffer for traffic spikes & high availability):**
$$30 \times 0.30 = 9 \text{ extra containers}$$
- **Total Containers Needed:**
$$30 + 9 = 39 \text{ containers}$$
---
## 2. Cold Start Mitigation Strategy
To minimize latency and prevent performance drops when new containers spin up rapidly during auto-scaling:
- **Pre-warmed / Min Replicas:** Maintain a baseline of idle warm containers ready to take traffic immediately.
- **Lightweight Container Images:** Optimize the Dockerfile (using multi-stage builds and slim base images) to reduce image pull and startup time.
- **Health Check Optimization:** Tune liveness probes to detect readiness faster without overloading the container during boot.
---
## 3. Ghaymah Block Storage for Stateful Workloads
- **The Problem:** Containers are inherently ephemeral (stateless)—any data written inside the container's internal file system is lost if the container crashes or restarts.
- **The Solution (Ghaymah Block Storage):**
- Provides high-performance, persistent network-attached storage volumes.
- By mounting a Ghaymah Block Storage volume to the stateful workload (e.g., databases or file uploads), data is decoupled from the container lifecycle.
- If a container dies, a new container spins up and attaches to the exact same persistent storage volume with zero data loss.

عرض الملف

@@ -0,0 +1,17 @@
# استخدام صورة بايثون خفيفة
FROM python:3.9-slim
# تحديد مجلد العمل داخل الحاوية
WORKDIR /app
# تثبيت المكاتب المطلوبة مباشرة بدون الحاجة لملف requirements.txt منفصل
RUN pip install --no-cache-dir fastapi uvicorn requests
# نسخ باقي ملفات المشروع (مثل monitor.py و dashboard.html) إلى مجلد العمل
COPY . /app
# فتح البورت الذي يعمل عليه التطبيق
EXPOSE 8000
# أمر التشغيل المباشر باستخدام Uvicorn
CMD ["uvicorn", "monitor:app", "--host", "0.0.0.0", "--port", "8000"]

عرض الملف

@@ -0,0 +1,149 @@
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>لوحة مراقبة موقع مثال - Mithal Monitor</title>
<!-- مكتبة الرسم البياني Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body { font-family: Arial, sans-serif; background: #0f172a; margin: 0; padding: 40px 20px; color: #ffffff; }
.container { max-width: 800px; margin: auto; text-align: center; }
h1 { color: #ffffff; font-size: 24px; margin-bottom: 30px; }
.metrics-box { display: flex; gap: 15px; margin-bottom: 20px; }
.card { background: #1e293b; border-radius: 8px; padding: 20px; flex: 1; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); }
.card h3 { margin: 0 0 8px; font-size: 14px; color: #38bdf8; }
.card p { font-size: 18px; margin: 0; font-weight: bold; color: #ffffff; }
.chart-container { background: #1e293b; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); }
.status-ok { color: #4ade80 !important; }
.status-down { color: #f87171 !important; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; background: #1e293b; border-radius: 8px; overflow: hidden; }
th, td { padding: 12px; text-align: center; font-size: 14px; border-bottom: 1px solid #334155; }
th { background: #0f172a; color: #38bdf8; }
tr:last-child td { border-bottom: none; }
</style>
</head>
<body>
<div class="container">
<h1>لوحة مراقبة موقع مثال (mithal.space)</h1>
<div class="metrics-box">
<div class="card">
<h3>حالة الموقع</h3>
<p id="siteStatus" class="status-ok">جاري التحميل...</p>
</div>
<div class="card">
<h3>حالة SSL وتاريخ الانتهاء</h3>
<p id="sslStatus" style="font-size: 14px;">جاري التحميل...</p>
</div>
<div class="card">
<h3>متوسط الـ Latency</h3>
<p id="latencyStatus">جاري التحميل...</p>
</div>
</div>
<!-- الرسم البياني (Line Chart) لزمن الاستجابة -->
<div class="chart-container">
<h3 style="color: #38bdf8; margin-top: 0; text-align: right;">رسم بياني لزمن الاستجابة (Latency - آخر ساعة)</h3>
<canvas id="latencyChart"></canvas>
</div>
<h2 style="font-size: 18px; margin-top: 30px; color: #38bdf8; text-align: right;">سجل آخر الفحصات</h2>
<table>
<thead>
<tr>
<th>الوقت</th>
<th>حالة الموقع</th>
<th>زمن الاستجابة</th>
<th>زمن البحث</th>
<th>حالة SSL</th>
</tr>
</thead>
<tbody id="logTableBody">
</tbody>
</table>
</div>
<script>
// إعداد الرسم البياني باستخدام Chart.js
const ctx = document.getElementById('latencyChart').getContext('2d');
const latencyChart = new Chart(ctx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'زمن الاستجابة (ms)',
data: [],
borderColor: '#38bdf8',
backgroundColor: 'rgba(56, 189, 248, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.3
}]
},
options: {
responsive: true,
plugins: {
legend: { labels: { color: '#ffffff' } }
},
scales: {
x: { ticks: { color: '#94a3b8' }, grid: { color: '#334155' } },
y: { ticks: { color: '#94a3b8' }, grid: { color: '#334155' } }
}
}
});
async function fetchMetrics() {
try {
const response = await fetch('/api/metrics');
const data = await response.json();
if (data && data.length > 0) {
const latest = data[data.length - 1];
// تحديث الكروت العلوية
const statusElem = document.getElementById('siteStatus');
if (latest.status_code === 200) {
statusElem.textContent = "متصل (200 OK)";
statusElem.className = "status-ok";
} else {
statusElem.textContent = `غير متصل (${latest.status_code})`;
statusElem.className = "status-down";
}
document.getElementById('sslStatus').textContent = latest.ssl_status;
document.getElementById('latencyStatus').textContent = `${latest.latency_ms} ms`;
// تحديث بيانات الرسم البياني (Line Chart) من السكريبت
const timestamps = data.map(row => row.timestamp.split(' ')[1]); // أخذ الوقت فقط
const latencies = data.map(row => row.latency_ms);
latencyChart.data.labels = timestamps;
latencyChart.data.datasets[0].data = latencies;
latencyChart.update();
// تحديث الجدول
const tableBody = document.getElementById('logTableBody');
tableBody.innerHTML = '';
const reversedData = [...data].reverse().slice(0, 10);
reversedData.forEach(row => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${row.timestamp}</td>
<td class="${row.status_code === 200 ? 'status-ok' : 'status-down'}">${row.status_code} OK</td>
<td>${row.latency_ms} ms</td>
<td>${row.search_response_ms} ms</td>
<td>${row.ssl_status}</td>
`;
tableBody.appendChild(tr);
});
}
} catch (e) {
console.log("Error fetching metrics");
}
}
fetchMetrics();
setInterval(fetchMetrics, 5000); // تحديث الجراف والبيانات تلقائياً كل 5 ثوانٍ
</script>
</body>
</html>

عرض الملف

@@ -0,0 +1,74 @@
[
{
"timestamp": "2026-07-27 19:52:03",
"status_code": 200,
"latency_ms": 1041.82,
"dns_ms": 9.59,
"search_response_ms": 944.04,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
},
{
"timestamp": "2026-07-27 19:53:06",
"status_code": 200,
"latency_ms": 961.73,
"dns_ms": 1.01,
"search_response_ms": 951.24,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
},
{
"timestamp": "2026-07-27 19:54:09",
"status_code": 200,
"latency_ms": 1117.17,
"dns_ms": 21.45,
"search_response_ms": 849.41,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
},
{
"timestamp": "2026-07-27 19:55:12",
"status_code": 200,
"latency_ms": 1785.42,
"dns_ms": 0.0,
"search_response_ms": 846.86,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
},
{
"timestamp": "2026-07-27 19:56:23",
"status_code": 200,
"latency_ms": 3183.29,
"dns_ms": 1.12,
"search_response_ms": 4690.82,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
},
{
"timestamp": "2026-07-27 19:57:25",
"status_code": 200,
"latency_ms": 1111.06,
"dns_ms": 8.02,
"search_response_ms": 848.63,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
},
{
"timestamp": "2026-07-27 19:58:28",
"status_code": 200,
"latency_ms": 1030.14,
"dns_ms": 1.01,
"search_response_ms": 839.49,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
},
{
"timestamp": "2026-07-27 19:59:31",
"status_code": 200,
"latency_ms": 985.51,
"dns_ms": 18.2,
"search_response_ms": 931.7,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
},
{
"timestamp": "2026-07-27 20:00:33",
"status_code": 200,
"latency_ms": 936.12,
"dns_ms": 13.48,
"search_response_ms": 939.24,
"ssl_status": "صحيحة (تنتهي خلال 49 يوم)"
}
]

عرض الملف

@@ -0,0 +1,120 @@
import time
import requests
import json
import ssl
import socket
import os
import asyncio
from datetime import datetime, timezone
from urllib.parse import urlparse
from fastapi import FastAPI
from fastapi.responses import JSONResponse, FileResponse
from contextlib import asynccontextmanager
# --- تعريف الـ Lifespan لحل مشكلة الـ startup وتوليد الخلفية ---
@asynccontextmanager
async def lifespan(app: FastAPI):
task = asyncio.create_task(background_monitor())
yield
task.cancel()
app = FastAPI(lifespan=lifespan)
TARGET_URL = "https://mithal.space"
LOG_FILE = "metrics.json"
# --- دالة الفحص الخلفية بـ FastAPI ---
async def background_monitor():
while True:
parsed_url = urlparse(TARGET_URL)
hostname = parsed_url.netloc
start_time = time.time()
status_code = 0
latency = 0
ssl_expiry = "N/A"
dns_time = 0
search_time = 0
try:
dns_start = time.time()
socket.gethostbyname(hostname)
dns_time = round((time.time() - dns_start) * 1000, 2)
except:
dns_time = -1
try:
response = requests.get(TARGET_URL, timeout=10)
latency = round((time.time() - start_time) * 1000, 2)
status_code = response.status_code
except:
latency = -1
status_code = 503
try:
search_start = time.time()
requests.get(f"{TARGET_URL}/search?q=test", timeout=5)
search_time = round((time.time() - search_start) * 1000, 2)
except:
search_time = -1
try:
context = ssl.create_default_context()
with socket.create_connection((hostname, 443), timeout=5) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
cert = ssock.getpeercert()
expiry_date = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z').replace(tzinfo=timezone.utc)
days_left = (expiry_date - datetime.now(timezone.utc)).days
ssl_expiry = f"صحيحة (تنتهي خلال {days_left} يوم)"
except:
ssl_expiry = "خطأ في جلب SSL"
timestamp_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
record = {
"timestamp": timestamp_str,
"status_code": status_code,
"latency_ms": latency,
"dns_ms": dns_time,
"search_response_ms": search_time,
"ssl_status": ssl_expiry
}
try:
if os.path.exists(LOG_FILE):
with open(LOG_FILE, "r", encoding="utf-8") as f:
data = json.load(f)
else:
data = []
except:
data = []
data.append(record)
if len(data) > 20:
data = data[-20:]
with open(LOG_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
print(f"[{timestamp_str}] Background Checked {TARGET_URL} - Status: {status_code} - Latency: {latency}ms")
# الانتظار لمدة 30 ثانية أو دقيقة بحسب رغبتك
await asyncio.sleep(60)
# --- المسارات (Endpoints) ---
@app.get("/")
def index():
if os.path.exists("dashboard.html"):
return FileResponse("dashboard.html")
return {"message": "Dashboard file not found"}
@app.get("/api/metrics")
def get_metrics():
if os.path.exists(LOG_FILE):
try:
with open(LOG_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
return JSONResponse(content=data)
except:
return JSONResponse(content=[])
return JSONResponse(content=[])