mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
Log requestId in some convenient spots
This commit is contained in:
parent
0cdb7b8cd5
commit
368bf91b1f
10 changed files with 47 additions and 28 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import { DittoConf } from '@ditto/conf';
|
import { DittoConf } from '@ditto/conf';
|
||||||
import { DittoDB, DittoPolyPg } from '@ditto/db';
|
import { DittoPolyPg } from '@ditto/db';
|
||||||
import { paginationMiddleware, tokenMiddleware, userMiddleware } from '@ditto/mastoapi/middleware';
|
import { paginationMiddleware, tokenMiddleware, userMiddleware } from '@ditto/mastoapi/middleware';
|
||||||
import { DittoApp, type DittoEnv } from '@ditto/mastoapi/router';
|
import { DittoApp, type DittoEnv } from '@ditto/mastoapi/router';
|
||||||
import { relayPoolRelaysSizeGauge, relayPoolSubscriptionsSizeGauge } from '@ditto/metrics';
|
import { relayPoolRelaysSizeGauge, relayPoolSubscriptionsSizeGauge } from '@ditto/metrics';
|
||||||
|
|
@ -152,21 +152,15 @@ import { logiMiddleware } from '@/middleware/logiMiddleware.ts';
|
||||||
import { DittoRelayStore } from '@/storages/DittoRelayStore.ts';
|
import { DittoRelayStore } from '@/storages/DittoRelayStore.ts';
|
||||||
|
|
||||||
export interface AppEnv extends DittoEnv {
|
export interface AppEnv extends DittoEnv {
|
||||||
Variables: {
|
Variables: DittoEnv['Variables'] & {
|
||||||
conf: DittoConf;
|
|
||||||
/** Uploader for the user to upload files. */
|
/** Uploader for the user to upload files. */
|
||||||
uploader?: NUploader;
|
uploader?: NUploader;
|
||||||
/** NIP-98 signed event proving the pubkey is owned by the user. */
|
/** NIP-98 signed event proving the pubkey is owned by the user. */
|
||||||
proof?: NostrEvent;
|
proof?: NostrEvent;
|
||||||
/** Kysely instance for the database. */
|
|
||||||
db: DittoDB;
|
|
||||||
/** Base database store. No content filtering. */
|
|
||||||
relay: NRelay;
|
|
||||||
/** Normalized pagination params. */
|
/** Normalized pagination params. */
|
||||||
pagination: { since?: number; until?: number; limit: number };
|
pagination: { since?: number; until?: number; limit: number };
|
||||||
/** Translation service. */
|
/** Translation service. */
|
||||||
translator?: DittoTranslator;
|
translator?: DittoTranslator;
|
||||||
signal: AbortSignal;
|
|
||||||
user?: {
|
user?: {
|
||||||
/** Signer to get the logged-in user's pubkey, relays, and to sign events, or `undefined` if the user isn't logged in. */
|
/** Signer to get the logged-in user's pubkey, relays, and to sign events, or `undefined` if the user isn't logged in. */
|
||||||
signer: NostrSigner;
|
signer: NostrSigner;
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ const adminAccountActionSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
const adminActionController: AppController = async (c) => {
|
const adminActionController: AppController = async (c) => {
|
||||||
const { conf, relay } = c.var;
|
const { conf, relay, requestId } = c.var;
|
||||||
|
|
||||||
const body = await parseBody(c.req.raw);
|
const body = await parseBody(c.req.raw);
|
||||||
const result = adminAccountActionSchema.safeParse(body);
|
const result = adminAccountActionSchema.safeParse(body);
|
||||||
|
|
@ -155,7 +155,7 @@ const adminActionController: AppController = async (c) => {
|
||||||
n.disabled = true;
|
n.disabled = true;
|
||||||
n.suspended = true;
|
n.suspended = true;
|
||||||
relay.remove!([{ authors: [authorId] }]).catch((e: unknown) => {
|
relay.remove!([{ authors: [authorId] }]).catch((e: unknown) => {
|
||||||
logi({ level: 'error', ns: 'ditto.api.admin.account.action', type: data.type, error: errorJson(e) });
|
logi({ level: 'error', ns: 'ditto.api.admin.account.action', type: data.type, requestId, error: errorJson(e) });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (data.type === 'revoke_name') {
|
if (data.type === 'revoke_name') {
|
||||||
|
|
@ -163,7 +163,7 @@ const adminActionController: AppController = async (c) => {
|
||||||
try {
|
try {
|
||||||
await relay.remove!([{ kinds: [30360], authors: [await conf.signer.getPublicKey()], '#p': [authorId] }]);
|
await relay.remove!([{ kinds: [30360], authors: [await conf.signer.getPublicKey()], '#p': [authorId] }]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logi({ level: 'error', ns: 'ditto.api.admin.account.action', type: data.type, error: errorJson(e) });
|
logi({ level: 'error', ns: 'ditto.api.admin.account.action', type: data.type, requestId, error: errorJson(e) });
|
||||||
return c.json({ error: 'Unexpected runtime error' }, 500);
|
return c.json({ error: 'Unexpected runtime error' }, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ route.put('/wallet', userMiddleware({ enc: 'nip44' }), async (c) => {
|
||||||
|
|
||||||
/** Gets a wallet, if it exists. */
|
/** Gets a wallet, if it exists. */
|
||||||
route.get('/wallet', userMiddleware({ enc: 'nip44' }), swapNutzapsMiddleware, async (c) => {
|
route.get('/wallet', userMiddleware({ enc: 'nip44' }), swapNutzapsMiddleware, async (c) => {
|
||||||
const { conf, relay, user, signal } = c.var;
|
const { conf, relay, user, signal, requestId } = c.var;
|
||||||
|
|
||||||
const pubkey = await user.signer.getPublicKey();
|
const pubkey = await user.signer.getPublicKey();
|
||||||
|
|
||||||
|
|
@ -139,7 +139,7 @@ route.get('/wallet', userMiddleware({ enc: 'nip44' }), swapNutzapsMiddleware, as
|
||||||
return accumulator + current.amount;
|
return accumulator + current.amount;
|
||||||
}, 0);
|
}, 0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logi({ level: 'error', ns: 'ditto.api.cashu.wallet.swap', error: errorJson(e) });
|
logi({ level: 'error', ns: 'ditto.api.cashu.wallet.swap', requestId, error: errorJson(e) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ const mediaUpdateSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
const mediaController: AppController = async (c) => {
|
const mediaController: AppController = async (c) => {
|
||||||
const { user, signal } = c.var;
|
const { user, signal, requestId } = c.var;
|
||||||
|
|
||||||
const pubkey = await user!.signer.getPublicKey();
|
const pubkey = await user!.signer.getPublicKey();
|
||||||
const result = mediaBodySchema.safeParse(await parseBody(c.req.raw));
|
const result = mediaBodySchema.safeParse(await parseBody(c.req.raw));
|
||||||
|
|
@ -35,7 +35,7 @@ const mediaController: AppController = async (c) => {
|
||||||
const media = await uploadFile(c, file, { pubkey, description }, signal);
|
const media = await uploadFile(c, file, { pubkey, description }, signal);
|
||||||
return c.json(renderAttachment(media));
|
return c.json(renderAttachment(media));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logi({ level: 'error', ns: 'ditto.api.media', error: errorJson(e) });
|
logi({ level: 'error', ns: 'ditto.api.media', requestId, error: errorJson(e) });
|
||||||
return c.json({ error: 'Failed to upload file.' }, 500);
|
return c.json({ error: 'Failed to upload file.' }, 500);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,8 @@ const limiter = new TTLCache<string, number>();
|
||||||
const connections = new Set<WebSocket>();
|
const connections = new Set<WebSocket>();
|
||||||
|
|
||||||
const streamingController: AppController = async (c) => {
|
const streamingController: AppController = async (c) => {
|
||||||
const { conf, relay, user } = c.var;
|
const { conf, relay, user, requestId } = c.var;
|
||||||
|
|
||||||
const upgrade = c.req.header('upgrade');
|
const upgrade = c.req.header('upgrade');
|
||||||
const token = c.req.header('sec-websocket-protocol');
|
const token = c.req.header('sec-websocket-protocol');
|
||||||
const stream = streamSchema.optional().catch(undefined).parse(c.req.query('stream'));
|
const stream = streamSchema.optional().catch(undefined).parse(c.req.query('stream'));
|
||||||
|
|
@ -122,7 +123,7 @@ const streamingController: AppController = async (c) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logi({ level: 'error', ns: 'ditto.streaming', msg: 'Error in streaming', error: errorJson(e) });
|
logi({ level: 'error', ns: 'ditto.streaming', msg: 'Error in streaming', requestId, error: errorJson(e) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const translateSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
const translateController: AppController = async (c) => {
|
const translateController: AppController = async (c) => {
|
||||||
const { relay, user, signal } = c.var;
|
const { relay, user, signal, requestId } = c.var;
|
||||||
|
|
||||||
const result = translateSchema.safeParse(await parseBody(c.req.raw));
|
const result = translateSchema.safeParse(await parseBody(c.req.raw));
|
||||||
|
|
||||||
|
|
@ -143,7 +143,7 @@ const translateController: AppController = async (c) => {
|
||||||
if (e instanceof Error && e.message.includes('not supported')) {
|
if (e instanceof Error && e.message.includes('not supported')) {
|
||||||
return c.json({ error: `Translation of source language '${event.language}' not supported` }, 422);
|
return c.json({ error: `Translation of source language '${event.language}' not supported` }, 422);
|
||||||
}
|
}
|
||||||
logi({ level: 'error', ns: 'ditto.translate', error: errorJson(e) });
|
logi({ level: 'error', ns: 'ditto.translate', requestId, error: errorJson(e) });
|
||||||
return c.json({ error: 'Service Unavailable' }, 503);
|
return c.json({ error: 'Service Unavailable' }, 503);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ import { logi } from '@soapbox/logi';
|
||||||
|
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '@/utils/log.ts';
|
||||||
|
|
||||||
export const errorHandler: ErrorHandler = (err, c) => {
|
import type { DittoEnv } from '@ditto/mastoapi/router';
|
||||||
|
|
||||||
|
export const errorHandler: ErrorHandler<DittoEnv> = (err, c) => {
|
||||||
|
const { requestId } = c.var;
|
||||||
const { method } = c.req;
|
const { method } = c.req;
|
||||||
const { pathname } = new URL(c.req.url);
|
const { pathname } = new URL(c.req.url);
|
||||||
|
|
||||||
|
|
@ -22,7 +25,15 @@ export const errorHandler: ErrorHandler = (err, c) => {
|
||||||
return c.json({ error: 'The server was unable to respond in a timely manner' }, 500);
|
return c.json({ error: 'The server was unable to respond in a timely manner' }, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
logi({ level: 'error', ns: 'ditto.http', msg: 'Unhandled error', method, pathname, error: errorJson(err) });
|
logi({
|
||||||
|
level: 'error',
|
||||||
|
ns: 'ditto.http',
|
||||||
|
msg: 'Unhandled error',
|
||||||
|
method,
|
||||||
|
pathname,
|
||||||
|
requestId,
|
||||||
|
error: errorJson(err),
|
||||||
|
});
|
||||||
|
|
||||||
return c.json({ error: 'Something went wrong' }, 500);
|
return c.json({ error: 'Something went wrong' }, 500);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ import { renderAccount } from '@/views/mastodon/accounts.ts';
|
||||||
const META_PLACEHOLDER = '<!--server-generated-meta-->' as const;
|
const META_PLACEHOLDER = '<!--server-generated-meta-->' as const;
|
||||||
|
|
||||||
export const frontendController: AppMiddleware = async (c) => {
|
export const frontendController: AppMiddleware = async (c) => {
|
||||||
|
const { requestId } = c.var;
|
||||||
|
|
||||||
c.header('Cache-Control', 'max-age=86400, s-maxage=30, public, stale-if-error=604800');
|
c.header('Cache-Control', 'max-age=86400, s-maxage=30, public, stale-if-error=604800');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -26,7 +28,7 @@ export const frontendController: AppMiddleware = async (c) => {
|
||||||
const meta = renderMetadata(c.req.url, entities);
|
const meta = renderMetadata(c.req.url, entities);
|
||||||
return c.html(content.replace(META_PLACEHOLDER, meta));
|
return c.html(content.replace(META_PLACEHOLDER, meta));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logi({ level: 'error', ns: 'ditto.frontend', msg: 'Error building meta tags', error: errorJson(e) });
|
logi({ level: 'error', ns: 'ditto.frontend', msg: 'Error building meta tags', requestId, error: errorJson(e) });
|
||||||
return c.html(content);
|
return c.html(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
NostrClientMsg,
|
NostrClientMsg,
|
||||||
NostrClientREQ,
|
NostrClientREQ,
|
||||||
NostrRelayMsg,
|
NostrRelayMsg,
|
||||||
|
NRelay,
|
||||||
NSchema as n,
|
NSchema as n,
|
||||||
} from '@nostrify/nostrify';
|
} from '@nostrify/nostrify';
|
||||||
|
|
||||||
|
|
@ -40,8 +41,17 @@ const limiters = {
|
||||||
/** Connections for metrics purposes. */
|
/** Connections for metrics purposes. */
|
||||||
const connections = new Set<WebSocket>();
|
const connections = new Set<WebSocket>();
|
||||||
|
|
||||||
|
interface ConnectStreamOpts {
|
||||||
|
conf: DittoConf;
|
||||||
|
relay: NRelay;
|
||||||
|
requestId: string;
|
||||||
|
}
|
||||||
|
|
||||||
/** Set up the Websocket connection. */
|
/** Set up the Websocket connection. */
|
||||||
function connectStream(conf: DittoConf, relay: DittoPgStore, socket: WebSocket, ip: string | undefined) {
|
function connectStream(socket: WebSocket, ip: string | undefined, opts: ConnectStreamOpts): void {
|
||||||
|
const { conf, requestId } = opts;
|
||||||
|
const relay = opts.relay as DittoPgStore;
|
||||||
|
|
||||||
const controllers = new Map<string, AbortController>();
|
const controllers = new Map<string, AbortController>();
|
||||||
|
|
||||||
if (ip) {
|
if (ip) {
|
||||||
|
|
@ -74,7 +84,7 @@ function connectStream(conf: DittoConf, relay: DittoPgStore, socket: WebSocket,
|
||||||
const msg = result.data;
|
const msg = result.data;
|
||||||
const verb = msg[0];
|
const verb = msg[0];
|
||||||
|
|
||||||
logi({ level: 'trace', ns: 'ditto.relay.msg', verb, msg: msg as JsonValue, ip });
|
logi({ level: 'trace', ns: 'ditto.relay.msg', verb, msg: msg as JsonValue, ip, requestId });
|
||||||
relayMessagesCounter.inc({ verb });
|
relayMessagesCounter.inc({ verb });
|
||||||
|
|
||||||
handleMsg(result.data);
|
handleMsg(result.data);
|
||||||
|
|
@ -165,7 +175,7 @@ function connectStream(conf: DittoConf, relay: DittoPgStore, socket: WebSocket,
|
||||||
send(['OK', event.id, false, e.message]);
|
send(['OK', event.id, false, e.message]);
|
||||||
} else {
|
} else {
|
||||||
send(['OK', event.id, false, 'error: something went wrong']);
|
send(['OK', event.id, false, 'error: something went wrong']);
|
||||||
logi({ level: 'error', ns: 'ditto.relay', msg: 'Error in relay', error: errorJson(e), ip });
|
logi({ level: 'error', ns: 'ditto.relay', msg: 'Error in relay', error: errorJson(e), ip, requestId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +205,8 @@ function connectStream(conf: DittoConf, relay: DittoPgStore, socket: WebSocket,
|
||||||
}
|
}
|
||||||
|
|
||||||
const relayController: AppController = (c, next) => {
|
const relayController: AppController = (c, next) => {
|
||||||
const { conf, relay } = c.var;
|
const { conf } = c.var;
|
||||||
|
|
||||||
const upgrade = c.req.header('upgrade');
|
const upgrade = c.req.header('upgrade');
|
||||||
|
|
||||||
// NIP-11: https://github.com/nostr-protocol/nips/blob/master/11.md
|
// NIP-11: https://github.com/nostr-protocol/nips/blob/master/11.md
|
||||||
|
|
@ -214,7 +225,7 @@ const relayController: AppController = (c, next) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { socket, response } = Deno.upgradeWebSocket(c.req.raw);
|
const { socket, response } = Deno.upgradeWebSocket(c.req.raw);
|
||||||
connectStream(conf, relay as DittoPgStore, socket, ip);
|
connectStream(socket, ip, c.var);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export class DittoApp extends Hono<DittoEnv> {
|
||||||
// @ts-ignore Require a DittoRoute for type safety.
|
// @ts-ignore Require a DittoRoute for type safety.
|
||||||
declare route: (path: string, app: Hono<DittoEnv>) => Hono<DittoEnv>;
|
declare route: (path: string, app: Hono<DittoEnv>) => Hono<DittoEnv>;
|
||||||
|
|
||||||
constructor(opts: Omit<DittoEnv['Variables'], 'signal'> & HonoOptions<DittoEnv>) {
|
constructor(opts: Omit<DittoEnv['Variables'], 'signal' | 'requestId'> & HonoOptions<DittoEnv>) {
|
||||||
super(opts);
|
super(opts);
|
||||||
|
|
||||||
this.use((c, next) => {
|
this.use((c, next) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue