refactor: ♻️ Rewrite logging logic into a unified package
Some checks failed
Mirror to Codeberg / Mirror (push) Failing after 0s
Test Publish / build (client) (push) Failing after 0s
Test Publish / build (sdk) (push) Failing after 0s

This commit is contained in:
Jesse Wierzbinski 2025-06-22 18:43:03 +02:00
parent e1bd389bf1
commit aff51b651c
No known key found for this signature in database
32 changed files with 479 additions and 402 deletions

View file

@ -1,4 +1,3 @@
import { getLogger, type Logger } from "@logtape/logtape";
import { EntitySorter, type JSONObject } from "@versia/sdk";
import { verify } from "@versia/sdk/crypto";
import * as VersiaEntities from "@versia/sdk/entities";
@ -13,13 +12,13 @@ import {
User,
} from "@versia-server/kit/db";
import { Likes, Notes } from "@versia-server/kit/tables";
import { federationInboxLogger } from "@versia-server/logging";
import type { SocketAddress } from "bun";
import { Glob } from "bun";
import chalk from "chalk";
import { and, eq } from "drizzle-orm";
import { matches } from "ip-matching";
import { isValidationError } from "zod-validation-error";
import { sentry } from "@/sentry";
/**
* Checks if the hostname is defederated using glob matching.
@ -65,7 +64,6 @@ export class InboxProcessor {
key: CryptoKey;
} | null,
private authorizationHeader?: string,
private logger: Logger = getLogger(["federation", "inbox"]),
private requestIp: SocketAddress | null = null,
) {}
@ -156,7 +154,7 @@ export class InboxProcessor {
*/
public async process(): Promise<void> {
!this.sender &&
this.logger.debug`Processing request from potential bridge`;
federationInboxLogger.debug`Processing request from potential bridge`;
if (this.sender && isDefederated(this.sender.instance.data.baseUrl)) {
// Return 201 to avoid
@ -165,15 +163,15 @@ export class InboxProcessor {
return;
}
this.logger.debug`Instance ${chalk.gray(
federationInboxLogger.debug`Instance ${chalk.gray(
this.sender?.instance.data.baseUrl,
)} is not defederated`;
const shouldCheckSignature = this.shouldCheckSignature();
shouldCheckSignature
? this.logger.debug`Checking signature`
: this.logger.debug`Skipping signature check`;
? federationInboxLogger.debug`Checking signature`
: federationInboxLogger.debug`Skipping signature check`;
if (shouldCheckSignature) {
const isValid = await this.isSignatureValid();
@ -183,7 +181,7 @@ export class InboxProcessor {
}
}
shouldCheckSignature && this.logger.debug`Signature is valid`;
shouldCheckSignature && federationInboxLogger.debug`Signature is valid`;
try {
await new EntitySorter(this.body)
@ -596,8 +594,7 @@ export class InboxProcessor {
throw new ApiError(400, "Failed to process request", e.message);
}
this.logger.error`${e}`;
sentry?.captureException(e);
federationInboxLogger.error`${e}`;
throw new ApiError(500, "Failed to process request", e.message);
}

View file

@ -1,7 +1,7 @@
import { readdir } from "node:fs/promises";
import { getLogger, type Logger } from "@logtape/logtape";
import { config } from "@versia-server/config";
import { type Manifest, manifestSchema, Plugin } from "@versia-server/kit";
import { pluginLogger, serverLogger } from "@versia-server/logging";
import { file, sleep } from "bun";
import chalk from "chalk";
import { parseJSON5, parseJSONC } from "confbox";
@ -14,8 +14,6 @@ import type { HonoEnv } from "~/types/api";
* Class to manage plugins.
*/
export class PluginLoader {
private logger = getLogger("plugin");
/**
* Get all directories in a given directory.
* @param {string} dir - The directory to search.
@ -74,8 +72,7 @@ export class PluginLoader {
throw new Error(`Unsupported manifest file type: ${manifestFile}`);
} catch (e) {
this.logger
.fatal`Could not parse plugin manifest ${chalk.blue(manifestPath)} as ${manifestFile.split(".").pop()?.toUpperCase()}.`;
pluginLogger.fatal`Could not parse plugin manifest ${chalk.blue(manifestPath)} as ${manifestFile.split(".").pop()?.toUpperCase()}.`;
throw e;
}
}
@ -129,8 +126,7 @@ export class PluginLoader {
const result = await manifestSchema.safeParseAsync(manifest);
if (!result.success) {
this.logger
.fatal`Plugin manifest ${chalk.blue(manifestPath)} is invalid.`;
pluginLogger.fatal`Plugin manifest ${chalk.blue(manifestPath)} is invalid.`;
throw fromZodError(result.error);
}
@ -154,8 +150,7 @@ export class PluginLoader {
return plugin;
}
this.logger
.fatal`Default export of entrypoint ${chalk.blue(entrypoint)} at ${chalk.blue(dir)} is not a Plugin.`;
pluginLogger.fatal`Default export of entrypoint ${chalk.blue(entrypoint)} at ${chalk.blue(dir)} is not a Plugin.`;
throw new Error("Entrypoint is not a Plugin");
}
@ -177,8 +172,7 @@ export class PluginLoader {
const disabledOn = (disabled?.length ?? 0) > 0;
if (enabledOn && disabledOn) {
this.logger
.fatal`Both enabled and disabled lists are specified. Only one of them can be used.`;
pluginLogger.fatal`Both enabled and disabled lists are specified. Only one of them can be used.`;
throw new Error("Invalid configuration");
}
@ -219,10 +213,9 @@ export class PluginLoader {
plugin: Plugin<ZodTypeAny>;
}[],
app: Hono<HonoEnv>,
logger: Logger,
): Promise<void> {
for (const data of plugins) {
logger.info`Loading plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(data.manifest.version)} ${chalk.gray(`[${plugins.indexOf(data) + 1}/${plugins.length}]`)}`;
serverLogger.info`Loading plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(data.manifest.version)} ${chalk.gray(`[${plugins.indexOf(data) + 1}/${plugins.length}]`)}`;
const time1 = performance.now();
@ -232,13 +225,13 @@ export class PluginLoader {
config.plugins?.config?.[data.manifest.name],
);
} catch (e) {
logger.fatal`Error encountered while loading plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(data.manifest.version)} configuration.`;
logger.fatal`This is due to invalid, missing or incomplete configuration.`;
logger.fatal`Put your configuration at ${chalk.blueBright(
serverLogger.fatal`Error encountered while loading plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(data.manifest.version)} configuration.`;
serverLogger.fatal`This is due to invalid, missing or incomplete configuration.`;
serverLogger.fatal`Put your configuration at ${chalk.blueBright(
"plugins.config.<plugin-name>",
)}`;
logger.fatal`Here is the error message, please fix the configuration file accordingly:`;
logger.fatal`${(e as ValidationError).message}`;
serverLogger.fatal`Here is the error message, please fix the configuration file accordingly:`;
serverLogger.fatal`${(e as ValidationError).message}`;
await sleep(Number.POSITIVE_INFINITY);
}
@ -250,7 +243,7 @@ export class PluginLoader {
const time3 = performance.now();
logger.info`Plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(
serverLogger.info`Plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(
data.manifest.version,
)} loaded in ${chalk.gray(
`${(time2 - time1).toFixed(2)}ms`,

View file

@ -1,4 +1,3 @@
import { getLogger } from "@logtape/logtape";
import type { JSONObject } from "@versia/sdk";
import { config } from "@versia-server/config";
import { ApiError } from "@versia-server/kit";
@ -64,7 +63,6 @@ export const getInboxWorker = (): Worker<InboxJobData, void, InboxJobType> =>
data,
null,
headers.authorization,
getLogger(["federation", "inbox"]),
ip,
);
@ -160,7 +158,6 @@ export const getInboxWorker = (): Worker<InboxJobData, void, InboxJobType> =>
key,
},
undefined,
getLogger(["federation", "inbox"]),
ip,
);

View file

@ -3,9 +3,9 @@
* @description Sonic search integration for indexing and searching accounts and statuses
*/
import { getLogger } from "@logtape/logtape";
import { config } from "@versia-server/config";
import { db, Note, User } from "@versia-server/kit/db";
import { sonicLogger } from "@versia-server/logging";
import type { SQL, ValueOrArray } from "drizzle-orm";
import {
Ingest as SonicChannelIngest,
@ -27,7 +27,6 @@ export class SonicSearchManager {
private searchChannel: SonicChannelSearch;
private ingestChannel: SonicChannelIngest;
private connected = false;
private logger = getLogger("sonic");
/**
* @param config Configuration for Sonic
@ -55,7 +54,7 @@ export class SonicSearchManager {
*/
public async connect(silent = false): Promise<void> {
if (!config.search.enabled) {
!silent && this.logger.info`Sonic search is disabled`;
!silent && sonicLogger.info`Sonic search is disabled`;
return;
}
@ -63,28 +62,24 @@ export class SonicSearchManager {
return;
}
!silent && this.logger.info`Connecting to Sonic...`;
!silent && sonicLogger.info`Connecting to Sonic...`;
// Connect to Sonic
await new Promise<boolean>((resolve, reject) => {
this.searchChannel.connect({
connected: (): void => {
!silent &&
this.logger.info`Connected to Sonic Search Channel`;
sonicLogger.info`Connected to Sonic Search Channel`;
resolve(true);
},
disconnected: (): void =>
this.logger
.error`Disconnected from Sonic Search Channel. You might be using an incorrect password.`,
sonicLogger.error`Disconnected from Sonic Search Channel. You might be using an incorrect password.`,
timeout: (): void =>
this.logger
.error`Sonic Search Channel connection timed out`,
sonicLogger.error`Sonic Search Channel connection timed out`,
retrying: (): void =>
this.logger
.warn`Retrying connection to Sonic Search Channel`,
sonicLogger.warn`Retrying connection to Sonic Search Channel`,
error: (error): void => {
this.logger
.error`Failed to connect to Sonic Search Channel: ${error}`;
sonicLogger.error`Failed to connect to Sonic Search Channel: ${error}`;
reject(error);
},
});
@ -94,20 +89,17 @@ export class SonicSearchManager {
this.ingestChannel.connect({
connected: (): void => {
!silent &&
this.logger.info`Connected to Sonic Ingest Channel`;
sonicLogger.info`Connected to Sonic Ingest Channel`;
resolve(true);
},
disconnected: (): void =>
this.logger.error`Disconnected from Sonic Ingest Channel`,
sonicLogger.error`Disconnected from Sonic Ingest Channel`,
timeout: (): void =>
this.logger
.error`Sonic Ingest Channel connection timed out`,
sonicLogger.error`Sonic Ingest Channel connection timed out`,
retrying: (): void =>
this.logger
.warn`Retrying connection to Sonic Ingest Channel`,
sonicLogger.warn`Retrying connection to Sonic Ingest Channel`,
error: (error): void => {
this.logger
.error`Failed to connect to Sonic Ingest Channel: ${error}`;
sonicLogger.error`Failed to connect to Sonic Ingest Channel: ${error}`;
reject(error);
},
});
@ -119,9 +111,9 @@ export class SonicSearchManager {
this.ingestChannel.ping(),
]);
this.connected = true;
!silent && this.logger.info`Connected to Sonic`;
!silent && sonicLogger.info`Connected to Sonic`;
} catch (error) {
this.logger.fatal`Error while connecting to Sonic: ${error}`;
sonicLogger.fatal`Error while connecting to Sonic: ${error}`;
throw error;
}
}
@ -143,7 +135,7 @@ export class SonicSearchManager {
`${user.data.username} ${user.data.displayName} ${user.data.note}`,
);
} catch (error) {
this.logger.error`Failed to add user to Sonic: ${error}`;
sonicLogger.error`Failed to add user to Sonic: ${error}`;
}
}