feat: correlate server errors and monitor application health
This commit is contained in:
16
src/api.ts
16
src/api.ts
@@ -1,3 +1,4 @@
|
||||
import { errorDetails } from "./ops/monitor";
|
||||
import { createAccountRoutes } from "./account/routes";
|
||||
import { createHabitRoutes } from "./habits/routes";
|
||||
import { ApiError } from "./habits/service";
|
||||
@@ -9,11 +10,18 @@ import type { FetchDiscord } from "./auth/discord";
|
||||
import { createSharingRoutes, type DiscordFetch } from "./sharing/routes";
|
||||
import type { DiscordSharingConfig } from "./sharing/config";
|
||||
|
||||
export function createApi(db: AppDatabase, config: AuthConfig, request?: FetchDiscord, now?: () => number, discordRequest?: DiscordFetch, sharingConfig: DiscordSharingConfig = { token: "", channelId: "" }) {
|
||||
export function createApi(db: AppDatabase, config: AuthConfig, request?: FetchDiscord, now?: () => number, discordRequest?: DiscordFetch, sharingConfig: DiscordSharingConfig = { token: "", channelId: "" }, operations: { healthy?: () => boolean; log?: (event: Record<string, unknown>) => void } = {}) {
|
||||
const app = new Hono<AuthEnv>();
|
||||
app.use("*", async (c, next) => {
|
||||
const requestId = crypto.randomUUID();
|
||||
c.set("requestId", requestId); c.header("X-Request-ID", requestId);
|
||||
await next();
|
||||
});
|
||||
const auth = createAuth(db, config, request, now);
|
||||
app.get("/api/health", c => {
|
||||
c.header("Cache-Control", "no-store");
|
||||
db.get(sql`SELECT 1`);
|
||||
if (operations.healthy && !operations.healthy()) return c.json({ status: "degraded" }, 503);
|
||||
return c.json({ status: "ok" });
|
||||
});
|
||||
app.route("/api/auth", auth.routes);
|
||||
@@ -25,7 +33,11 @@ export function createApi(db: AppDatabase, config: AuthConfig, request?: FetchDi
|
||||
app.onError((_error, c) => {
|
||||
c.header("Cache-Control", "no-store");
|
||||
if (_error instanceof ApiError) return c.json({ error: _error.message }, _error.status);
|
||||
return c.json({ error: "Internal server error" }, 500);
|
||||
const requestId = c.get("requestId");
|
||||
const event = { event: "request_failed", timestamp: new Date().toISOString(), requestId, method: c.req.method,
|
||||
route: c.req.routePath, ...errorDetails(_error) };
|
||||
(operations.log ?? (event => console.error(JSON.stringify(event))))(event);
|
||||
return c.json({ error: "Internal server error", requestId }, 500);
|
||||
});
|
||||
return app;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user