Add per-server telemetry request diagnostics
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { getServer } from '$lib/server/fleet/servers.js';
|
||||
import { listTelemetryRequests } from '$lib/server/fleet/telemetry-requests.js';
|
||||
import { TELEMETRY_REQUEST_RETENTION } from '$lib/telemetry-diagnostics.js';
|
||||
|
||||
export async function GET({ params }: { params: { name: string } }) {
|
||||
if (!getServer(params.name)) return json({ ok: false, error: 'no such server' }, { status: 404 });
|
||||
return json({ ok: true, requests: listTelemetryRequests(params.name), retention: TELEMETRY_REQUEST_RETENTION }, {
|
||||
headers: { 'Cache-Control': 'no-store' }
|
||||
});
|
||||
}
|
||||
@@ -2,26 +2,51 @@ import { json } from '@sveltejs/kit';
|
||||
import { parseGameEvent, type GameTelemetry } from '$lib/telemetry.js';
|
||||
import { getServer } from '$lib/server/fleet/servers.js';
|
||||
import { saveTelemetry } from '$lib/server/fleet/telemetry.js';
|
||||
import { recordTelemetryRequest } from '$lib/server/fleet/telemetry-requests.js';
|
||||
import { recordGameEvent } from '$lib/server/fleet/beta-tests.js';
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
import { emit } from '$lib/server/pipeline/bus.js';
|
||||
|
||||
export async function POST({ request }: { request: Request }) {
|
||||
if (request.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== 'application/json') {
|
||||
return json({ ok: false, error: 'Content-Type must be application/json' }, { status: 415 });
|
||||
}
|
||||
const receivedAt = new Date().toISOString();
|
||||
const contentType = request.headers.get('content-type');
|
||||
let value: unknown;
|
||||
let malformed = false;
|
||||
try { value = await request.json(); }
|
||||
catch { return json({ ok: false, error: 'Malformed JSON' }, { status: 400 }); }
|
||||
catch { malformed = true; }
|
||||
|
||||
function log(status: number, error: string | null): void {
|
||||
try { recordTelemetryRequest({ value, receivedAt, status, error, contentType }); }
|
||||
catch (error) {
|
||||
// Diagnostics must not turn a saved report into a failed request.
|
||||
console.error('Could not record telemetry request diagnostics', error);
|
||||
}
|
||||
}
|
||||
function reject(status: number, error: string): Response {
|
||||
log(status, error);
|
||||
return json({ ok: false, error }, { status });
|
||||
}
|
||||
// Even a wrong content type may carry readable JSON with a server name.
|
||||
if (contentType?.split(';')[0].trim().toLowerCase() !== 'application/json') {
|
||||
return reject(415, 'Content-Type must be application/json');
|
||||
}
|
||||
if (malformed) return reject(400, 'Malformed JSON');
|
||||
let telemetry: GameTelemetry;
|
||||
try { telemetry = { ...parseGameEvent(value), receivedAt: new Date().toISOString() }; }
|
||||
catch (error) { return json({ ok: false, error: (error as Error).message }, { status: 400 }); }
|
||||
const server = getServer(telemetry.server);
|
||||
if (!server || server.destroyed_at) return json({ ok: false, error: 'Server is not registered or has been destroyed' }, { status: 404 });
|
||||
db().transaction(() => {
|
||||
saveTelemetry(telemetry);
|
||||
recordGameEvent(telemetry);
|
||||
})();
|
||||
emit({ type: 'server-telemetry', entries: [telemetry] });
|
||||
try { telemetry = { ...parseGameEvent(value), receivedAt }; }
|
||||
catch (error) { return reject(400, (error as Error).message); }
|
||||
try {
|
||||
const server = getServer(telemetry.server);
|
||||
if (!server || server.destroyed_at) return reject(404, 'Server is not registered or has been destroyed');
|
||||
db().transaction(() => {
|
||||
saveTelemetry(telemetry);
|
||||
recordGameEvent(telemetry);
|
||||
})();
|
||||
emit({ type: 'server-telemetry', entries: [telemetry] });
|
||||
} catch (error) {
|
||||
console.error('Could not process telemetry', error);
|
||||
log(500, `Could not process telemetry: ${error instanceof Error ? error.message : String(error)}`);
|
||||
return json({ ok: false, error: 'Could not process telemetry' }, { status: 500 });
|
||||
}
|
||||
log(200, null);
|
||||
return json({ ok: true, telemetry });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user