diff --git a/modules/pihole/design.json b/modules/pihole/design.json index 4e1a89e..7093477 100644 --- a/modules/pihole/design.json +++ b/modules/pihole/design.json @@ -3,7 +3,8 @@ "title": "Pi-hole", "description": "Pi-hole Monitoring, Listen und Steuerung fuer mehrere Instanzen.", "actions": [ - { "label": "Zur Startseite", "href": "/", "variant": "ghost" } + { "label": "Setup", "href": "/modules/setup/pihole", "variant": "ghost" }, + { "label": "Instanzen", "href": "/module/pihole/instances", "variant": "secondary" } ], "tabs": [ { "label": "Dashboard", "href": "/module/pihole" }, diff --git a/modules/pihole/pages/api.php b/modules/pihole/pages/api.php index 76f2d4a..261b71a 100644 --- a/modules/pihole/pages/api.php +++ b/modules/pihole/pages/api.php @@ -21,6 +21,10 @@ $respond = function (array $data, int $status = 200): void { exit; }; +$debugPush = static function (string $label, array $payload = []): void { + module_debug_push('pihole', array_merge(['label' => $label], $payload)); +}; + $normalizeApiPath = function (string $baseUrl, string $apiPath): string { $base = rtrim($baseUrl, '/'); $path = $apiPath; @@ -221,6 +225,28 @@ $detectApi = function (array $instance) use ($v6Auth, $v6RequestAny, $v5Request) return ['version' => 0, 'sid' => '', 'probe' => $probe, 'legacy' => $legacy]; }; +$debugResult = static function (string $label, string $instanceId, array $instance, array $result) use ($debugPush): void { + $payload = [ + 'instance_id' => $instanceId, + 'instance_name' => (string)($instance['name'] ?? $instanceId), + 'url' => (string)($instance['url'] ?? ''), + 'ok' => (bool)($result['ok'] ?? false), + 'http_code' => (int)($result['http_code'] ?? 0), + 'error' => (string)($result['error'] ?? ''), + 'error_key' => (string)($result['error_key'] ?? ''), + 'hint' => $result['hint'] ?? null, + 'request_url' => (string)($result['url'] ?? ''), + ]; + + if (isset($result['data']) && is_array($result['data'])) { + $payload['response'] = $result['data']; + } elseif (isset($result['raw'])) { + $payload['raw'] = (string)$result['raw']; + } + + $debugPush($label, $payload); +}; + $resolvePrimaryId = function () use ($instances): ?string { foreach ($instances as $id => $row) { if (!empty($row['is_primary'])) { @@ -322,6 +348,11 @@ if ($action === 'dashboard') { $respond(['ok' => false, 'error' => 'no_instances'], 400); } + $debugPush('dashboard.request', [ + 'action' => $action, + 'instance_count' => count($instances), + ]); + $aggregate = [ 'summary' => [ 'dns_queries_today' => 0, @@ -370,14 +401,22 @@ if ($action === 'dashboard') { $versionsData = null; $apiInfo = $detectApi($instance); + $debugPush('api.detect.result', [ + 'instance_id' => $id, + 'instance_name' => (string)($instance['name'] ?? $id), + 'version' => (int)($apiInfo['version'] ?? 0), + 'sid_present' => !empty($apiInfo['sid']), + ]); if ($apiInfo['version'] === 6) { $sid = (string)($apiInfo['sid'] ?? ''); $summary = $apiInfo['probe']; + $debugResult('dashboard.summary', $id, $instance, $summary); if (!$summary['ok']) { $errors[] = $makeError('summary', $summary); } $blocking = $v6RequestAny($instance, ['dns/blocking'], 'GET', [], $sid); + $debugResult('dashboard.blocking', $id, $instance, $blocking); if (!$blocking['ok']) { $errors[] = $makeError('blocking', $blocking); } @@ -388,11 +427,13 @@ if ($action === 'dashboard') { 'queries?from=' . $from . '&until=' . $now, 'queries/all?from=' . $from . '&until=' . $now, ], 'GET', [], $sid); + $debugResult('dashboard.queries', $id, $instance, $queries); if (!$queries['ok']) { $errors[] = $makeError('queries', $queries); } $upstreams = $v6RequestAny($instance, ['stats/upstreams', 'upstreams'], 'GET', [], $sid); + $debugResult('dashboard.upstreams', $id, $instance, $upstreams); if (!$upstreams['ok']) { $errors[] = $makeError('upstreams', $upstreams); } @@ -522,6 +563,13 @@ if ($action === 'dashboard') { $forwardDest = $v5Request($instance, ['getForwardDestinations' => 1]); $recentBlocked = $v5Request($instance, ['recentBlocked' => 30]); $versions = $v5Request($instance, ['versions' => 1]); + $debugResult('dashboard.summary', $id, $instance, $summary); + $debugResult('dashboard.topItems', $id, $instance, $topItems); + $debugResult('dashboard.queryTypes', $id, $instance, $queryTypes); + $debugResult('dashboard.querySources', $id, $instance, $querySources); + $debugResult('dashboard.forwardDestinations', $id, $instance, $forwardDest); + $debugResult('dashboard.recentBlocked', $id, $instance, $recentBlocked); + $debugResult('dashboard.versions', $id, $instance, $versions); if (!$summary['ok']) { $errors[] = $makeError('summary', $summary); @@ -555,6 +603,9 @@ if ($action === 'dashboard') { $updates = $parseUpdates(is_array($versionsData) ? $versionsData : null); } else { $probe = $apiInfo['probe'] ?? ['error' => 'unknown']; + if (is_array($probe)) { + $debugResult('dashboard.probe', $id, $instance, $probe); + } $errors[] = $makeError('probe', is_array($probe) ? $probe : ['error' => 'unknown']); } @@ -647,6 +698,11 @@ if ($action === 'dashboard') { } $aggregate['summary']['status'] = $status; + $debugPush('dashboard.response', [ + 'aggregate_summary' => $aggregate['summary'], + 'instance_ids' => array_keys($instancePayloads), + ]); + $respond([ 'ok' => true, 'ts' => time(), @@ -666,9 +722,21 @@ if ($action === 'test') { } $instance = $instances[$target]; + $debugPush('test.request', [ + 'instance_id' => $target, + 'instance_name' => (string)($instance['name'] ?? $target), + 'url' => (string)($instance['url'] ?? ''), + ]); $apiInfo = $detectApi($instance); + $debugPush('test.detect.result', [ + 'instance_id' => $target, + 'version' => (int)($apiInfo['version'] ?? 0), + 'sid_present' => !empty($apiInfo['sid']), + ]); + if (!empty($apiInfo['probe']) && is_array($apiInfo['probe'])) { + $debugResult('test.probe', $target, $instance, $apiInfo['probe']); + } if ($apiInfo['version'] === 6) { - $sid = (string)($apiInfo['sid'] ?? ''); $result = $apiInfo['probe']; if ($result['ok']) { $respond([ @@ -746,6 +814,7 @@ if ($action === 'test') { if ($action === 'disable') { require_admin(); + $debugPush('disable.request', ['payload' => $payload]); $minutes = (int)($payload['minutes'] ?? 0); $target = (string)($payload['instance'] ?? 'all'); if ($minutes <= 0) { @@ -771,12 +840,14 @@ if ($action === 'disable') { $result = ['ok' => false, 'error' => 'unknown_api', 'http_code' => 0, 'url' => '']; } $results[$id] = $result; + $debugResult('disable.result', $id, $instance, $result); } $respond(['ok' => true, 'results' => $results]); } if ($action === 'enable') { require_admin(); + $debugPush('enable.request', ['payload' => $payload]); $target = (string)($payload['instance'] ?? 'all'); $targets = $pickInstances($target); if (!$targets) { @@ -797,12 +868,14 @@ if ($action === 'enable') { $result = ['ok' => false, 'error' => 'unknown_api', 'http_code' => 0, 'url' => '']; } $results[$id] = $result; + $debugResult('enable.result', $id, $instance, $result); } $respond(['ok' => true, 'results' => $results]); } if ($action === 'gravity') { require_admin(); + $debugPush('gravity.request', ['payload' => $payload]); $target = $listsPrimaryOnly ? 'primary' : (string)($payload['instance'] ?? 'primary'); $targets = $pickInstances($target); if (!$targets) { @@ -820,12 +893,14 @@ if ($action === 'gravity') { $result = ['ok' => false, 'error' => 'unknown_api', 'http_code' => 0, 'url' => '']; } $results[$id] = $result; + $debugResult('gravity.result', $id, $instance, $result); } $respond(['ok' => true, 'results' => $results]); } if ($action === 'domain_add') { require_admin(); + $debugPush('domain_add.request', ['payload' => $payload]); $domain = trim((string)($payload['domain'] ?? '')); $type = (string)($payload['type'] ?? 'block'); if ($domain === '') { @@ -852,12 +927,14 @@ if ($action === 'domain_add') { $result = ['ok' => false, 'error' => 'unknown_api', 'http_code' => 0, 'url' => '']; } $results[$id] = $result; + $debugResult('domain_add.result', $id, $instance, $result); } $respond(['ok' => true, 'results' => $results]); } if ($action === 'adlist_add') { require_admin(); + $debugPush('adlist_add.request', ['payload' => $payload]); $url = trim((string)($payload['url'] ?? '')); if ($url === '') { $respond(['ok' => false, 'error' => 'missing_url'], 400); @@ -879,12 +956,14 @@ if ($action === 'adlist_add') { $result = ['ok' => false, 'error' => 'unknown_api', 'http_code' => 0, 'url' => '']; } $results[$id] = $result; + $debugResult('adlist_add.result', $id, $instance, $result); } $respond(['ok' => true, 'results' => $results]); } if ($action === 'update') { require_admin(); + $debugPush('update.request', ['payload' => $payload]); $target = (string)($payload['instance'] ?? 'primary'); $targets = $pickInstances($target); if (!$targets) { @@ -902,6 +981,7 @@ if ($action === 'update') { $result = ['ok' => false, 'error' => 'unknown_api', 'http_code' => 0, 'url' => '']; } $results[$id] = $result; + $debugResult('update.result', $id, $instance, $result); } $respond(['ok' => true, 'results' => $results]); }