feat: add GlitchTip test page and PUBLIC_UMAMI_SCRIPT_URL to ui env
Some checks failed
CI / Test backend (pull_request) Successful in 19s
CI / Check ui (pull_request) Successful in 40s
CI / Docker / caddy (pull_request) Failing after 43s
CI / Docker / ui (pull_request) Successful in 1m17s
CI / Docker / backend (pull_request) Successful in 1m58s
CI / Docker / runner (pull_request) Successful in 2m12s
Some checks failed
CI / Test backend (pull_request) Successful in 19s
CI / Check ui (pull_request) Successful in 40s
CI / Docker / caddy (pull_request) Failing after 43s
CI / Docker / ui (pull_request) Successful in 1m17s
CI / Docker / backend (pull_request) Successful in 1m58s
CI / Docker / runner (pull_request) Successful in 2m12s
This commit is contained in:
@@ -160,6 +160,7 @@ services:
|
|||||||
LOG_LEVEL: "${LOG_LEVEL}"
|
LOG_LEVEL: "${LOG_LEVEL}"
|
||||||
KOKORO_URL: "${KOKORO_URL}"
|
KOKORO_URL: "${KOKORO_URL}"
|
||||||
KOKORO_VOICE: "${KOKORO_VOICE}"
|
KOKORO_VOICE: "${KOKORO_VOICE}"
|
||||||
|
GLITCHTIP_DSN: "${GLITCHTIP_DSN}"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "/healthcheck", "http://localhost:8080/health"]
|
test: ["CMD", "/healthcheck", "http://localhost:8080/health"]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
@@ -167,7 +168,11 @@ services:
|
|||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
# ─── Runner (background task worker) ─────────────────────────────────────────
|
# ─── Runner (background task worker) ─────────────────────────────────────────
|
||||||
|
# profiles: [runner] prevents accidental restart on `docker compose up -d`.
|
||||||
|
# The homelab runner (192.168.0.109) is the sole worker in production.
|
||||||
|
# To start explicitly: doppler run -- docker compose --profile runner up -d runner
|
||||||
runner:
|
runner:
|
||||||
|
profiles: [runner]
|
||||||
image: kalekber/libnovel-runner:${GIT_TAG:-latest}
|
image: kalekber/libnovel-runner:${GIT_TAG:-latest}
|
||||||
build:
|
build:
|
||||||
context: ./backend
|
context: ./backend
|
||||||
@@ -211,6 +216,7 @@ services:
|
|||||||
# Kokoro-FastAPI TTS endpoint
|
# Kokoro-FastAPI TTS endpoint
|
||||||
KOKORO_URL: "${KOKORO_URL}"
|
KOKORO_URL: "${KOKORO_URL}"
|
||||||
KOKORO_VOICE: "${KOKORO_VOICE}"
|
KOKORO_VOICE: "${KOKORO_VOICE}"
|
||||||
|
GLITCHTIP_DSN: "${GLITCHTIP_DSN}"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
# The runner writes /tmp/runner.alive on every poll.
|
# The runner writes /tmp/runner.alive on every poll.
|
||||||
# 120s = 2× the default 30s poll interval with generous headroom.
|
# 120s = 2× the default 30s poll interval with generous headroom.
|
||||||
@@ -256,6 +262,11 @@ services:
|
|||||||
PUBLIC_MINIO_PUBLIC_URL: "${MINIO_PUBLIC_ENDPOINT}"
|
PUBLIC_MINIO_PUBLIC_URL: "${MINIO_PUBLIC_ENDPOINT}"
|
||||||
# Valkey
|
# Valkey
|
||||||
VALKEY_ADDR: "valkey:6379"
|
VALKEY_ADDR: "valkey:6379"
|
||||||
|
# Umami analytics
|
||||||
|
PUBLIC_UMAMI_WEBSITE_ID: "${PUBLIC_UMAMI_WEBSITE_ID}"
|
||||||
|
PUBLIC_UMAMI_SCRIPT_URL: "${PUBLIC_UMAMI_SCRIPT_URL}"
|
||||||
|
# GlitchTip client + server-side error tracking
|
||||||
|
PUBLIC_GLITCHTIP_DSN: "${PUBLIC_GLITCHTIP_DSN}"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
|
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
@@ -556,7 +567,7 @@ services:
|
|||||||
GOTIFY_DEFAULTUSER_PASS: "${GOTIFY_ADMIN_PASS}"
|
GOTIFY_DEFAULTUSER_PASS: "${GOTIFY_ADMIN_PASS}"
|
||||||
GOTIFY_SERVER_PORT: "80"
|
GOTIFY_SERVER_PORT: "80"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "-qO-", "http://localhost:80/health"]
|
test: ["CMD", "curl", "-sf", "http://localhost:80/health"]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|||||||
@@ -171,10 +171,10 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>libnovel</title>
|
<title>libnovel</title>
|
||||||
<!-- Umami analytics — no-op when PUBLIC_UMAMI_WEBSITE_ID is unset -->
|
<!-- Umami analytics — no-op when PUBLIC_UMAMI_WEBSITE_ID is unset -->
|
||||||
{#if env.PUBLIC_UMAMI_WEBSITE_ID}
|
{#if env.PUBLIC_UMAMI_WEBSITE_ID && env.PUBLIC_UMAMI_SCRIPT_URL}
|
||||||
<script
|
<script
|
||||||
defer
|
defer
|
||||||
src="https://analytics.libnovel.cc/script.js"
|
src={env.PUBLIC_UMAMI_SCRIPT_URL}
|
||||||
data-website-id={env.PUBLIC_UMAMI_WEBSITE_ID}
|
data-website-id={env.PUBLIC_UMAMI_WEBSITE_ID}
|
||||||
></script>
|
></script>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
10
ui/src/routes/glitchtip-test/+page.server.ts
Normal file
10
ui/src/routes/glitchtip-test/+page.server.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async ({ url }) => {
|
||||||
|
if (url.searchParams.get('server_error') === '1') {
|
||||||
|
// This unhandled throw is caught by handleError in hooks.server.ts,
|
||||||
|
// which forwards it to GlitchTip via Sentry.captureException.
|
||||||
|
throw new Error('GlitchTip server-side test error — ' + new Date().toISOString());
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
48
ui/src/routes/glitchtip-test/+page.svelte
Normal file
48
ui/src/routes/glitchtip-test/+page.svelte
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import * as Sentry from '@sentry/sveltekit';
|
||||||
|
import { Button } from '$lib/components/ui/button';
|
||||||
|
|
||||||
|
function throwClientError() {
|
||||||
|
throw new Error('GlitchTip client-side test error — ' + new Date().toISOString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function captureManual() {
|
||||||
|
Sentry.captureException(
|
||||||
|
new Error('GlitchTip manual capture test — ' + new Date().toISOString())
|
||||||
|
);
|
||||||
|
alert('Manually captured exception sent to GlitchTip.');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="max-w-lg mx-auto py-16 flex flex-col gap-6">
|
||||||
|
<h1 class="text-2xl font-bold text-zinc-100">GlitchTip Test Page</h1>
|
||||||
|
<p class="text-zinc-400 text-sm">
|
||||||
|
Use the buttons below to fire test errors. Check
|
||||||
|
<a
|
||||||
|
href="https://errors.libnovel.cc"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="text-amber-400 hover:text-amber-300 underline">errors.libnovel.cc</a
|
||||||
|
> to confirm they arrive.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<!-- Triggers an unhandled JS exception → caught by handleError in hooks.client.ts -->
|
||||||
|
<Button variant="destructive" onclick={throwClientError}>
|
||||||
|
Throw unhandled client-side error
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Sends an exception directly via Sentry.captureException -->
|
||||||
|
<Button variant="outline" onclick={captureManual}>
|
||||||
|
Manually capture exception (Sentry.captureException)
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- SSR load error — visit this URL to trigger a server-side throw -->
|
||||||
|
<a
|
||||||
|
href="/glitchtip-test?server_error=1"
|
||||||
|
class="text-sm text-zinc-400 hover:text-amber-400 underline text-center"
|
||||||
|
>
|
||||||
|
Trigger server-side load error (navigate here with ?server_error=1)
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user