mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29: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 { DittoDB, DittoPolyPg } from '@ditto/db';
|
||||
import { DittoPolyPg } from '@ditto/db';
|
||||
import { paginationMiddleware, tokenMiddleware, userMiddleware } from '@ditto/mastoapi/middleware';
|
||||
import { DittoApp, type DittoEnv } from '@ditto/mastoapi/router';
|
||||
import { relayPoolRelaysSizeGauge, relayPoolSubscriptionsSizeGauge } from '@ditto/metrics';
|
||||
|
|
@ -152,21 +152,15 @@ import { logiMiddleware } from '@/middleware/logiMiddleware.ts';
|
|||
import { DittoRelayStore } from '@/storages/DittoRelayStore.ts';
|
||||
|
||||
export interface AppEnv extends DittoEnv {
|
||||
Variables: {
|
||||
conf: DittoConf;
|
||||
Variables: DittoEnv['Variables'] & {
|
||||
/** Uploader for the user to upload files. */
|
||||
uploader?: NUploader;
|
||||
/** NIP-98 signed event proving the pubkey is owned by the user. */
|
||||
proof?: NostrEvent;
|
||||
/** Kysely instance for the database. */
|
||||
db: DittoDB;
|
||||
/** Base database store. No content filtering. */
|
||||
relay: NRelay;
|
||||
/** Normalized pagination params. */
|
||||
pagination: { since?: number; until?: number; limit: number };
|
||||
/** Translation service. */
|
||||
translator?: DittoTranslator;
|
||||
signal: AbortSignal;
|
||||
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: NostrSigner;
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ const adminAccountActionSchema = z.object({
|
|||
});
|
||||
|
||||
const adminActionController: AppController = async (c) => {
|
||||
const { conf, relay } = c.var;
|
||||
const { conf, relay, requestId } = c.var;
|
||||
|
||||
const body = await parseBody(c.req.raw);
|
||||
const result = adminAccountActionSchema.safeParse(body);
|
||||
|
|
@ -155,7 +155,7 @@ const adminActionController: AppController = async (c) => {
|
|||
n.disabled = true;
|
||||
n.suspended = true;
|
||||
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') {
|
||||
|
|
@ -163,7 +163,7 @@ const adminActionController: AppController = async (c) => {
|
|||
try {
|
||||
await relay.remove!([{ kinds: [30360], authors: [await conf.signer.getPublicKey()], '#p': [authorId] }]);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ route.put('/wallet', userMiddleware({ enc: 'nip44' }), async (c) => {
|
|||
|
||||
/** Gets a wallet, if it exists. */
|
||||
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();
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ route.get('/wallet', userMiddleware({ enc: 'nip44' }), swapNutzapsMiddleware, as
|
|||
return accumulator + current.amount;
|
||||
}, 0);
|
||||
} 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 { user, signal } = c.var;
|
||||
const { user, signal, requestId } = c.var;
|
||||
|
||||
const pubkey = await user!.signer.getPublicKey();
|
||||
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);
|
||||
return c.json(renderAttachment(media));
|
||||
} 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);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ const limiter = new TTLCache<string, number>();
|
|||
const connections = new Set<WebSocket>();
|
||||
|
||||
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 token = c.req.header('sec-websocket-protocol');
|
||||
const stream = streamSchema.optional().catch(undefined).parse(c.req.query('stream'));
|
||||
|
|
@ -122,7 +123,7 @@ const streamingController: AppController = async (c) => {
|
|||
}
|
||||
}
|
||||
} 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 { relay, user, signal } = c.var;
|
||||
const { relay, user, signal, requestId } = c.var;
|
||||
|
||||
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')) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@ import { logi } from '@soapbox/logi';
|
|||
|
||||
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 { 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);
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import { renderAccount } from '@/views/mastodon/accounts.ts';
|
|||
const META_PLACEHOLDER = '<!--server-generated-meta-->' as const;
|
||||
|
||||
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');
|
||||
|
||||
try {
|
||||
|
|
@ -26,7 +28,7 @@ export const frontendController: AppMiddleware = async (c) => {
|
|||
const meta = renderMetadata(c.req.url, entities);
|
||||
return c.html(content.replace(META_PLACEHOLDER, meta));
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
NostrClientMsg,
|
||||
NostrClientREQ,
|
||||
NostrRelayMsg,
|
||||
NRelay,
|
||||
NSchema as n,
|
||||
} from '@nostrify/nostrify';
|
||||
|
||||
|
|
@ -40,8 +41,17 @@ const limiters = {
|
|||
/** Connections for metrics purposes. */
|
||||
const connections = new Set<WebSocket>();
|
||||
|
||||
interface ConnectStreamOpts {
|
||||
conf: DittoConf;
|
||||
relay: NRelay;
|
||||
requestId: string;
|
||||
}
|
||||
|
||||
/** 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>();
|
||||
|
||||
if (ip) {
|
||||
|
|
@ -74,7 +84,7 @@ function connectStream(conf: DittoConf, relay: DittoPgStore, socket: WebSocket,
|
|||
const msg = result.data;
|
||||
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 });
|
||||
|
||||
handleMsg(result.data);
|
||||
|
|
@ -165,7 +175,7 @@ function connectStream(conf: DittoConf, relay: DittoPgStore, socket: WebSocket,
|
|||
send(['OK', event.id, false, e.message]);
|
||||
} else {
|
||||
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 { conf, relay } = c.var;
|
||||
const { conf } = c.var;
|
||||
|
||||
const upgrade = c.req.header('upgrade');
|
||||
|
||||
// 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);
|
||||
connectStream(conf, relay as DittoPgStore, socket, ip);
|
||||
connectStream(socket, ip, c.var);
|
||||
|
||||
return response;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export class DittoApp extends Hono<DittoEnv> {
|
|||
// @ts-ignore Require a DittoRoute for type safety.
|
||||
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);
|
||||
|
||||
this.use((c, next) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue