<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Server Status</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
padding: 40px;
max-width: 800px;
width: 100%;
}
.header {
text-align: center;
margin-bottom: 40px;
}
.status-badge {
display: inline-block;
padding: 10px 30px;
border-radius: 50px;
font-size: 18px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 10px;
}
.status-ok {
background: #10b981;
color: white;
}
.status-error {
background: #ef4444;
color: white;
}
.status-warning {
background: #f59e0b;
color: white;
}
h1 {
color: #1f2937;
font-size: 32px;
margin-bottom: 10px;
}
.timestamp {
color: #6b7280;
font-size: 14px;
}
.checks {
display: grid;
gap: 20px;
}
.check-card {
border: 2px solid #e5e7eb;
border-radius: 12px;
padding: 20px;
transition: all 0.3s ease;
}
.check-card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
transform: translateY(-2px);
}
.check-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15px;
}
.check-name {
font-size: 20px;
font-weight: 600;
color: #1f2937;
text-transform: capitalize;
}
.check-status {
width: 20px;
height: 20px;
border-radius: 50%;
}
.check-status.ok {
background: #10b981;
box-shadow: 0 0 10px rgba(16, 185, 129, 0.5);
}
.check-status.error {
background: #ef4444;
box-shadow: 0 0 10px rgba(239, 68, 68, 0.5);
}
.check-status.warning {
background: #f59e0b;
box-shadow: 0 0 10px rgba(245, 158, 11, 0.5);
}
.check-details {
color: #6b7280;
font-size: 14px;
line-height: 1.8;
}
.check-details strong {
color: #374151;
display: inline-block;
min-width: 140px;
}
.error-message {
background: #fee2e2;
color: #991b1b;
padding: 12px;
border-radius: 6px;
margin-top: 10px;
font-size: 13px;
word-break: break-word;
}
.warning-message {
background: #fef3c7;
color: #92400e;
padding: 12px;
border-radius: 6px;
margin-top: 10px;
font-size: 13px;
}
.refresh-note {
text-align: center;
margin-top: 30px;
color: #6b7280;
font-size: 14px;
}
.refresh-btn {
background: #667eea;
color: white;
border: none;
padding: 12px 30px;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
margin-top: 10px;
transition: background 0.3s ease;
}
.refresh-btn:hover {
background: #5568d3;
}
.metric {
display: inline-block;
margin-right: 15px;
}
</style>
</head>
<body>
// Configuration
$config = [
'mysql' => [
'host' => 'localhost',
'port' => 3306,
'username' => 'root',
'password' => '', // Add your MySQL password
'database' => 'mysql' // or your database name
],
'elasticsearch' => [
'url' => 'http://127.0.0.1:9200'
]
];
// Initialize status
$checks = [];
// Check MySQL
function checkMySQL($config) {
$startTime = microtime(true);
$status = [
'status' => 'ok',
'name' => 'MySQL Database',
'message' => '',
'details' => []
];
try {
$mysqli = new mysqli(
$config['mysql']['host'],
$config['mysql']['username'],
$config['mysql']['password'],
$config['mysql']['database'],
$config['mysql']['port']
);
if ($mysqli->connect_error) {
throw new Exception($mysqli->connect_error);
}
$responseTime = round((microtime(true) - $startTime) * 1000, 2);
// Get MySQL version
$version = $mysqli->server_info;
// Check connection
$result = $mysqli->query("SELECT 1");
if (!$result) {
throw new Exception("Query failed");
}
// Get additional stats
$uptime = $mysqli->query("SHOW GLOBAL STATUS LIKE 'Uptime'")->fetch_assoc();
$connections = $mysqli->query("SHOW GLOBAL STATUS LIKE 'Threads_connected'")->fetch_assoc();
$maxConnections = $mysqli->query("SHOW VARIABLES LIKE 'max_connections'")->fetch_assoc();
$status['status'] = 'ok';
$status['message'] = 'MySQL is running and accessible';
$status['details'] = [
'response_time_ms' => $responseTime,
'version' => $version,
'uptime_seconds' => number_format($uptime['Value']),
'connections' => $connections['Value'] . ' / ' . $maxConnections['Value'],
'host' => $config['mysql']['host'] . ':' . $config['mysql']['port']
];
$mysqli->close();
} catch (Exception $e) {
$status['status'] = 'error';
$status['message'] = 'MySQL connection failed';
$status['error'] = $e->getMessage();
}
return $status;
}
// Check Elasticsearch
function checkElasticsearch($config) {
$startTime = microtime(true);
$status = [
'status' => 'ok',
'name' => 'Elasticsearch',
'message' => '',
'details' => []
];
try {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $config['elasticsearch']['url'] . '/_cluster/health');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$responseTime = round((microtime(true) - $startTime) * 1000, 2);
if (curl_errno($ch)) {
throw new Exception(curl_error($ch));
}
curl_close($ch);
if ($httpCode != 200) {
throw new Exception("HTTP " . $httpCode);
}
$health = json_decode($response, true);
if (!$health) {
throw new Exception("Invalid JSON response");
}
// Get additional cluster info
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $config['elasticsearch']['url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$infoResponse = curl_exec($ch);
curl_close($ch);
$info = json_decode($infoResponse, true);
// Determine status based on cluster health
$clusterStatus = $health['status'];
if ($clusterStatus === 'green') {
$status['status'] = 'ok';
$status['message'] = 'Elasticsearch cluster is healthy';
} elseif ($clusterStatus === 'yellow') {
$status['status'] = 'warning';
$status['message'] = 'Elasticsearch cluster status is YELLOW';
} else {
$status['status'] = 'error';
$status['message'] = 'Elasticsearch cluster status is RED';
}
$status['details'] = [
'response_time_ms' => $responseTime,
'cluster_name' => $health['cluster_name'],
'cluster_status' => strtoupper($health['status']),
'nodes' => $health['number_of_nodes'],
'data_nodes' => $health['number_of_data_nodes'],
'active_shards' => $health['active_shards'],
'version' => $info['version']['number'] ?? 'N/A'
];
if (isset($health['unassigned_shards']) && $health['unassigned_shards'] > 0) {
$status['details']['unassigned_shards'] = $health['unassigned_shards'];
}
} catch (Exception $e) {
$status['status'] = 'error';
$status['message'] = 'Elasticsearch connection failed';
$status['error'] = $e->getMessage();
}
return $status;
}
// Run checks
$checks['mysql'] = checkMySQL($config);
$checks['elasticsearch'] = checkElasticsearch($config);
// Determine overall status
foreach ($checks as $check) {
if ($check['status'] === 'error') {
'ok' = 'error';
break;
} elseif ($check['status'] === 'warning' && 'ok' !== 'error') {
'ok' = 'warning';
}
}
$timestamp = date('Y-m-d H:i:s T');
// If requested as JSON (for monitoring tools)
if (isset($_GET['format']) && $_GET['format'] === 'json') {
header('Content-Type: application/json');
$httpCode = ('ok' === 'ok') ? 200 : 503;
http_response_code($httpCode);
echo json_encode([
'status' => 'ok',
'timestamp' => $timestamp,
'checks' => $checks
], JSON_PRETTY_PRINT);
exit;
}
<div class="container">
<div class="header">
<span class="status-badge status-echo 'ok';">
echo strtoupper('ok');
</span>
<h1>Server Status</h1>
<p class="timestamp">echo $timestamp;</p>
</div>
<div class="checks">
foreach ($checks as $key => $check):
<div class="check-card">
<div class="check-header">
<div class="check-name">echo htmlspecialchars($check['name']);</div>
<div class="check-status echo $check['status'];"></div>
</div>
<div class="check-details">
<div><strong>Status:</strong> echo ucfirst($check['status']);</div>
<div><strong>Message:</strong> echo htmlspecialchars($check['message']);</div>
if (!empty($check['details'])):
foreach ($check['details'] as $detailKey => $detailValue):
<div>
<strong>echo ucfirst(str_replace('_', ' ', $detailKey));:</strong>
echo htmlspecialchars($detailValue);
</div>
endforeach;
endif;
</div>
if (isset($check['error'])):
<div class="echo $check['status'] === 'warning' ? 'warning-message' : 'error-message';">
<strong>Error:</strong> echo htmlspecialchars($check['error']);
</div>
endif;
</div>
endforeach;
</div>
<div class="refresh-note">
<button class="refresh-btn" onclick="window.location.reload()">
Refresh Status
</button>
<p style="margin-top: 15px; font-size: 12px;">
Auto-refreshes every 30 seconds |
<a href="?format=json" style="color: #667eea;">View JSON</a>
</p>
</div>
</div>
<script>
// Auto-refresh every 30 seconds
setTimeout(function() {
window.location.reload();
}, 30000);
</script>
</body>
</html>
© 2023 Quttera Ltd. All rights reserved.