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,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",

View file

@ -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());

View file

@ -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}` },

View file

@ -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();
});

View file

@ -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:",

View file

@ -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);
},

View file

@ -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}`;
}
}

View file

@ -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(`

View file

@ -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({

View 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
View 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");

View 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:"
}
}

View file

@ -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}`;
};

View file

@ -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`;

View file

@ -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 };
}

View file

@ -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:",

View file

@ -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`;
};

View file

@ -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...`;

View file

@ -40,7 +40,7 @@
"dependencies": {
"@versia-server/config": "workspace:*",
"@versia-server/kit": "workspace:*",
"chalk": "catalog:",
"@logtape/logtape": "catalog:"
"@versia-server/logging": "workspace:*",
"chalk": "catalog:"
}
}

View file

@ -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(`