mirror of
https://github.com/versia-pub/server.git
synced 2026-03-12 21:39:15 +01:00
refactor: ♻️ Rewrite logging logic into a unified package
This commit is contained in:
parent
e1bd389bf1
commit
aff51b651c
32 changed files with 479 additions and 402 deletions
|
|
@ -1,8 +1,8 @@
|
|||
import { resolve } from "node:path";
|
||||
import { getLogger } from "@logtape/logtape";
|
||||
import { Scalar } from "@scalar/hono-api-reference";
|
||||
import { config } from "@versia-server/config";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { serverLogger } from "@versia-server/logging";
|
||||
import chalk from "chalk";
|
||||
import { Hono } from "hono";
|
||||
import { serveStatic } from "hono/bun";
|
||||
|
|
@ -13,8 +13,6 @@ import { secureHeaders } from "hono/secure-headers";
|
|||
import { openAPISpecs } from "hono-openapi";
|
||||
import { Youch } from "youch";
|
||||
import { applyToHono } from "@/bull-board.ts";
|
||||
import { configureLoggers } from "@/loggers";
|
||||
import { sentry } from "@/sentry";
|
||||
import pkg from "~/package.json" with { type: "application/json" };
|
||||
import { PluginLoader } from "../../classes/plugin/loader.ts";
|
||||
import type { ApiRouteExports, HonoEnv } from "../../types/api.ts";
|
||||
|
|
@ -28,9 +26,6 @@ import { routes } from "./routes.ts";
|
|||
import "zod-openapi/extend";
|
||||
|
||||
export const appFactory = async (): Promise<Hono<HonoEnv>> => {
|
||||
await configureLoggers();
|
||||
const serverLogger = getLogger("server");
|
||||
|
||||
const app = new Hono<HonoEnv>({
|
||||
strict: false,
|
||||
});
|
||||
|
|
@ -124,7 +119,7 @@ export const appFactory = async (): Promise<Hono<HonoEnv>> => {
|
|||
config.plugins?.overrides.disabled,
|
||||
);
|
||||
|
||||
await PluginLoader.addToApp(plugins, app, serverLogger);
|
||||
await PluginLoader.addToApp(plugins, app);
|
||||
|
||||
const time2 = performance.now();
|
||||
|
||||
|
|
@ -193,7 +188,6 @@ export const appFactory = async (): Promise<Hono<HonoEnv>> => {
|
|||
const youch = new Youch();
|
||||
console.error(await youch.toANSI(error));
|
||||
|
||||
sentry?.captureException(error);
|
||||
return c.json(
|
||||
{
|
||||
error: "A server error occured",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import process from "node:process";
|
||||
import { config } from "@versia-server/config";
|
||||
import { Youch } from "youch";
|
||||
import { sentry } from "@/sentry";
|
||||
import { createServer } from "@/server";
|
||||
import { appFactory } from "./app.ts";
|
||||
|
||||
|
|
@ -16,6 +15,5 @@ process.on("uncaughtException", async (error) => {
|
|||
});
|
||||
|
||||
await import("./setup.ts");
|
||||
sentry?.captureMessage("Server started", "info");
|
||||
|
||||
createServer(config, await appFactory());
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import { config } from "@versia-server/config";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { serverLogger } from "@versia-server/logging";
|
||||
import type { SocketAddress } from "bun";
|
||||
import { createMiddleware } from "hono/factory";
|
||||
import { matches } from "ip-matching";
|
||||
import { sentry } from "@/sentry";
|
||||
|
||||
export const ipBans = createMiddleware(async (context, next) => {
|
||||
// Check for banned IPs
|
||||
|
|
@ -22,11 +21,8 @@ export const ipBans = createMiddleware(async (context, next) => {
|
|||
throw new ApiError(403, "Forbidden");
|
||||
}
|
||||
} catch (e) {
|
||||
const logger = getLogger("server");
|
||||
|
||||
logger.error`Error while parsing banned IP "${ip}" `;
|
||||
logger.error`${e}`;
|
||||
sentry?.captureException(e);
|
||||
serverLogger.error`Error while parsing banned IP "${ip}" `;
|
||||
serverLogger.error`${e}`;
|
||||
|
||||
return context.json(
|
||||
{ error: `A server error occured: ${(e as Error).message}` },
|
||||
|
|
|
|||
|
|
@ -1,37 +1,26 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import { config } from "@versia-server/config";
|
||||
import { serverLogger } from "@versia-server/logging";
|
||||
import { SHA256 } from "bun";
|
||||
import chalk from "chalk";
|
||||
import { createMiddleware } from "hono/factory";
|
||||
|
||||
export const logger = createMiddleware(async (context, next) => {
|
||||
if (config.logging.types.requests) {
|
||||
const serverLogger = getLogger("server");
|
||||
const body = await context.req.raw.clone().text();
|
||||
const body = await context.req.raw.clone().text();
|
||||
|
||||
const urlAndMethod = `${chalk.green(context.req.method)} ${chalk.blue(context.req.url)}`;
|
||||
const urlAndMethod = `${chalk.green(context.req.method)} ${chalk.blue(context.req.url)}`;
|
||||
|
||||
const hash = `${chalk.bold("Hash")}: ${chalk.yellow(
|
||||
new SHA256().update(body).digest("hex"),
|
||||
)}`;
|
||||
const hash = `${chalk.bold("Hash")}: ${chalk.yellow(
|
||||
new SHA256().update(body).digest("hex"),
|
||||
)}`;
|
||||
|
||||
const headers = `${chalk.bold("Headers")}:\n${Array.from(
|
||||
context.req.raw.headers.entries(),
|
||||
)
|
||||
.map(
|
||||
([key, value]) =>
|
||||
` - ${chalk.cyan(key)}: ${chalk.white(value)}`,
|
||||
)
|
||||
.join("\n")}`;
|
||||
const headers = `${chalk.bold("Headers")}:\n${Array.from(
|
||||
context.req.raw.headers.entries(),
|
||||
)
|
||||
.map(([key, value]) => ` - ${chalk.cyan(key)}: ${chalk.white(value)}`)
|
||||
.join("\n")}`;
|
||||
|
||||
const bodyLog = `${chalk.bold("Body")}: ${chalk.gray(body)}`;
|
||||
const bodyLog = `${chalk.bold("Body")}: ${chalk.gray(body)}`;
|
||||
|
||||
if (config.logging.types.requests_content) {
|
||||
serverLogger.debug`${urlAndMethod}\n${hash}\n${headers}\n${bodyLog}`;
|
||||
} else {
|
||||
serverLogger.debug`${urlAndMethod}`;
|
||||
}
|
||||
}
|
||||
serverLogger.debug`${urlAndMethod}\n${hash}\n${headers}\n${bodyLog}`;
|
||||
|
||||
await next();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@
|
|||
"@versia-server/config": "workspace:*",
|
||||
"@versia-server/tests": "workspace:*",
|
||||
"@versia-server/kit": "workspace:*",
|
||||
"@versia-server/logging": "workspace:*",
|
||||
"@versia/client": "workspace:*",
|
||||
"@versia/sdk": "workspace:*",
|
||||
"@logtape/logtape": "catalog:",
|
||||
"youch": "catalog:",
|
||||
"hono": "catalog:",
|
||||
"hono-openapi": "catalog:",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import { apiRoute } from "@versia-server/kit/api";
|
||||
import { federationMessagingLogger } from "@versia-server/logging";
|
||||
import chalk from "chalk";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
|
||||
|
|
@ -19,8 +19,7 @@ export default apiRoute((app) =>
|
|||
async (context) => {
|
||||
const content = await context.req.text();
|
||||
|
||||
getLogger(["federation", "messaging"])
|
||||
.info`Received message via ${chalk.bold("Instance Messaging")}:\n${content}`;
|
||||
federationMessagingLogger.info`Received message via ${chalk.bold("Instance Messaging")}:\n${content}`;
|
||||
|
||||
return context.text("", 200);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import { FederationRequester } from "@versia/sdk/http";
|
||||
import { WebFingerSchema } from "@versia/sdk/schemas";
|
||||
import { config } from "@versia-server/config";
|
||||
|
|
@ -8,6 +7,7 @@ import { User } from "@versia-server/kit/db";
|
|||
import { parseUserAddress } from "@versia-server/kit/parsers";
|
||||
import { uuid, webfingerMention } from "@versia-server/kit/regex";
|
||||
import { Users } from "@versia-server/kit/tables";
|
||||
import { federationBridgeLogger } from "@versia-server/logging";
|
||||
import { and, eq, isNull } from "drizzle-orm";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
|
|
@ -90,8 +90,7 @@ export default apiRoute((app) =>
|
|||
} catch (e) {
|
||||
const error = e as ApiError;
|
||||
|
||||
getLogger(["federation", "bridge"])
|
||||
.error`Error from bridge: ${error.message}`;
|
||||
federationBridgeLogger.error`Error from bridge: ${error.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,11 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import { config } from "@versia-server/config";
|
||||
import { Note, setupDatabase } from "@versia-server/kit/db";
|
||||
import { connection } from "@versia-server/kit/redis";
|
||||
import { configureLoggers } from "@/loggers";
|
||||
import { serverLogger } from "@versia-server/logging";
|
||||
import { searchManager } from "../../classes/search/search-manager.ts";
|
||||
|
||||
const timeAtStart = performance.now();
|
||||
|
||||
await configureLoggers();
|
||||
|
||||
const serverLogger = getLogger("server");
|
||||
|
||||
console.info(`
|
||||
██╗ ██╗███████╗██████╗ ███████╗██╗ █████╗
|
||||
██║ ██║██╔════╝██╔══██╗██╔════╝██║██╔══██╗
|
||||
|
|
|
|||
|
|
@ -716,34 +716,35 @@ export const ConfigSchema = z
|
|||
admin: z.array(z.nativeEnum(RolePermission)).default(ADMIN_ROLES),
|
||||
}),
|
||||
logging: z.strictObject({
|
||||
types: z.record(
|
||||
z.enum([
|
||||
"requests",
|
||||
"responses",
|
||||
"requests_content",
|
||||
"filters",
|
||||
]),
|
||||
z
|
||||
.boolean()
|
||||
.default(false)
|
||||
.or(
|
||||
z.strictObject({
|
||||
level: z
|
||||
.enum([
|
||||
"debug",
|
||||
"info",
|
||||
"warning",
|
||||
"error",
|
||||
"fatal",
|
||||
])
|
||||
.default("info"),
|
||||
log_file_path: z.string().optional(),
|
||||
}),
|
||||
),
|
||||
),
|
||||
log_level: z
|
||||
.enum(["debug", "info", "warning", "error", "fatal"])
|
||||
.default("info"),
|
||||
file: z
|
||||
.strictObject({
|
||||
path: z.string().default("logs/versia.log"),
|
||||
rotation: z
|
||||
.strictObject({
|
||||
max_size: z
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.default(10_000_000), // 10 MB
|
||||
max_files: z
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.default(10),
|
||||
})
|
||||
.optional(),
|
||||
log_level: z
|
||||
.enum([
|
||||
"trace",
|
||||
"debug",
|
||||
"info",
|
||||
"warning",
|
||||
"error",
|
||||
"fatal",
|
||||
])
|
||||
.default("info"),
|
||||
})
|
||||
.optional(),
|
||||
sentry: z
|
||||
.strictObject({
|
||||
dsn: url,
|
||||
|
|
@ -753,9 +754,21 @@ export const ConfigSchema = z
|
|||
trace_propagation_targets: z.array(z.string()).default([]),
|
||||
max_breadcrumbs: z.number().default(100),
|
||||
environment: z.string().optional(),
|
||||
log_level: z
|
||||
.enum([
|
||||
"trace",
|
||||
"debug",
|
||||
"info",
|
||||
"warning",
|
||||
"error",
|
||||
"fatal",
|
||||
])
|
||||
.default("info"),
|
||||
})
|
||||
.optional(),
|
||||
log_file_path: z.string().default("logs/versia.log"),
|
||||
log_level: z
|
||||
.enum(["trace", "debug", "info", "warning", "error", "fatal"])
|
||||
.default("info"),
|
||||
}),
|
||||
debug: z
|
||||
.strictObject({
|
||||
|
|
|
|||
56
packages/logging/formatter.ts
Normal file
56
packages/logging/formatter.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import type { LogLevel, LogRecord } from "@logtape/logtape";
|
||||
import chalk, { type ChalkInstance } from "chalk";
|
||||
|
||||
const levelAbbreviations: Record<LogLevel, string> = {
|
||||
debug: "DBG",
|
||||
info: "INF",
|
||||
warning: "WRN",
|
||||
error: "ERR",
|
||||
fatal: "FTL",
|
||||
trace: "TRC",
|
||||
};
|
||||
|
||||
/**
|
||||
* The styles for the log level in the console.
|
||||
*/
|
||||
const logLevelStyles: Record<LogLevel, ChalkInstance> = {
|
||||
debug: chalk.white.bgGray,
|
||||
info: chalk.black.bgWhite,
|
||||
warning: chalk.black.bgYellow,
|
||||
error: chalk.white.bgRed,
|
||||
fatal: chalk.white.bgRedBright,
|
||||
trace: chalk.white.bgBlue,
|
||||
};
|
||||
|
||||
/**
|
||||
* Pretty colored console formatter.
|
||||
*
|
||||
* @param record The log record to format.
|
||||
* @returns The formatted log record, as an array of arguments for
|
||||
* {@link console.log}.
|
||||
*/
|
||||
export function consoleFormatter(record: LogRecord): string[] {
|
||||
const msg = record.message.join("");
|
||||
const date = new Date(record.timestamp);
|
||||
const time = `${date.getUTCHours().toString().padStart(2, "0")}:${date
|
||||
.getUTCMinutes()
|
||||
.toString()
|
||||
.padStart(
|
||||
2,
|
||||
"0",
|
||||
)}:${date.getUTCSeconds().toString().padStart(2, "0")}.${date
|
||||
.getUTCMilliseconds()
|
||||
.toString()
|
||||
.padStart(3, "0")}`;
|
||||
|
||||
const formattedTime = chalk.gray(time);
|
||||
const formattedLevel = logLevelStyles[record.level](
|
||||
levelAbbreviations[record.level],
|
||||
);
|
||||
const formattedCategory = chalk.gray(record.category.join("\xb7"));
|
||||
const formattedMsg = chalk.reset(msg);
|
||||
|
||||
return [
|
||||
`${formattedTime} ${formattedLevel} ${formattedCategory} ${formattedMsg}`,
|
||||
];
|
||||
}
|
||||
158
packages/logging/index.ts
Normal file
158
packages/logging/index.ts
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import { mkdir } from "node:fs/promises";
|
||||
import { dirname } from "node:path";
|
||||
import { getFileSink, getRotatingFileSink } from "@logtape/file";
|
||||
import {
|
||||
configure,
|
||||
getConsoleSink,
|
||||
getLevelFilter,
|
||||
getLogger,
|
||||
type Sink,
|
||||
withFilter,
|
||||
} from "@logtape/logtape";
|
||||
import { getSentrySink } from "@logtape/sentry";
|
||||
import * as Sentry from "@sentry/bun";
|
||||
import { config } from "@versia-server/config";
|
||||
import { env } from "bun";
|
||||
import pkg from "../../package.json" with { type: "json" };
|
||||
import { consoleFormatter } from "./formatter.ts";
|
||||
|
||||
if (config.logging.file?.path) {
|
||||
// config.logging.file.path is a path to a file, create the directory if it doesn't exist
|
||||
await mkdir(dirname(config.logging.file.path), { recursive: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all configured sinks depending on the configuration.
|
||||
*/
|
||||
const getSinks = (): Record<"file" | "console" | "sentry", Sink> => {
|
||||
const sinks: Record<string, Sink> = {};
|
||||
|
||||
if (config.logging.file) {
|
||||
if (config.logging.file.rotation) {
|
||||
sinks.file = getRotatingFileSink(config.logging.file.path, {
|
||||
maxFiles: config.logging.file.rotation.max_files,
|
||||
maxSize: config.logging.file.rotation.max_size,
|
||||
});
|
||||
} else {
|
||||
sinks.file = getFileSink(config.logging.file.path);
|
||||
}
|
||||
|
||||
sinks.file = withFilter(
|
||||
sinks.file,
|
||||
getLevelFilter(config.logging.file.log_level),
|
||||
);
|
||||
}
|
||||
|
||||
if (config.logging.sentry) {
|
||||
sinks.sentry = getSentrySink(
|
||||
Sentry.init({
|
||||
dsn: config.logging.sentry.dsn.origin,
|
||||
debug: config.logging.sentry.debug,
|
||||
sampleRate: config.logging.sentry.sample_rate,
|
||||
maxBreadcrumbs: config.logging.sentry.max_breadcrumbs,
|
||||
tracesSampleRate: config.logging.sentry.traces_sample_rate,
|
||||
environment: config.logging.sentry.environment,
|
||||
tracePropagationTargets:
|
||||
config.logging.sentry.trace_propagation_targets,
|
||||
release: env.GIT_COMMIT
|
||||
? `${pkg.version}-${env.GIT_COMMIT}`
|
||||
: pkg.version,
|
||||
integrations: [Sentry.extraErrorDataIntegration()],
|
||||
}),
|
||||
);
|
||||
|
||||
sinks.sentry = withFilter(
|
||||
sinks.sentry,
|
||||
getLevelFilter(config.logging.sentry.log_level),
|
||||
);
|
||||
}
|
||||
|
||||
sinks.console = getConsoleSink({
|
||||
formatter: consoleFormatter,
|
||||
});
|
||||
|
||||
sinks.console = withFilter(
|
||||
sinks.console,
|
||||
getLevelFilter(config.logging.log_level),
|
||||
);
|
||||
|
||||
return sinks;
|
||||
};
|
||||
|
||||
const getSinkNames = (): ("file" | "console" | "sentry")[] => {
|
||||
const names = [] as ("file" | "console" | "sentry")[];
|
||||
|
||||
if (config.logging.file) {
|
||||
names.push("file");
|
||||
}
|
||||
|
||||
if (config.logging.sentry) {
|
||||
names.push("sentry");
|
||||
}
|
||||
|
||||
names.push("console");
|
||||
|
||||
return names;
|
||||
};
|
||||
|
||||
await configure({
|
||||
reset: true,
|
||||
sinks: getSinks(),
|
||||
loggers: [
|
||||
{
|
||||
category: "server",
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: ["federation", "inbox"],
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: ["federation", "delivery"],
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: ["federation", "bridge"],
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: ["federation", "resolvers"],
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: ["federation", "messaging"],
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: "database",
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: "webfinger",
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: "sonic",
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
{
|
||||
category: ["logtape", "meta"],
|
||||
lowestLevel: "error",
|
||||
},
|
||||
{
|
||||
category: "plugin",
|
||||
sinks: getSinkNames(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const serverLogger = getLogger("server");
|
||||
export const federationInboxLogger = getLogger(["federation", "inbox"]);
|
||||
export const federationDeliveryLogger = getLogger(["federation", "delivery"]);
|
||||
export const federationBridgeLogger = getLogger(["federation", "bridge"]);
|
||||
export const federationResolversLogger = getLogger(["federation", "resolvers"]);
|
||||
export const federationMessagingLogger = getLogger(["federation", "messaging"]);
|
||||
export const databaseLogger = getLogger("database");
|
||||
export const webfingerLogger = getLogger("webfinger");
|
||||
export const sonicLogger = getLogger("sonic");
|
||||
export const pluginLogger = getLogger("plugin");
|
||||
22
packages/logging/package.json
Normal file
22
packages/logging/package.json
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@versia-server/logging",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./index.ts",
|
||||
"default": "./index.ts"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@versia-server/config": "workspace:*",
|
||||
"@logtape/logtape": "catalog:",
|
||||
"@logtape/file": "catalog:",
|
||||
"@logtape/sentry": "catalog:",
|
||||
"@logtape/otel": "catalog:",
|
||||
"@sentry/bun": "catalog:",
|
||||
"chalk": "catalog:"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import type { Hook } from "@hono/zod-validator";
|
||||
import { getLogger } from "@logtape/logtape";
|
||||
import type { RolePermission } from "@versia/client/schemas";
|
||||
import { config } from "@versia-server/config";
|
||||
import { serverLogger } from "@versia-server/logging";
|
||||
import { extractParams, verifySolution } from "altcha-lib";
|
||||
import chalk from "chalk";
|
||||
import { eq, type SQL } from "drizzle-orm";
|
||||
|
|
@ -418,7 +418,6 @@ export const jsonOrForm = (): MiddlewareHandler<HonoEnv> => {
|
|||
|
||||
export const debugResponse = async (res: Response): Promise<void> => {
|
||||
const body = await res.clone().text();
|
||||
const logger = getLogger("server");
|
||||
|
||||
const status = `${chalk.bold("Status")}: ${chalk.green(res.status)}`;
|
||||
|
||||
|
|
@ -430,9 +429,5 @@ export const debugResponse = async (res: Response): Promise<void> => {
|
|||
|
||||
const bodyLog = `${chalk.bold("Body")}: ${chalk.gray(body)}`;
|
||||
|
||||
if (config.logging.types.requests_content) {
|
||||
logger.debug`${status}\n${headers}\n${bodyLog}`;
|
||||
} else {
|
||||
logger.debug`${status}`;
|
||||
}
|
||||
serverLogger.debug`${status}\n${headers}\n${bodyLog}`;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import * as VersiaEntities from "@versia/sdk/entities";
|
||||
import { config } from "@versia-server/config";
|
||||
import { ApiError } from "@versia-server/kit";
|
||||
import { db } from "@versia-server/kit/db";
|
||||
import { Instances } from "@versia-server/kit/tables";
|
||||
import {
|
||||
federationMessagingLogger,
|
||||
federationResolversLogger,
|
||||
} from "@versia-server/logging";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import chalk from "chalk";
|
||||
import {
|
||||
|
|
@ -175,9 +178,6 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
const wellKnownUrl = new URL("/.well-known/nodeinfo", origin);
|
||||
|
||||
// Go to endpoint, then follow the links to the actual metadata
|
||||
|
||||
const logger = getLogger(["federation", "resolvers"]);
|
||||
|
||||
try {
|
||||
const { json, ok, status } = await fetch(wellKnownUrl, {
|
||||
// @ts-expect-error Bun extension
|
||||
|
|
@ -185,7 +185,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
});
|
||||
|
||||
if (!ok) {
|
||||
logger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
federationResolversLogger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
origin,
|
||||
)} - HTTP ${status}`;
|
||||
return null;
|
||||
|
|
@ -196,7 +196,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
};
|
||||
|
||||
if (!wellKnown.links) {
|
||||
logger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
federationResolversLogger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
origin,
|
||||
)} - No links found`;
|
||||
return null;
|
||||
|
|
@ -209,7 +209,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
);
|
||||
|
||||
if (!metadataUrl) {
|
||||
logger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
federationResolversLogger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
origin,
|
||||
)} - No metadata URL found`;
|
||||
return null;
|
||||
|
|
@ -225,7 +225,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
});
|
||||
|
||||
if (!ok2) {
|
||||
logger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
federationResolversLogger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
origin,
|
||||
)} - HTTP ${status2}`;
|
||||
return null;
|
||||
|
|
@ -264,7 +264,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
},
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
federationResolversLogger.error`Failed to fetch ActivityPub metadata for instance ${chalk.bold(
|
||||
origin,
|
||||
)} - Error! ${error}`;
|
||||
return null;
|
||||
|
|
@ -312,14 +312,12 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
}
|
||||
|
||||
public async updateFromRemote(): Promise<Instance> {
|
||||
const logger = getLogger(["federation", "resolvers"]);
|
||||
|
||||
const output = await Instance.fetchMetadata(
|
||||
new URL(`https://${this.data.baseUrl}`),
|
||||
);
|
||||
|
||||
if (!output) {
|
||||
logger.error`Failed to update instance ${chalk.bold(
|
||||
federationResolversLogger.error`Failed to update instance ${chalk.bold(
|
||||
this.data.baseUrl,
|
||||
)}`;
|
||||
throw new Error("Failed to update instance");
|
||||
|
|
@ -341,12 +339,10 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
}
|
||||
|
||||
public async sendMessage(content: string): Promise<void> {
|
||||
const logger = getLogger(["federation", "messaging"]);
|
||||
|
||||
if (
|
||||
!this.data.extensions?.["pub.versia:instance_messaging"]?.endpoint
|
||||
) {
|
||||
logger.info`Instance ${chalk.gray(
|
||||
federationMessagingLogger.info`Instance ${chalk.gray(
|
||||
this.data.baseUrl,
|
||||
)} does not support Instance Messaging, skipping message`;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import type {
|
||||
Account,
|
||||
Mention as MentionSchema,
|
||||
|
|
@ -29,6 +28,10 @@ import {
|
|||
Users,
|
||||
UserToPinnedNotes,
|
||||
} from "@versia-server/kit/tables";
|
||||
import {
|
||||
federationDeliveryLogger,
|
||||
federationResolversLogger,
|
||||
} from "@versia-server/logging";
|
||||
import { password as bunPassword, randomUUIDv7 } from "bun";
|
||||
import chalk from "chalk";
|
||||
import {
|
||||
|
|
@ -49,7 +52,6 @@ import { htmlToText } from "html-to-text";
|
|||
import type { z } from "zod";
|
||||
import { getBestContentType } from "@/content_types";
|
||||
import { randomString } from "@/math";
|
||||
import { sentry } from "@/sentry";
|
||||
import { searchManager } from "~/classes/search/search-manager";
|
||||
import type { HttpVerb, KnownEntity } from "~/types/api.ts";
|
||||
import {
|
||||
|
|
@ -1165,8 +1167,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
}
|
||||
|
||||
public static async resolve(uri: URL): Promise<User | null> {
|
||||
getLogger(["federation", "resolvers"])
|
||||
.debug`Resolving user ${chalk.gray(uri)}`;
|
||||
federationResolversLogger.debug`Resolving user ${chalk.gray(uri)}`;
|
||||
// Check if user not already in database
|
||||
const foundUser = await User.fromSql(eq(Users.uri, uri.href));
|
||||
|
||||
|
|
@ -1187,8 +1188,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
return await User.fromId(userUuid[0]);
|
||||
}
|
||||
|
||||
getLogger(["federation", "resolvers"])
|
||||
.debug`User not found in database, fetching from remote`;
|
||||
federationResolversLogger.debug`User not found in database, fetching from remote`;
|
||||
|
||||
return User.fromVersia(uri);
|
||||
}
|
||||
|
|
@ -1419,11 +1419,10 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
entity,
|
||||
);
|
||||
} catch (e) {
|
||||
getLogger(["federation", "delivery"]).error`Federating ${chalk.gray(
|
||||
federationDeliveryLogger.error`Federating ${chalk.gray(
|
||||
entity.data.type,
|
||||
)} to ${user.uri} ${chalk.bold.red("failed")}`;
|
||||
getLogger(["federation", "delivery"]).error`${e}`;
|
||||
sentry?.captureException(e);
|
||||
federationDeliveryLogger.error`${e}`;
|
||||
|
||||
return { ok: false };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@
|
|||
"chalk": "catalog:",
|
||||
"@versia/client": "workspace:*",
|
||||
"@versia-server/config": "workspace:*",
|
||||
"@versia-server/logging": "workspace:*",
|
||||
"@versia/sdk": "workspace:*",
|
||||
"html-to-text": "catalog:",
|
||||
"@logtape/logtape": "catalog:",
|
||||
"sharp": "catalog:",
|
||||
"magic-regexp": "catalog:",
|
||||
"altcha-lib": "catalog:",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import { config } from "@versia-server/config";
|
||||
import { databaseLogger } from "@versia-server/logging";
|
||||
import { SQL } from "bun";
|
||||
import chalk from "chalk";
|
||||
import { type BunSQLDatabase, drizzle } from "drizzle-orm/bun-sql";
|
||||
|
|
@ -40,8 +40,6 @@ export const db =
|
|||
: drizzle(primaryDb, { schema });
|
||||
|
||||
export const setupDatabase = async (info = true): Promise<void> => {
|
||||
const logger = getLogger("database");
|
||||
|
||||
for (const dbPool of [primaryDb, ...replicas]) {
|
||||
try {
|
||||
await dbPool.connect();
|
||||
|
|
@ -53,7 +51,7 @@ export const setupDatabase = async (info = true): Promise<void> => {
|
|||
return;
|
||||
}
|
||||
|
||||
logger.fatal`Failed to connect to database ${chalk.bold(
|
||||
databaseLogger.fatal`Failed to connect to database ${chalk.bold(
|
||||
// Index of the database in the array
|
||||
replicas.indexOf(dbPool) === -1
|
||||
? "primary"
|
||||
|
|
@ -65,17 +63,17 @@ export const setupDatabase = async (info = true): Promise<void> => {
|
|||
}
|
||||
|
||||
// Migrate the database
|
||||
info && logger.info`Migrating database...`;
|
||||
info && databaseLogger.info`Migrating database...`;
|
||||
|
||||
try {
|
||||
await migrate(db, {
|
||||
migrationsFolder: "./packages/plugin-kit/tables/migrations",
|
||||
});
|
||||
} catch (e) {
|
||||
logger.fatal`Failed to migrate database. Please check your configuration.`;
|
||||
databaseLogger.fatal`Failed to migrate database. Please check your configuration.`;
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
info && logger.info`Database migrated`;
|
||||
info && databaseLogger.info`Database migrated`;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import process from "node:process";
|
||||
import { getLogger } from "@logtape/logtape";
|
||||
import { serverLogger } from "@versia-server/logging";
|
||||
import chalk from "chalk";
|
||||
import { sentry } from "@/sentry";
|
||||
import { workers } from "./workers.ts";
|
||||
|
||||
process.on("SIGINT", () => {
|
||||
|
|
@ -9,9 +8,6 @@ process.on("SIGINT", () => {
|
|||
});
|
||||
|
||||
await import("./setup.ts");
|
||||
sentry?.captureMessage("Server started", "info");
|
||||
|
||||
const serverLogger = getLogger("server");
|
||||
|
||||
for (const [worker, fn] of Object.entries(workers)) {
|
||||
serverLogger.info`Starting ${worker} Worker...`;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
"dependencies": {
|
||||
"@versia-server/config": "workspace:*",
|
||||
"@versia-server/kit": "workspace:*",
|
||||
"chalk": "catalog:",
|
||||
"@logtape/logtape": "catalog:"
|
||||
"@versia-server/logging": "workspace:*",
|
||||
"chalk": "catalog:"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,12 @@
|
|||
import { getLogger } from "@logtape/logtape";
|
||||
import { config } from "@versia-server/config";
|
||||
import { Note, setupDatabase } from "@versia-server/kit/db";
|
||||
import { connection } from "@versia-server/kit/redis";
|
||||
import { serverLogger } from "@versia-server/logging";
|
||||
import chalk from "chalk";
|
||||
import { configureLoggers } from "@/loggers";
|
||||
import { searchManager } from "../../classes/search/search-manager.ts";
|
||||
|
||||
const timeAtStart = performance.now();
|
||||
|
||||
await configureLoggers();
|
||||
|
||||
const serverLogger = getLogger("server");
|
||||
|
||||
console.info(`
|
||||
██╗ ██╗███████╗██████╗ ███████╗██╗ █████╗
|
||||
██║ ██║██╔════╝██╔══██╗██╔════╝██║██╔══██╗
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue