0.2.79 - Slow api fixes

This commit is contained in:
ponzischeme89
2026-08-19 18:08:00 +12:00
parent 590e069366
commit 0782545013
41 changed files with 1820 additions and 317 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "memby-admin",
"private": true,
"version": "0.1.39",
"version": "0.1.40",
"type": "module",
"description": "The Memby operations console. Built by Vite, served by the memby-admin container, proxied by the gateway at /admin.",
"scripts": {
+2
View File
@@ -752,6 +752,7 @@ export interface GatewaySettings {
sonarrAlertMinutes: number;
radarrAlertMinutes: number;
embyHealthSeconds: number;
slowRequestMillis: number;
librarySyncMinutes: number;
updatedAt?: string;
updatedBy?: string;
@@ -766,6 +767,7 @@ export interface GatewaySettingValues {
sonarrAlertMinutes: number;
radarrAlertMinutes: number;
embyHealthSeconds: number;
slowRequestMillis: number;
librarySyncMinutes: number;
}
+13 -2
View File
@@ -373,7 +373,13 @@ export const DRAWER_SECTIONS: { title: string; keys: string[] }[] = [
'watched', 'subtitles', 'subtitle_track', 'subtitle_language', 'event_name',
],
},
{ title: 'Diagnostics', keys: ['error', 'stack', 'correlation', 'version', 'gateway_version', 'duration'] },
// The breakdown is the answer to the question the duration column can only ask, so it
// gets a heading of its own rather than sitting among the diagnostics. `elsewhere` is
// the request's own time less its largest stage: not "gateway processing" — the stages
// overlap, so no such figure exists — but the honest answer to whether any of it is
// unaccounted for.
{ title: 'Where the time went', keys: ['duration', 'breakdown', 'elsewhere'] },
{ title: 'Diagnostics', keys: ['error', 'stack', 'correlation', 'version', 'gateway_version'] },
];
const SECTIONED = new Set(DRAWER_SECTIONS.flatMap((section) => section.keys));
@@ -447,7 +453,12 @@ function derive(event: LogEvent): Shaped {
// most of a log — keeps its identity at the end of its own line instead, because density
// is the whole reason this page is worth watching and a second line on every request
// would halve what an operator can see at once.
const secondary = detail || (isRequest ? '' : context);
// A slow request earns the second line every other request is denied. It is exactly
// the case density was being protected for: these are rare by definition, and the whole
// point of measuring where the time went is that an operator scanning the log can see it
// without opening anything.
const breakdown = text(attributes.breakdown);
const secondary = detail || (isRequest ? breakdown : context);
const secondaryTone: Shaped['secondaryTone'] = detail ? 'error' : secondary ? 'context' : '';
const trail = !detail && isRequest ? context : '';
+18 -1
View File
@@ -53,6 +53,7 @@ interface Draft {
sonarrAlertMinutes: string;
radarrAlertMinutes: string;
embyHealthSeconds: string;
slowRequestMillis: string;
librarySyncMinutes: string;
}
@@ -64,6 +65,7 @@ function draftFrom(settings: GatewaySettings): Draft {
sonarrAlertMinutes: numberFieldValue(settings.sonarrAlertMinutes),
radarrAlertMinutes: numberFieldValue(settings.radarrAlertMinutes),
embyHealthSeconds: numberFieldValue(settings.embyHealthSeconds),
slowRequestMillis: numberFieldValue(settings.slowRequestMillis),
librarySyncMinutes: numberFieldValue(settings.librarySyncMinutes),
};
}
@@ -94,6 +96,7 @@ export function SettingsPage() {
sonarrAlertMinutes: parseNumberField(draft.sonarrAlertMinutes, true),
radarrAlertMinutes: parseNumberField(draft.radarrAlertMinutes, true),
embyHealthSeconds: parseNumberField(draft.embyHealthSeconds, true),
slowRequestMillis: parseNumberField(draft.slowRequestMillis, true),
librarySyncMinutes: parseNumberField(draft.librarySyncMinutes, true),
};
const saved = await wrap(
@@ -113,7 +116,7 @@ export function SettingsPage() {
const saved = await wrap(
() => api.post<GatewaySettingsResponse>('/admin/api/gateway-settings', {
timezone: '', logLevel: '', sessionIdleDays: 0,
sonarrAlertMinutes: 0, radarrAlertMinutes: 0, embyHealthSeconds: 0,
sonarrAlertMinutes: 0, radarrAlertMinutes: 0, embyHealthSeconds: 0, slowRequestMillis: 0,
librarySyncMinutes: 0,
}),
'Every setting is back to what this container was deployed with.',
@@ -151,6 +154,7 @@ export function SettingsPage() {
{ label: 'Log level', value: effective.logLevel },
{ label: 'Sign-in expiry', value: describe(effective.sessionIdleDays, 'day') },
{ label: 'Emby health probe', value: describe(effective.embyHealthSeconds, 'second') },
{ label: 'Slow-request breakdown', value: describe(effective.slowRequestMillis, 'millisecond') },
{ label: 'Catalogue sweep', value: describe(effective.librarySyncMinutes, 'minute') },
{ label: 'Episode alert window', value: describe(effective.sonarrAlertMinutes, 'minute') },
{ label: 'Film alert window', value: describe(effective.radarrAlertMinutes, 'minute') },
@@ -216,6 +220,19 @@ export function SettingsPage() {
/>
</Field>
<Field
label="Slow-request breakdown above (ms)"
hint={`Deployed: ${deployed.slowRequestMillis || 'off'}. A request slower than this logs where its time went — Emby, Postgres, Redis, row assembly. Lower it while chasing one slow screen; type off to stop annotating altogether.`}
>
<input
type="text"
inputMode="numeric"
value={draft.slowRequestMillis}
placeholder={String(deployed.slowRequestMillis)}
onChange={(event) => set('slowRequestMillis', event.target.value)}
/>
</Field>
<Field
label="Emby health probe (seconds)"
hint={`Deployed: ${deployed.embyHealthSeconds || 'off'}. How often the gateway asks Emby whether it is answering. Type off to stop probing, which also removes the outage bar from every television.`}