هذا الالتزام موجود في:
2026-07-28 13:34:58 +03:00
التزام 1150963ef4
20 ملفات معدلة مع 674 إضافات و0 حذوفات

عرض الملف

@@ -0,0 +1 @@
https://qabilah.com/profile/mostafa-bebars/posts

عرض الملف

@@ -0,0 +1,18 @@
# Use a lightweight Node base image
FROM node:18-alpine
# Set the working directory inside the container
WORKDIR /usr/src/app
# Copy dependency definitions and install them
COPY package*.json ./
RUN npm install --production
# Copy the application code
COPY . .
# Expose the API port
EXPOSE 3000
# Start the application
CMD ["npm", "start"]

عرض الملف

@@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API Metrics Dashboard</title>
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
background: #f4f4f9;
padding: 2rem;
color: #333;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
max-width: 800px;
margin: 0 auto;
}
.card {
background: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
text-align: center;
}
h2 {
margin: 0 0 0.5rem;
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: #666;
}
.value {
font-size: 2.5rem;
font-weight: bold;
color: #111;
}
.status-up { color: #10b981; }
.status-down { color: #ef4444; }
</style>
</head>
<body>
<div class="grid">
<div class="card">
<h2>System Status</h2>
<div id="status" class="value">Loading...</div>
</div>
<div class="card">
<h2>Avg Response Time</h2>
<div class="value"><span id="responseTime">0</span> ms</div>
</div>
<div class="card">
<h2>Dashboard Pings</h2>
<div class="value" id="reqCount">0</div>
</div>
</div>
<script>
// Ensure this matches your running API (local or deployed)
const API_URL = 'https://bebars-64f19cdda81b.hosted.ghaymah.systems/health';
// Variables stored in the browser's memory
let requestCount = 0;
let totalResponseTimeMs = 0;
async function fetchMetrics() {
const startTime = Date.now(); // 1. Start the timer
try {
const res = await fetch(API_URL);
if (!res.ok) throw new Error('API unreachable');
const data = await res.json();
const endTime = Date.now(); // 2. Stop the timer
const duration = endTime - startTime; // 3. Calculate how long it took
//Do the math
requestCount++;
totalResponseTimeMs += duration;
const avgResponseTime = Math.round(totalResponseTimeMs / requestCount);
// Update the UI
const statusEl = document.getElementById('status');
statusEl.textContent = data.status;
statusEl.className = data.status === 'UP' ? 'value status-up' : 'value status-down';
document.getElementById('responseTime').textContent = avgResponseTime;
document.getElementById('reqCount').textContent = requestCount;
} catch (err) {
const statusEl = document.getElementById('status');
statusEl.textContent = 'DOWN';
statusEl.className = 'value status-down';
}
}
// Fetch immediately, then poll every 5 seconds
fetchMetrics();
setInterval(fetchMetrics, 5000);
</script>
</body>
</html>

عرض الملف

@@ -0,0 +1,22 @@
#!/bin/bash
# Replace this with your actual deployed Ghaymah URL
API_URL="https://bebars-64f19cdda81b.hosted.ghaymah.systems/health"
echo "Starting monitoring for $API_URL..."
echo "Press [CTRL+C] to stop."
while true; do
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
# Fetch only the HTTP status code
HTTP_STATUS=$(curl -o /dev/null -s -w "%{http_code}" "$API_URL")
if [ "$HTTP_STATUS" -eq 200 ]; then
echo "[$TIMESTAMP] ✅ Status: $HTTP_STATUS - App is HEALTHY"
else
echo "[$TIMESTAMP] ❌ Status: $HTTP_STATUS - App is DOWN or UNREACHABLE"
fi
sleep 30
done

عرض الملف

@@ -0,0 +1,18 @@
{
"name": "q1-deploy-monitor",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2"
}
}

عرض الملف

@@ -0,0 +1,23 @@
const express = require('express');
const cors = require('cors');
const app = express();
const port = process.env.PORT || 3000;
let requestCount = 0;
let totalResponseTime = 0;
// cors
app.use(cors());
// The requested health endpoint
app.get('/health', (req, res) => {
res.status(200).json({ status: 'UP', timestamp: new Date().toISOString() });
});
app.listen(port, () => {
console.log(`API running on port ${port}`);
});

عرض الملف

@@ -0,0 +1,51 @@
# Incident Postmortem Analysis: Application Outage (OOMKilled)
## 1. Summary
The application deployed on the Ghaymah platform experienced a complete outage lasting 45 minutes. The service continuously crashed and failed to start due to recurring `OOMKilled` (Out of Memory) errors. This resulted in a 100% failure rate for incoming requests during the incident window until mitigation measures were applied.
## 2. Timeline of Events
* **T-00:00 - Traffic Spike / Memory Leak Initiated:** Application memory consumption begins to spike uncontrollably due to an anomalous load or internal memory leak.
* **T+00:05 - Initial OOMKilled Event:** Container RAM usage hits the hard limit. The Ghaymah orchestrator forcefully terminates the process to protect the node, logging an `OOMKilled` event.
* **T+00:06 to T+00:44 - CrashLoopBackOff State:** Ghaymah automatically attempts to restart the container, but it repeatedly exceeds memory limits shortly after booting. Service remains entirely unavailable.
* **T+00:45 - Incident Mitigated:** Engineers manually intervene by vertically scaling the container's memory limits or deploying a hotfix. The application stabilizes and resumes serving traffic.
## 3. Root Cause
An `OOMKilled` error occurs when a container attempts to consume more memory than its configured limits allow. The underlying causes typically involve:
* **Memory Leak:** A flaw in the application code where unused memory is not released (e.g., inefficient garbage collection, unclosed connections).
* **Unoptimized Queries/Payloads:** The application attempted to process an unusually large dataset in memory all at once rather than using streams or pagination.
* **Under-provisioning:** The application lacked the baseline memory required to handle a legitimate surge in concurrent user traffic.
## 4. Action Items & Recommendations
* **Code Profiling:** Conduct memory profiling on the application to identify and patch memory leaks.
* **Pagination/Streaming:** Ensure large data processing tasks use streams rather than loading entire datasets into RAM.
* **Capacity Tuning:** Re-evaluate and adjust the baseline memory limits and requests configured for the container.
* **Implement Auto-scaling:** Configure dynamic scaling policies to absorb sudden spikes automatically.
---
## Auto-Scaling Policy Design for Ghaymah
Ghaymah natively supports both horizontal and vertical auto-scaling based on CPU and memory usage. To prevent this issue from recurring, a proactive scaling policy should be implemented:
* **Target Metric:** Average Container Memory Utilization.
* **Scale-Out (Increase Capacity):**
* **Condition:** If Memory Utilization is greater than 75% for a sustained period of 2 minutes.
* **Action:** Add 1 additional container replica (Horizontal Scaling) or dynamically increase the RAM allocation (Vertical Scaling).
* **Scale-In (Decrease Capacity):**
* **Condition:** If Memory Utilization falls below 40% for 5 minutes.
* **Action:** Remove 1 replica to optimize resource consumption.
* **Limits:** Minimum of 2 replicas (for high availability) and a Maximum of 10 replicas (to control cloud spend).
**Why this works:** The 75% threshold leaves a 25% safety buffer. This gives the Ghaymah platform enough time to spin up new instances and distribute the load before any single container hits the 100% `OOMKilled` threshold.
---
## Early Detection Using Ghaymah Monitoring Tools
Relying on user complaints or complete downtime is an anti-pattern. You can detect memory exhaustion early using Ghaymah's built-in monitoring:
* **Threshold Alerts:** Configure Ghaymah to send automated alerts (via Slack, email, or webhook) when memory usage reaches 70% and 80%. This provides a critical window for intervention before the container crashes.
* **Restart Rate Monitoring:** Set an alert if the container restart count exceeds 1 within a 15-minute window. Frequent restarts are the earliest indicator of a `CrashLoopBackOff` state.
* **Application Logs Analysis:** Monitor logs for warning signs such as garbage collection (GC) taking excessively long, or application-level out-of-memory warnings that often precede the infrastructure-level kill signal.
* **Endpoint Health Checks:** Ensure proper Liveness and Readiness probes are configured. If high memory pressure degrades application performance, the Readiness probe should fail, instructing Ghaymah's load balancer to stop routing traffic to the struggling instance before it dies.

17
q3-cicd/.ghaymah.json Normal file
عرض الملف

@@ -0,0 +1,17 @@
{
"id": "9299b6b6-ff2e-4984-8d85-5bdb0b809533",
"name": "q3",
"projectId": "27aacb50-4d56-474c-baae-b52a853b4d57",
"ports": [
{
"expose": true,
"number": 3000
}
],
"publicAccess": {
"enabled": true,
"domain": "auto"
},
"resourceTier": "t1",
"dockerFileName": "Dockerfile"
}

55
q3-cicd/.github/workflows/ci.yml مباع Normal file
عرض الملف

@@ -0,0 +1,55 @@
name: Ghaymah CI/CD Pipeline
on:
push:
branches: [ "master" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
deploy-staging:
name: Deploy to Staging
needs: build
runs-on: ubuntu-latest
# Staging is used for pre-production validation before a live release.
environment:
name: staging
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Install Ghaymah CLI
run: curl -sSL https://cli.ghaymah.systems/install.sh | bash
- name: Login to Ghaymah
run: $HOME/ghaymah/bin/gy auth login --email "${{ secrets.GHAYMAH_EMAIL }}" --password "${{ secrets.GHAYMAH_PW }}" --debug
deploy-production:
name: Deploy to Production
needs: deploy-staging
runs-on: ubuntu-latest
# Production is the live environment and should be protected by manual approval.
environment:
name: production
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Install Ghaymah CLI
run: curl -sSL https://cli.ghaymah.systems/install.sh | bash
- name: Login to Ghaymah
run: $HOME/ghaymah/bin/gy auth login --email "${{secrets.GHAYMAH_EMAIL}}" --password "${{secrets.GHAYMAH_PW}}" --debug
- name: Deploy to Ghaymah (Production)
run: $HOME/ghaymah/bin/gy resource app launch --debug

18
q3-cicd/Dockerfile Normal file
عرض الملف

@@ -0,0 +1,18 @@
# Use a lightweight Node base image
FROM node:18-alpine
# Set the working directory inside the container
WORKDIR /usr/src/app
# Copy dependency definitions and install them
COPY package*.json ./
RUN npm install --production
# Copy the application code
COPY . .
# Expose the API port
EXPOSE 3000
# Start the application
CMD ["npm", "start"]

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

@@ -0,0 +1,50 @@
# Ghaymah CI/CD Guide
## Staging vs. Production
- Staging is a pre-production environment used to test changes safely before they reach real users. It is typically isolated from production data and traffic, so teams can validate deployments, configuration, and application behavior without affecting live services.
- Production is the live environment that serves real users and business-critical traffic. Deployments here should be controlled carefully, usually with approval gates, protected environments, and rollback plans.
- A common release flow is:
1. Build and test the application.
2. Deploy to staging.
3. Validate the release.
4. Request approval for production.
5. Deploy to production.
## Connecting the GitHub Actions workflow to Ghaymah CLI
The workflow uses the Ghaymah CLI to authenticate and deploy the app.
### 1. Add GitHub secrets
Create these repository or environment secrets in GitHub:
- GHAYMAH_EMAIL
- GHAYMAH_PW
### 2. Install the CLI
The workflow installs the CLI during the deployment job:
```bash
curl -sSL https://cli.ghaymah.systems/install.sh | bash
```
### 3. Authenticate with Ghaymah
After installation, the workflow logs in with the stored credentials:
```bash
$HOME/ghaymah/bin/gy auth login --email "${{ secrets.GHAYMAH_EMAIL }}" --password "${{ secrets.GHAYMAH_PW }}" --debug
```
### 4. Deploy the application
The deployment step then launches the app through Ghaymah:
```bash
$HOME/ghaymah/bin/gy resource app launch --debug
```
### 5. Recommended GitHub environment setup
Use GitHub Environments for deployment control:
- Create a staging environment for regular validation.
- Create a production environment and require manual approval before deployment.
- Attach the same secrets to the relevant environment when needed.

18
q3-cicd/package.json Normal file
عرض الملف

@@ -0,0 +1,18 @@
{
"name": "q1-deploy-monitor",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2"
}
}

23
q3-cicd/server.js Normal file
عرض الملف

@@ -0,0 +1,23 @@
const express = require('express');
const cors = require('cors');
const app = express();
const port = process.env.PORT || 3000;
let requestCount = 0;
let totalResponseTime = 0;
// cors
app.use(cors());
// The requested health endpoint
app.get('/health', (req, res) => {
res.status(200).json({ status: 'UP', timestamp: new Date().toISOString() });
});
app.listen(port, () => {
console.log(`API running on port ${port}`);
});

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

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

بعد

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

عرض الملف

@@ -0,0 +1,20 @@
Container Calculation
### Container Capacity Calculation
To handle 15,000 requests per second with a base container capacity of 500 requests per second and a 30% safety margin:
1. **Base Containers Needed:** 15,000 / 500 = 30 containers
2. **Safety Buffer (30%):** 30 * 0.30 = 9 containers
3. **Total Required Containers:** 30 + 9 = **39 containers**
### Cold Start Mitigation Strategy
To prevent dropped requests or high latency when spinning up new containers:
1. **Pre-warming (Provisioned Concurrency):** Maintain a buffer of extra "warm" containers running just above the current traffic demands.
2. **Health & Readiness Probes:** Ensure the load balancer only routes traffic to containers that have passed their readiness checks and are fully booted.
3. **Image Optimization:** Keep Docker images small (e.g., using Alpine Linux) so Ghaymah can pull and extract the image rapidly.
### Using Ghaymah Block Storage for Stateful Workloads
Because containers are ephemeral, stateful workloads (like databases) lose data if a container crashes. Ghaymah Block Storage solves this:
1. **Provision & Mount:** A persistent block storage volume is provisioned and mounted to a specific directory path inside the container
2. **Persistence:** The application writes data directly to this external volume. If the container is destroyed or rescheduled, the volume easily reattaches to the new container, ensuring zero data loss.

عرض الملف

@@ -0,0 +1,17 @@
{
"id": "159ccedb-4f26-447c-99e7-bcad1de22120",
"name": "q5-mithal-monitor",
"projectId": "27aacb50-4d56-474c-baae-b52a853b4d57",
"ports": [
{
"expose": true,
"number": 80
}
],
"publicAccess": {
"enabled": true,
"domain": "auto"
},
"resourceTier": "t1",
"dockerFileName": "Dockerfile"
}

عرض الملف

@@ -0,0 +1,34 @@
name: Ghaymah CI/CD Pipeline
on:
push:
branches: [ "master" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
deploy-production:
name: Deploy to Production
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Install Ghaymah CLI
run: curl -sSL https://cli.ghaymah.systems/install.sh | bash
- name: Login to Ghaymah
run: $HOME/ghaymah/bin/gy auth login --email "${{ secrets.GHAYMAH_EMAIL }}" --password "${{ secrets.GHAYMAH_PW }}" --debug
- name: Deploy to Ghaymah (Production)
run: $HOME/ghaymah/bin/gy resource app launch --debug

عرض الملف

@@ -0,0 +1,28 @@
FROM nginx:alpine
# Install bash, curl, openssl, coreutils (for date parsing), and cron
RUN apk update && apk add bash curl openssl coreutils dcron
# Clear the default Nginx welcome page first
RUN rm -rf /usr/share/nginx/html/*
# Setup workspace
COPY dashboard.html /usr/share/nginx/html/index.html
COPY monitor.sh /usr/local/bin/monitor.sh
RUN chmod +x /usr/local/bin/monitor.sh
RUN touch /usr/share/nginx/html/data.csv && \
chown -R nginx:nginx /usr/share/nginx/html && \
chmod -R 755 /usr/share/nginx/html
# Add cron job (runs every minute)
RUN echo "* * * * * /usr/local/bin/monitor.sh" | crontab -
# Custom entrypoint to start cron in background, then nginx in foreground
RUN echo '#!/bin/sh' > /entrypoint.sh && \
echo 'crond -b -l 8' >> /entrypoint.sh && \
echo 'nginx -g "daemon off;"' >> /entrypoint.sh && \
chmod +x /entrypoint.sh
EXPOSE 80
CMD ["/entrypoint.sh"]

عرض الملف

@@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mithal Engine Status</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body { font-family: system-ui, sans-serif; background: #f4f4f5; margin: 0; padding: 20px; color: #18181b; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 20px; }
.card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
.metric { font-size: 2rem; font-weight: bold; color: #2563eb; }
table { width: 100%; border-collapse: collapse; margin-top: 10px; }
th, td { text-align: left; padding: 12px; border-bottom: 1px solid #e4e4e7; }
.status-up { color: #16a34a; font-weight: bold; }
.status-down { color: #dc2626; font-weight: bold; }
</style>
</head>
<body>
<h1>Mithal Engine Monitoring Dashboard</h1>
<div class="grid">
<div class="card">
<h3>Uptime (Last 24h)</h3>
<div class="metric" id="uptime-indicator">--%</div>
</div>
<div class="card">
<h3>SSL Certificate</h3>
<div class="metric" id="ssl-status">-- Days</div>
</div>
</div>
<div class="card" style="margin-bottom: 20px;">
<h3>Response Time (Last Hour)</h3>
<canvas id="latencyChart" height="80"></canvas>
</div>
<div class="card">
<h3>Recent Logs (Last 10 Checks)</h3>
<table>
<thead>
<tr>
<th>Timestamp</th>
<th>Status</th>
<th>Latency (s)</th>
<th>DNS (s)</th>
<th>Search (s)</th>
</tr>
</thead>
<tbody id="log-table"></tbody>
</table>
</div>
<script>
async function loadData() {
const response = await fetch('data.csv');
const text = await response.text();
// Parse CSV
const rows = text.trim().split('\n').slice(1).map(row => {
const [timestamp, status, latency, ssl_days, dns, search] = row.split(',');
return { timestamp, status: parseInt(status), latency: parseFloat(latency), ssl_days, dns, search };
});
if (rows.length === 0) return;
// Uptime Calculation
const upChecks = rows.filter(r => r.status >= 200 && r.status < 400).length;
const uptimePct = ((upChecks / rows.length) * 100).toFixed(2);
document.getElementById('uptime-indicator').textContent = `${uptimePct}%`;
// SSL Status
const latest = rows[rows.length - 1];
document.getElementById('ssl-status').textContent = `${latest.ssl_days} Days`;
// Chart Data (Last 60 entries = 1 hour)
const recentHour = rows.slice(-60);
const labels = recentHour.map(r => new Date(r.timestamp).toLocaleTimeString());
const data = recentHour.map(r => r.latency);
new Chart(document.getElementById('latencyChart'), {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Latency (s)',
data: data,
borderColor: '#2563eb',
tension: 0.1,
fill: false
}]
},
options: { animation: false }
});
// Logs Table (Last 10)
const last10 = rows.slice(-10).reverse();
const tbody = document.getElementById('log-table');
tbody.innerHTML = last10.map(r => `
<tr>
<td>${new Date(r.timestamp).toLocaleString()}</td>
<td class="${r.status === 200 ? 'status-up' : 'status-down'}">${r.status}</td>
<td>${r.latency.toFixed(3)}</td>
<td>${parseFloat(r.dns).toFixed(3)}</td>
<td>${parseFloat(r.search).toFixed(3)}</td>
</tr>
`).join('');
}
loadData();
setInterval(loadData, 60000); // Refresh every minute
</script>
</body>
</html>

عرض الملف

@@ -0,0 +1,41 @@
#!/bin/bash
# monitor.sh
TARGET="mithal.space"
URL="https://$TARGET"
SEARCH_URL="$URL/?q=test" # Adjust query parameter based on the actual search endpoint
if [ -d "/usr/share/nginx/html" ]; then
DATA_FILE="/usr/share/nginx/html/data.csv"
else
DATA_FILE="./data.csv"
fi
# Initialize CSV with headers if it doesn't exist
if [ ! -f "$DATA_FILE" ]; then
echo "timestamp,status,latency,ssl_days,dns_time,search_time" > "$DATA_FILE"
fi
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# 1. Uptime, Latency, and DNS Resolution
HTTP_RESPONSE=$(curl -o /dev/null -s -w "%{http_code},%{time_total},%{time_namelookup}" "$URL")
STATUS=$(echo "$HTTP_RESPONSE" | cut -d',' -f1)
LATENCY=$(echo "$HTTP_RESPONSE" | cut -d',' -f2)
DNS_TIME=$(echo "$HTTP_RESPONSE" | cut -d',' -f3)
# 2. Search Response Time
SEARCH_TIME=$(curl -o /dev/null -s -w "%{time_total}" "$SEARCH_URL")
# 3. SSL Expiration
EXP_DATE=$(echo | openssl s_client -servername "$TARGET" -connect "$TARGET:443" 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
if [ -n "$EXP_DATE" ]; then
EXP_EPOCH=$(date -d "$EXP_DATE" +%s)
CURRENT_EPOCH=$(date +%s)
SSL_DAYS=$(( (EXP_EPOCH - CURRENT_EPOCH) / 86400 ))
else
SSL_DAYS=0
fi
# Append to CSV
echo "$TIMESTAMP,$STATUS,$LATENCY,$SSL_DAYS,$DNS_TIME,$SEARCH_TIME" >> "$DATA_FILE"