When you run multiple video sites across different servers, monitoring is essential. Here's how I built a lightweight monitoring dashboard for TrendVidStream and its sister sites.
What to Monitor
For a multi-site video platform, the critical metrics are:
- Site availability - Is each site responding?
- Content freshness - When was the last successful fetch?
- Database health - SQLite integrity and size
- API quota - YouTube API usage
- Cache hit rates - Are caches working?
- Performance - PageSpeed scores over time
Health Check Endpoint
Each site exposes a /health endpoint:
<?php
// health.php
header('Content-Type: application/json');
header('Cache-Control: no-cache');
$db = new PDO('sqlite:' . __DIR__ . '/data/app.db');
// Check database
$dbOk = false;
try {
$result = $db->query('PRAGMA integrity_check')->fetchColumn();
$dbOk = ($result === 'ok');
} catch (Exception $e) {
$dbOk = false;
}
// Get last fetch time
$lastFetch = $db->query(
"SELECT MAX(fetched_at) FROM videos"
)->fetchColumn();
// Get video counts per region
$regions = $db->query(
"SELECT region, COUNT(*) as count FROM videos GROUP BY region"
)->fetchAll(PDO::FETCH_KEY_PAIR);
// Database file size
$dbSize = filesize(__DIR__ . '/data/app.db');
// Cache stats
$cacheDir = __DIR__ . '/data/cache';
$cacheFiles = glob($cacheDir . '/*.cache');
$cacheSize = array_sum(array_map('filesize', $cacheFiles ?: []));
$status = [
'status' => $dbOk ? 'healthy' : 'degraded',
'timestamp' => date('c'),
'php_version' => PHP_VERSION,
'sapi' => php_sapi_name(),
'database' => [
'ok' => $dbOk,
'size_mb' => round($dbSize / 1024 / 1024, 2),
'last_fetch' => $lastFetch,
'freshness_hours' => $lastFetch
? round((time() - strtotime($lastFetch)) / 3600, 1)
: null,
],
'regions' => $regions,
'cache' => [
'files' => count($cacheFiles ?: []),
'size_mb' => round($cacheSize / 1024 / 1024, 2),
],
'opcache' => function_exists('opcache_get_status')
? opcache_get_status(false)
: null,
];
http_response_code($dbOk ? 200 : 503);
echo json_encode($status, JSON_PRETTY_PRINT);
Dashboard Collector
A script that checks all sites periodically:
<?php
// monitor.php - Run from a monitoring server or local machine
$sites = [
'dwv' => 'https://dailywatch.video/health',
'tvh' => 'https://topvideohub.com/health',
'tvs' => 'https://trendvidstream.com/health',
'vvv' => 'https://viralvidvault.com/health',
];
$results = [];
foreach ($sites as $alias => $url) {
$start = microtime(true);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTPHEADER => ['Accept: application/json'],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$elapsed = round((microtime(true) - $start) * 1000);
curl_close($ch);
$data = json_decode($response, true);
$results[$alias] = [
'reachable' => $httpCode === 200,
'status' => $data['status'] ?? 'unreachable',
'response_ms' => $elapsed,
'last_fetch' => $data['database']['last_fetch'] ?? null,
'freshness_hours' => $data['database']['freshness_hours'] ?? null,
'db_size_mb' => $data['database']['size_mb'] ?? null,
'regions' => $data['regions'] ?? [],
'total_videos' => array_sum($data['regions'] ?? []),
];
}
// Display dashboard
echo "\n=== Multi-Site Video Platform Monitor ===";
echo "\n" . date('Y-m-d H:i:s') . "\n";
echo str_repeat('=', 60) . "\n\n";
foreach ($results as $alias => $r) {
$status = $r['reachable'] ? "OK" : "DOWN";
$fresh = $r['freshness_hours'] !== null
? "{$r['freshness_hours']}h ago"
: "unknown";
printf(
"%-5s | %-8s | %4dms | %5d videos | Last fetch: %s | DB: %sMB\n",
strtoupper($alias),
$status,
$r['response_ms'],
$r['total_videos'],
$fresh,
$r['db_size_mb'] ?? '?'
);
}
// Alert if any site is down or stale
$alerts = [];
foreach ($results as $alias => $r) {
if (!$r['reachable']) {
$alerts[] = "ALERT: {$alias} is unreachable";
}
if ($r['freshness_hours'] !== null && $r['freshness_hours'] > 12) {
$alerts[] = "ALERT: {$alias} last fetch was {$r['freshness_hours']} hours ago";
}
}
if (!empty($alerts)) {
echo "\n" . str_repeat('!', 60) . "\n";
foreach ($alerts as $alert) {
echo "$alert\n";
}
}
PageSpeed Monitoring
<?php
class PageSpeedMonitor
{
private string $apiKey;
public function __construct(string $apiKey)
{
$this->apiKey = $apiKey;
}
public function audit(string $url, string $strategy = 'mobile'): array
{
$apiUrl = 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed?'
. http_build_query([
'url' => $url,
'strategy' => $strategy,
'key' => $this->apiKey,
'category' => 'performance',
]);
$response = json_decode(file_get_contents($apiUrl), true);
$audit = $response['lighthouseResult'] ?? [];
return [
'score' => ($audit['categories']['performance']['score'] ?? 0) * 100,
'lcp' => $audit['audits']['largest-contentful-paint']['numericValue'] ?? 0,
'cls' => $audit['audits']['cumulative-layout-shift']['numericValue'] ?? 0,
'inp' => $audit['audits']['experimental-interaction-to-next-paint']['numericValue'] ?? 0,
];
}
}
// Monitor all sites
$monitor = new PageSpeedMonitor(getenv('PAGESPEED_API_KEY'));
$pages = [
'https://trendvidstream.com/',
'https://trendvidstream.com/category/music',
'https://trendvidstream.com/category/gaming',
];
foreach ($pages as $url) {
$result = $monitor->audit($url);
printf(
"%s\n Score: %d | LCP: %dms | CLS: %.3f\n",
$url,
$result['score'],
$result['lcp'],
$result['cls']
);
}
Cron-Based Monitoring
# Check health every 30 minutes
*/30 * * * * php /path/to/monitor.php >> /var/log/monitor.log 2>&1
# PageSpeed audit twice daily
0 6,18 * * * php /path/to/pagespeed_audit.php >> /var/log/pagespeed.log 2>&1
This monitoring system keeps all 4 TrendVidStream sites healthy. The health endpoint pattern is reusable for any PHP application with SQLite.
Key principle: monitor what matters (availability, freshness, performance), alert on what is actionable, and keep the monitoring infrastructure simpler than what it monitors.
Top comments (1)
Useful breakdown, especially separating availability, freshness, quota, cache behaviour, and PageSpeed instead of collapsing everything into a single “site health” number.
One thing we’ve found helpful in multi-site setups is splitting performance monitoring into two layers:
That matters on video-heavy estates because a drop in PageSpeed can come from very different causes: heavier embeds, player script changes, image payload creep, or third-party tag drift. If you only look at one headline score, you see the symptom but not the pattern.
The health endpoint approach here makes sense as the operational base layer.