Ajoute endpoint probe health
This commit is contained in:
+101
-4
@@ -1,10 +1,6 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/src/lib/admin.php';
|
||||
|
||||
$config = gridtv_load_config();
|
||||
gridtv_require_admin($config, 'Health');
|
||||
[$locale, $L] = gridtv_load_locale($config);
|
||||
|
||||
function health_status_class(bool $ok): string {
|
||||
return $ok ? 'ok' : 'ko';
|
||||
}
|
||||
@@ -80,6 +76,69 @@ function health_format_xmltv_stamp(?string $stamp): string {
|
||||
return $dt->format('d/m/Y H:i');
|
||||
}
|
||||
|
||||
function health_probe_payload(): array {
|
||||
$config_path = gridtv_config_path();
|
||||
$config_exists = file_exists($config_path);
|
||||
$config_valid = false;
|
||||
$config = [];
|
||||
|
||||
if ($config_exists) {
|
||||
$decoded = json_decode(file_get_contents($config_path), true);
|
||||
if (is_array($decoded)) {
|
||||
$config = $decoded;
|
||||
$config_valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
$sources = $config_valid ? array_values($config['epg_sources'] ?? []) : [];
|
||||
$first_source = $sources[0] ?? null;
|
||||
|
||||
$checks = [
|
||||
'config_exists' => $config_exists,
|
||||
'config_valid' => $config_valid,
|
||||
'php_curl' => extension_loaded('curl'),
|
||||
'php_xml' => class_exists('DOMDocument'),
|
||||
'source_configured' => !empty($sources),
|
||||
];
|
||||
|
||||
$details = [
|
||||
'group_name' => $config['group_name'] ?? 'GridTV',
|
||||
'source_count' => count($sources),
|
||||
];
|
||||
|
||||
if ($first_source && !empty($first_source['epg_url'])) {
|
||||
$fetch = gridtv_fetch_url((string) $first_source['epg_url'], 12);
|
||||
$checks['xmltv_reachable'] = $fetch['ok'];
|
||||
$details['xmltv_status'] = $fetch['status'];
|
||||
$details['xmltv_time_total'] = round((float) $fetch['time_total'], 3);
|
||||
if ($fetch['ok']) {
|
||||
$stats = health_parse_xmltv($fetch['body']);
|
||||
$checks['xmltv_valid'] = !empty($stats['ok']);
|
||||
if (!empty($stats['ok'])) {
|
||||
$details['xmltv_channels'] = $stats['channels'];
|
||||
$details['xmltv_programmes'] = $stats['programmes'];
|
||||
} else {
|
||||
$details['xmltv_error'] = $stats['error'] ?? 'Invalid XMLTV';
|
||||
}
|
||||
} else {
|
||||
$details['xmltv_error'] = $fetch['error'] ?: ('HTTP ' . $fetch['status']);
|
||||
}
|
||||
} else {
|
||||
$checks['xmltv_reachable'] = false;
|
||||
$details['xmltv_error'] = 'No XMLTV source configured';
|
||||
}
|
||||
|
||||
$ok = !in_array(false, $checks, true);
|
||||
|
||||
return [
|
||||
'ok' => $ok,
|
||||
'status' => $ok ? 'ok' : 'degraded',
|
||||
'timestamp' => gmdate('c'),
|
||||
'checks' => $checks,
|
||||
'details' => $details,
|
||||
];
|
||||
}
|
||||
|
||||
function health_build_payload(array $config, string $locale): array {
|
||||
$config_path = gridtv_config_path();
|
||||
$config_exists = file_exists($config_path);
|
||||
@@ -164,6 +223,23 @@ function health_build_payload(array $config, string $locale): array {
|
||||
];
|
||||
}
|
||||
|
||||
if (isset($_GET['format']) && $_GET['format'] === 'probe') {
|
||||
$payload = health_probe_payload();
|
||||
http_response_code($payload['ok'] ? 200 : 503);
|
||||
if (isset($_GET['plain']) && $_GET['plain'] === '1') {
|
||||
header('Content-Type: text/plain; charset=UTF-8');
|
||||
echo $payload['ok'] ? 'OK' : 'KO';
|
||||
} else {
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
echo json_encode($payload, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
$config = gridtv_load_config();
|
||||
gridtv_require_admin($config, 'Health');
|
||||
[$locale, $L] = gridtv_load_locale($config);
|
||||
|
||||
if (isset($_GET['format']) && $_GET['format'] === 'json') {
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
echo json_encode(health_build_payload($config, $locale), JSON_UNESCAPED_SLASHES);
|
||||
@@ -184,6 +260,12 @@ if (isset($_GET['format']) && $_GET['format'] === 'json') {
|
||||
.logo{font-family:'Share Tech Mono',monospace;font-size:26px;letter-spacing:.12em;color:var(--accent);text-transform:uppercase}
|
||||
.subtitle{color:var(--muted);font-size:14px;max-width:700px;line-height:1.5}
|
||||
.actions{display:flex;gap:10px;flex-wrap:wrap}.btn{display:inline-flex;align-items:center;gap:8px;padding:11px 14px;border:1px solid var(--border);background:var(--surface);color:var(--text);text-decoration:none;font-size:13px;letter-spacing:.08em;text-transform:uppercase}.btn-primary{background:var(--accent);color:#000;border-color:var(--accent)}
|
||||
.probe-box{margin-bottom:20px;padding:18px 20px;background:rgba(19,22,27,.95);border:1px solid var(--border)}
|
||||
.probe-box h2{margin:0 0 10px;font-size:18px;letter-spacing:.06em;text-transform:uppercase}
|
||||
.probe-box p{margin:0 0 12px;color:var(--muted);font-size:13px;line-height:1.5}
|
||||
.probe-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}
|
||||
.probe-item{padding:12px;background:var(--surface2);border:1px solid var(--border)}
|
||||
.probe-item .eyebrow{margin-bottom:6px}
|
||||
.grid,.checks,.source-list{display:grid;gap:14px}.grid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin-bottom:22px}.checks{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin-bottom:24px}.source-list{gap:18px}
|
||||
.card,.source,.check{background:rgba(19,22,27,.95);border:1px solid var(--border)}.card,.check,.source{padding:16px}.source{padding:20px}
|
||||
.eyebrow{font-family:'Share Tech Mono',monospace;font-size:11px;color:var(--accent2);letter-spacing:.12em;text-transform:uppercase;margin-bottom:10px}.value{font-size:28px;font-weight:700}.small{font-size:13px;color:var(--muted)}
|
||||
@@ -218,6 +300,21 @@ if (isset($_GET['format']) && $_GET['format'] === 'json') {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="probe-box">
|
||||
<h2>Monitoring probe</h2>
|
||||
<p>Use these public endpoints with Uptime Kuma or any HTTP monitoring tool. They return <code>200</code> when the instance is healthy and <code>503</code> when a critical check fails.</p>
|
||||
<div class="probe-grid">
|
||||
<div class="probe-item">
|
||||
<div class="eyebrow">JSON probe</div>
|
||||
<div class="mono"><?= htmlspecialchars(strtok($_SERVER['REQUEST_URI'] ?? '/health.php', '?')) ?>?format=probe</div>
|
||||
</div>
|
||||
<div class="probe-item">
|
||||
<div class="eyebrow">Plain text probe</div>
|
||||
<div class="mono"><?= htmlspecialchars(strtok($_SERVER['REQUEST_URI'] ?? '/health.php', '?')) ?>?format=probe&plain=1</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="grid" id="summaryGrid">
|
||||
<div class="card skeleton"><div class="eyebrow">Group</div><div class="skeleton-line"></div><div class="skeleton-line short"></div></div>
|
||||
<div class="card skeleton"><div class="eyebrow">Sources</div><div class="skeleton-line"></div><div class="skeleton-line short"></div></div>
|
||||
|
||||
Reference in New Issue
Block a user