diff --git a/.config/devenv.yml b/.config/devenv.yml index 77d4ce66b6..5e3ca24e8d 100644 --- a/.config/devenv.yml +++ b/.config/devenv.yml @@ -19,10 +19,4 @@ id: 'aid' # '10.69.1.0/24' #] -logLevel: [ - 'error', - 'success', - 'warning', - 'debug', - 'info' -] +maxLogLevel: 'debug' diff --git a/.config/example.yml b/.config/example.yml index 17149f6c3a..75ee713526 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -145,16 +145,11 @@ reservedUsernames: [ # IP address family used for outgoing request (ipv4, ipv6 or dual) #outgoingAddressFamily: ipv4 -# Log Option -# Production env: ['error', 'success', 'warning', 'info'] -# Debug/Test env or Troubleshooting: ['error', 'success', 'warning', 'debug' ,'info'] -# Production env which storage space or IO is tight: ['error', 'warning'] -logLevel: [ - 'error', - 'success', - 'warning', - 'info' -] +# Log level (error, warning, info, debug, trace) +# Production env: info +# Production env whose storage space or IO is tight: warning +# Debug/Test env or Troubleshooting: debug (or trace) +maxLogLevel: info # Syslog option #syslog: diff --git a/Cargo.lock b/Cargo.lock index 2959ad5bf6..5d3dba3b9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,6 +171,8 @@ dependencies = [ "strum 0.26.2", "thiserror", "tokio", + "tracing", + "tracing-subscriber", "url", "urlencoding", ] @@ -1128,6 +1130,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num" version = "0.4.2" @@ -1285,6 +1297,12 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1949,6 +1967,15 @@ dependencies = [ "keccak", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2380,6 +2407,16 @@ dependencies = [ "syn 2.0.58", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "time" version = "0.3.36" @@ -2514,6 +2551,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", ] [[package]] @@ -2593,6 +2656,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2687,6 +2756,28 @@ dependencies = [ "wasite", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 42de97a220..056f1006b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,8 @@ strum = "0.26.2" syn = "2.0.58" thiserror = "1.0.58" tokio = "1.37.0" +tracing = "0.1.40" +tracing-subscriber = "0.3.1" url = "2.5.0" urlencoding = "2.1.3" diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index 3a222cd4a5..22c786c6d5 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -36,6 +36,8 @@ serde_yaml = { workspace = true } strum = { workspace = true, features = ["derive"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } url = { workspace = true } urlencoding = { workspace = true } diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 6dc5848bd4..fca4394501 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -38,7 +38,9 @@ export interface ServerConfig { inboxJobPerSec?: number deliverJobMaxAttempts?: number inboxJobMaxAttempts?: number + /** deprecated */ logLevel?: Array + maxLogLevel?: string syslog?: SysLogConfig proxyRemoteFiles?: boolean mediaProxy?: string @@ -148,7 +150,9 @@ export interface Config { inboxJobPerSec?: number deliverJobMaxAttempts?: number inboxJobMaxAttempts?: number + /** deprecated */ logLevel?: Array + maxLogLevel?: string syslog?: SysLogConfig proxyRemoteFiles?: boolean mediaProxy?: string @@ -1122,6 +1126,7 @@ export interface Webhook { latestSentAt: Date | null latestStatus: number | null } +export function initializeRustLogger(): void export function watchNote(watcherId: string, noteAuthorId: string, noteId: string): Promise export function unwatchNote(watcherId: string, noteId: string): Promise export enum ChatEvent { diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index 1b7b487ede..430e799430 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,7 +310,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, watchNote, unwatchNote, ChatEvent, publishToChatStream, getTimestamp, genId, genIdAt, secureRndstr } = nativeBinding +const { loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initializeRustLogger, watchNote, unwatchNote, ChatEvent, publishToChatStream, getTimestamp, genId, genIdAt, secureRndstr } = nativeBinding module.exports.loadEnv = loadEnv module.exports.loadConfig = loadConfig @@ -354,6 +354,7 @@ module.exports.RelayStatusEnum = RelayStatusEnum module.exports.UserEmojimodpermEnum = UserEmojimodpermEnum module.exports.UserProfileFfvisibilityEnum = UserProfileFfvisibilityEnum module.exports.UserProfileMutingnotificationtypesEnum = UserProfileMutingnotificationtypesEnum +module.exports.initializeRustLogger = initializeRustLogger module.exports.watchNote = watchNote module.exports.unwatchNote = unwatchNote module.exports.ChatEvent = ChatEvent diff --git a/packages/backend-rs/src/config/server.rs b/packages/backend-rs/src/config/server.rs index 5a4ee481cd..3cba6722cd 100644 --- a/packages/backend-rs/src/config/server.rs +++ b/packages/backend-rs/src/config/server.rs @@ -36,8 +36,11 @@ struct ServerConfig { pub deliver_job_max_attempts: Option, pub inbox_job_max_attempts: Option, + /// deprecated pub log_level: Option>, + pub max_log_level: Option, + pub syslog: Option, pub proxy_remote_files: Option, @@ -197,7 +200,9 @@ pub struct Config { pub inbox_job_per_sec: Option, pub deliver_job_max_attempts: Option, pub inbox_job_max_attempts: Option, + /// deprecated pub log_level: Option>, + pub max_log_level: Option, pub syslog: Option, pub proxy_remote_files: Option, pub media_proxy: Option, @@ -346,6 +351,7 @@ fn load_config() -> Config { deliver_job_max_attempts: server_config.deliver_job_max_attempts, inbox_job_max_attempts: server_config.inbox_job_max_attempts, log_level: server_config.log_level, + max_log_level: server_config.max_log_level, syslog: server_config.syslog, proxy_remote_files: server_config.proxy_remote_files, media_proxy: server_config.media_proxy, diff --git a/packages/backend-rs/src/database/postgresql.rs b/packages/backend-rs/src/database/postgresql.rs index ec0945fbe3..03b610598d 100644 --- a/packages/backend-rs/src/database/postgresql.rs +++ b/packages/backend-rs/src/database/postgresql.rs @@ -1,5 +1,6 @@ use crate::config::CONFIG; -use sea_orm::{Database, DbConn, DbErr}; +use sea_orm::{ConnectOptions, Database, DbConn, DbErr}; +use tracing::log::LevelFilter; static DB_CONN: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); @@ -12,7 +13,10 @@ async fn init_database() -> Result<&'static DbConn, DbErr> { CONFIG.db.port, CONFIG.db.db, ); - let conn = Database::connect(database_uri).await?; + let option: ConnectOptions = ConnectOptions::new(database_uri) + .sqlx_logging_level(LevelFilter::Trace) + .to_owned(); + let conn = Database::connect(option).await?; Ok(DB_CONN.get_or_init(move || conn)) } diff --git a/packages/backend-rs/src/service/log.rs b/packages/backend-rs/src/service/log.rs new file mode 100644 index 0000000000..5164c9d747 --- /dev/null +++ b/packages/backend-rs/src/service/log.rs @@ -0,0 +1,42 @@ +use crate::config::CONFIG; +use tracing::Level; +use tracing_subscriber::FmtSubscriber; + +#[crate::export(js_name = "initializeRustLogger")] +pub fn initialize_logger() { + let mut builder = FmtSubscriber::builder(); + + // Deprecated + if let Some(levels) = &CONFIG.log_level { + if levels.contains(&"error".to_string()) { + builder = builder.with_max_level(Level::ERROR); + } + if levels.contains(&"warning".to_string()) { + builder = builder.with_max_level(Level::WARN); + } + if levels.contains(&"info".to_string()) { + builder = builder.with_max_level(Level::INFO); + } + if levels.contains(&"debug".to_string()) { + builder = builder.with_max_level(Level::DEBUG); + } + if levels.contains(&"trace".to_string()) { + builder = builder.with_max_level(Level::TRACE); + } + } else if let Some(max_level) = &CONFIG.max_log_level { + builder = builder.with_max_level(match max_level.as_str() { + "error" => Level::ERROR, + "warning" => Level::WARN, + "info" => Level::INFO, + "debug" => Level::DEBUG, + "trace" => Level::TRACE, + _ => Level::INFO, + }); + } else { + builder = builder.with_max_level(Level::INFO); + }; + + let subscriber = builder.with_level(true).pretty().finish(); + + tracing::subscriber::set_global_default(subscriber).expect("Failed to initialize the logger"); +} diff --git a/packages/backend-rs/src/service/mod.rs b/packages/backend-rs/src/service/mod.rs index a1b1ada71b..0a2644857f 100644 --- a/packages/backend-rs/src/service/mod.rs +++ b/packages/backend-rs/src/service/mod.rs @@ -1,2 +1,3 @@ +pub mod log; pub mod note; pub mod stream; diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index e9e3ceb98a..f8126fb6ab 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -9,6 +9,7 @@ import semver from "semver"; import Logger from "@/services/logger.js"; import type { Config } from "backend-rs"; +import { initializeRustLogger } from "backend-rs"; import { fetchMeta, removeOldAttestationChallenges } from "backend-rs"; import { config, envOption } from "@/config.js"; import { showMachineInfo } from "@/misc/show-machine-info.js"; @@ -94,6 +95,7 @@ export async function masterMain() { await showMachineInfo(bootLogger); showNodejsVersion(); await connectDb(); + initializeRustLogger(); } catch (e) { bootLogger.error( `Fatal error occurred during initialization:\n${inspect(e)}`, @@ -103,13 +105,13 @@ export async function masterMain() { process.exit(1); } - bootLogger.succ("Firefish initialized"); + bootLogger.info("Firefish initialized"); if (!envOption.disableClustering) { await spawnWorkers(config.clusterLimits); } - bootLogger.succ( + bootLogger.info( `Now listening on port ${config.port} on ${config.url}`, null, true, @@ -160,7 +162,7 @@ async function connectDb(): Promise { const v = await db .query("SHOW server_version") .then((x) => x[0].server_version); - dbLogger.succ(`Connected: v${v}`); + dbLogger.info(`Connected: v${v}`); } catch (e) { dbLogger.error("Failed to connect to the database", null, true); dbLogger.error(inspect(e)); @@ -196,7 +198,7 @@ async function spawnWorkers( `Starting ${clusterLimits.web} web workers and ${clusterLimits.queue} queue workers (total ${total})...`, ); await Promise.all(workers.map((mode) => spawnWorker(mode))); - bootLogger.succ("All workers started"); + bootLogger.info("All workers started"); } function spawnWorker(mode: "web" | "queue"): Promise { diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index 1295136054..d054aaf109 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -80,7 +80,7 @@ import { dbLogger } from "./logger.js"; const sqlLogger = dbLogger.createSubLogger("sql", "gray", false); -class MyCustomLogger implements Logger { +class DbLogger implements Logger { private highlight(sql: string) { return highlight.highlight(sql, { language: "sql", @@ -89,15 +89,16 @@ class MyCustomLogger implements Logger { } public logQuery(query: string, parameters?: any[]) { - sqlLogger.info(this.highlight(query).substring(0, 100)); + sqlLogger.trace(this.highlight(query).substring(0, 100)); } public logQueryError(error: string, query: string, parameters?: any[]) { + sqlLogger.error(error); sqlLogger.error(this.highlight(query)); } public logQuerySlow(time: number, query: string, parameters?: any[]) { - sqlLogger.warn(this.highlight(query)); + sqlLogger.trace(this.highlight(query)); } public logSchemaBuild(message: string) { @@ -215,7 +216,7 @@ export const db = new DataSource({ } : false, logging: log, - logger: log ? new MyCustomLogger() : undefined, + logger: log ? new DbLogger() : undefined, maxQueryExecutionTime: 300, entities: entities, migrations: ["../../migration/*.js"], diff --git a/packages/backend/src/misc/download-url.ts b/packages/backend/src/misc/download-url.ts index e3066ff333..d79d6a349e 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -94,7 +94,7 @@ export async function downloadUrl(url: string, path: string): Promise { } } - logger.succ(`Download finished: ${chalk.cyan(url)}`); + logger.info(`Download finished: ${chalk.cyan(url)}`); } export function isPrivateIp(ip: string): boolean { diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index 6272a5e668..5531ba6e99 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -564,12 +564,12 @@ export default function () { export function destroy() { deliverQueue.once("cleaned", (jobs, status) => { - deliverLogger.succ(`Cleaned ${jobs.length} ${status} jobs`); + deliverLogger.info(`Cleaned ${jobs.length} ${status} jobs`); }); deliverQueue.clean(0, "delayed"); inboxQueue.once("cleaned", (jobs, status) => { - inboxLogger.succ(`Cleaned ${jobs.length} ${status} jobs`); + inboxLogger.info(`Cleaned ${jobs.length} ${status} jobs`); }); inboxQueue.clean(0, "delayed"); } diff --git a/packages/backend/src/queue/processors/db/delete-account.ts b/packages/backend/src/queue/processors/db/delete-account.ts index b43cdd137c..b5218064de 100644 --- a/packages/backend/src/queue/processors/db/delete-account.ts +++ b/packages/backend/src/queue/processors/db/delete-account.ts @@ -43,7 +43,7 @@ export async function deleteAccount( await Notes.delete(notes.map((note) => note.id)); } - logger.succ("All of notes deleted"); + logger.info("All of notes deleted"); } { @@ -73,7 +73,7 @@ export async function deleteAccount( } } - logger.succ("All of files deleted"); + logger.info("All of files deleted"); } { diff --git a/packages/backend/src/queue/processors/db/delete-drive-files.ts b/packages/backend/src/queue/processors/db/delete-drive-files.ts index 28e4771329..f44814e6a9 100644 --- a/packages/backend/src/queue/processors/db/delete-drive-files.ts +++ b/packages/backend/src/queue/processors/db/delete-drive-files.ts @@ -54,7 +54,7 @@ export async function deleteDriveFiles( job.progress(deletedCount / total); } - logger.succ( + logger.info( `All drive files (${deletedCount}) of ${user.id} has been deleted.`, ); done(); diff --git a/packages/backend/src/queue/processors/db/export-blocking.ts b/packages/backend/src/queue/processors/db/export-blocking.ts index 4fd222b3ef..73c7047bed 100644 --- a/packages/backend/src/queue/processors/db/export-blocking.ts +++ b/packages/backend/src/queue/processors/db/export-blocking.ts @@ -83,7 +83,7 @@ export async function exportBlocking( } stream.end(); - logger.succ(`Exported to: ${path}`); + logger.info(`Exported to: ${path}`); const fileName = `blocking-${dateFormat( new Date(), @@ -96,7 +96,7 @@ export async function exportBlocking( force: true, }); - logger.succ(`Exported to: ${driveFile.id}`); + logger.info(`Exported to: ${driveFile.id}`); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/db/export-custom-emojis.ts b/packages/backend/src/queue/processors/db/export-custom-emojis.ts index 157751c1aa..1817e10078 100644 --- a/packages/backend/src/queue/processors/db/export-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/export-custom-emojis.ts @@ -105,7 +105,7 @@ export async function exportCustomEmojis( zlib: { level: 0 }, }); archiveStream.on("close", async () => { - logger.succ(`Exported to: ${archivePath}`); + logger.info(`Exported to: ${archivePath}`); const fileName = `custom-emojis-${dateFormat( new Date(), @@ -118,7 +118,7 @@ export async function exportCustomEmojis( force: true, }); - logger.succ(`Exported to: ${driveFile.id}`); + logger.info(`Exported to: ${driveFile.id}`); cleanup(); archiveCleanup(); done(); diff --git a/packages/backend/src/queue/processors/db/export-following.ts b/packages/backend/src/queue/processors/db/export-following.ts index 65d3673e70..bbaf7e5fd5 100644 --- a/packages/backend/src/queue/processors/db/export-following.ts +++ b/packages/backend/src/queue/processors/db/export-following.ts @@ -91,7 +91,7 @@ export async function exportFollowing( } stream.end(); - logger.succ(`Exported to: ${path}`); + logger.info(`Exported to: ${path}`); const fileName = `following-${dateFormat( new Date(), @@ -104,7 +104,7 @@ export async function exportFollowing( force: true, }); - logger.succ(`Exported to: ${driveFile.id}`); + logger.info(`Exported to: ${driveFile.id}`); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/db/export-mute.ts b/packages/backend/src/queue/processors/db/export-mute.ts index f7906ac9f0..072ddf1ddf 100644 --- a/packages/backend/src/queue/processors/db/export-mute.ts +++ b/packages/backend/src/queue/processors/db/export-mute.ts @@ -84,7 +84,7 @@ export async function exportMute( } stream.end(); - logger.succ(`Exported to: ${path}`); + logger.info(`Exported to: ${path}`); const fileName = `mute-${dateFormat( new Date(), @@ -97,7 +97,7 @@ export async function exportMute( force: true, }); - logger.succ(`Exported to: ${driveFile.id}`); + logger.info(`Exported to: ${driveFile.id}`); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/db/export-notes.ts b/packages/backend/src/queue/processors/db/export-notes.ts index bf53f83603..9a2b823bf5 100644 --- a/packages/backend/src/queue/processors/db/export-notes.ts +++ b/packages/backend/src/queue/processors/db/export-notes.ts @@ -91,7 +91,7 @@ export async function exportNotes( await write("]"); stream.end(); - logger.succ(`Exported to: ${path}`); + logger.info(`Exported to: ${path}`); const fileName = `notes-${dateFormat( new Date(), @@ -104,7 +104,7 @@ export async function exportNotes( force: true, }); - logger.succ(`Exported to: ${driveFile.id}`); + logger.info(`Exported to: ${driveFile.id}`); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/db/export-user-lists.ts b/packages/backend/src/queue/processors/db/export-user-lists.ts index e6877f31fc..709da535c8 100644 --- a/packages/backend/src/queue/processors/db/export-user-lists.ts +++ b/packages/backend/src/queue/processors/db/export-user-lists.ts @@ -59,7 +59,7 @@ export async function exportUserLists( } stream.end(); - logger.succ(`Exported to: ${path}`); + logger.info(`Exported to: ${path}`); const fileName = `user-lists-${dateFormat( new Date(), @@ -72,7 +72,7 @@ export async function exportUserLists( force: true, }); - logger.succ(`Exported to: ${driveFile.id}`); + logger.info(`Exported to: ${driveFile.id}`); } finally { cleanup(); } diff --git a/packages/backend/src/queue/processors/db/import-blocking.ts b/packages/backend/src/queue/processors/db/import-blocking.ts index e933b60783..512d2f8c4b 100644 --- a/packages/backend/src/queue/processors/db/import-blocking.ts +++ b/packages/backend/src/queue/processors/db/import-blocking.ts @@ -74,6 +74,6 @@ export async function importBlocking( } } - logger.succ("Imported"); + logger.info("Imported"); done(); } diff --git a/packages/backend/src/queue/processors/db/import-custom-emojis.ts b/packages/backend/src/queue/processors/db/import-custom-emojis.ts index f2371429f2..edbaf99b5a 100644 --- a/packages/backend/src/queue/processors/db/import-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/import-custom-emojis.ts @@ -143,8 +143,8 @@ export async function importCustomEmojis( cleanup(); - logger.succ("Imported"); + logger.info("Imported"); done(); }); - logger.succ(`Unzipping to ${outputPath}`); + logger.info(`Unzipping to ${outputPath}`); } diff --git a/packages/backend/src/queue/processors/db/import-firefish-post.ts b/packages/backend/src/queue/processors/db/import-firefish-post.ts index be412fc490..6599519751 100644 --- a/packages/backend/src/queue/processors/db/import-firefish-post.ts +++ b/packages/backend/src/queue/processors/db/import-firefish-post.ts @@ -94,7 +94,7 @@ export async function importCkPost( } else { logger.info(`Note exist`); } - logger.succ("Imported"); + logger.info("Imported"); if (post.childNotes) { for (const child of post.childNotes) { createImportCkPostJob( diff --git a/packages/backend/src/queue/processors/db/import-following.ts b/packages/backend/src/queue/processors/db/import-following.ts index 77017fa9ff..e09781577e 100644 --- a/packages/backend/src/queue/processors/db/import-following.ts +++ b/packages/backend/src/queue/processors/db/import-following.ts @@ -111,6 +111,6 @@ export async function importFollowing( } } - logger.succ("Imported"); + logger.info("Imported"); done(); } diff --git a/packages/backend/src/queue/processors/db/import-masto-post.ts b/packages/backend/src/queue/processors/db/import-masto-post.ts index d8f848d206..ccd43ec357 100644 --- a/packages/backend/src/queue/processors/db/import-masto-post.ts +++ b/packages/backend/src/queue/processors/db/import-masto-post.ts @@ -125,5 +125,5 @@ export async function importMastoPost( job.progress(100); done(); - logger.succ("Imported"); + logger.info("Imported"); } diff --git a/packages/backend/src/queue/processors/db/import-muting.ts b/packages/backend/src/queue/processors/db/import-muting.ts index b0d8f40956..bdb1899cd5 100644 --- a/packages/backend/src/queue/processors/db/import-muting.ts +++ b/packages/backend/src/queue/processors/db/import-muting.ts @@ -74,7 +74,7 @@ export async function importMuting( } } - logger.succ("Imported"); + logger.info("Imported"); done(); } diff --git a/packages/backend/src/queue/processors/db/import-posts.ts b/packages/backend/src/queue/processors/db/import-posts.ts index eee74bddeb..ac6b69ac17 100644 --- a/packages/backend/src/queue/processors/db/import-posts.ts +++ b/packages/backend/src/queue/processors/db/import-posts.ts @@ -47,7 +47,7 @@ export async function importPosts( // handle error logger.warn(`Failed to read Mastodon archive:\n${inspect(e)}`); } - logger.succ("Mastodon archive imported"); + logger.info("Mastodon archive imported"); done(); return; } @@ -73,7 +73,7 @@ export async function importPosts( logger.warn(`Error occured while reading:\n${inspect(e)}`); } - logger.succ("Imported"); + logger.info("Imported"); done(); } diff --git a/packages/backend/src/queue/processors/db/import-user-lists.ts b/packages/backend/src/queue/processors/db/import-user-lists.ts index 2bdecfd389..1fe44d03e7 100644 --- a/packages/backend/src/queue/processors/db/import-user-lists.ts +++ b/packages/backend/src/queue/processors/db/import-user-lists.ts @@ -90,6 +90,6 @@ export async function importUserLists( } } - logger.succ("Imported"); + logger.info("Imported"); done(); } diff --git a/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts b/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts index 14ad1b1014..0911fc4960 100644 --- a/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts +++ b/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts @@ -48,6 +48,6 @@ export default async function cleanRemoteFiles( job.progress(deletedCount / total); } - logger.succ("All cached remote files has been deleted."); + logger.info("All cached remote files has been deleted."); done(); } diff --git a/packages/backend/src/queue/processors/system/check-expired-mutings.ts b/packages/backend/src/queue/processors/system/check-expired-mutings.ts index a482d0218a..05518ae8e1 100644 --- a/packages/backend/src/queue/processors/system/check-expired-mutings.ts +++ b/packages/backend/src/queue/processors/system/check-expired-mutings.ts @@ -28,6 +28,6 @@ export async function checkExpiredMutings( } } - logger.succ("All expired mutings checked."); + logger.info("All expired mutings checked."); done(); } diff --git a/packages/backend/src/queue/processors/system/clean-charts.ts b/packages/backend/src/queue/processors/system/clean-charts.ts index 663441e638..22845bb810 100644 --- a/packages/backend/src/queue/processors/system/clean-charts.ts +++ b/packages/backend/src/queue/processors/system/clean-charts.ts @@ -11,6 +11,6 @@ export async function cleanCharts( ): Promise { logger.info("Cleaning active users chart..."); await activeUsersChart.clean(); - logger.succ("Active users chart has been cleaned."); + logger.info("Active users chart has been cleaned."); done(); } diff --git a/packages/backend/src/queue/processors/system/clean.ts b/packages/backend/src/queue/processors/system/clean.ts index fbd45b0bb9..2319d7b484 100644 --- a/packages/backend/src/queue/processors/system/clean.ts +++ b/packages/backend/src/queue/processors/system/clean.ts @@ -16,6 +16,6 @@ export async function clean( createdAt: LessThan(new Date(Date.now() - 1000 * 60 * 60 * 24 * 90)), }); - logger.succ("Cleaned."); + logger.info("Cleaned."); done(); } diff --git a/packages/backend/src/queue/processors/system/local-emoji-size.ts b/packages/backend/src/queue/processors/system/local-emoji-size.ts index 73595ed77b..6a885de54c 100644 --- a/packages/backend/src/queue/processors/system/local-emoji-size.ts +++ b/packages/backend/src/queue/processors/system/local-emoji-size.ts @@ -34,10 +34,10 @@ export async function setLocalEmojiSizes( } finally { // wait for 1sec so that this would not overwhelm the object storage. await new Promise((resolve) => setTimeout(resolve, 1000)); - if (i % 10 === 9) logger.succ(`fetched ${i + 1}/${emojis.length} emojis`); + if (i % 10 === 9) logger.info(`fetched ${i + 1}/${emojis.length} emojis`); } } - logger.succ("Done."); + logger.info("Done."); done(); } diff --git a/packages/backend/src/queue/processors/system/verify-links.ts b/packages/backend/src/queue/processors/system/verify-links.ts index 230e55de52..bcd69d4f15 100644 --- a/packages/backend/src/queue/processors/system/verify-links.ts +++ b/packages/backend/src/queue/processors/system/verify-links.ts @@ -39,6 +39,6 @@ export async function verifyLinks( } } - logger.succ("All links successfully verified."); + logger.info("All links successfully verified."); done(); } diff --git a/packages/backend/src/remote/resolve-user.ts b/packages/backend/src/remote/resolve-user.ts index 69a99c767a..cb999cd1bb 100644 --- a/packages/backend/src/remote/resolve-user.ts +++ b/packages/backend/src/remote/resolve-user.ts @@ -56,7 +56,7 @@ export async function resolveUser( if (user == null) { const self = await resolveSelf(acctLower); - logger.succ(`return new remote user: ${chalk.magenta(acctLower)}`); + logger.info(`return new remote user: ${chalk.magenta(acctLower)}`); return await createPerson(self.href); } diff --git a/packages/backend/src/server/web/url-preview.ts b/packages/backend/src/server/web/url-preview.ts index 8fd757ef14..f4ad758dc5 100644 --- a/packages/backend/src/server/web/url-preview.ts +++ b/packages/backend/src/server/web/url-preview.ts @@ -43,7 +43,7 @@ export const urlPreviewHandler = async (ctx: Koa.Context) => { lang: lang ?? "en-US", }); - logger.succ(`Got preview of ${url}: ${summary.title}`); + logger.info(`Got preview of ${url}: ${summary.title}`); if ( summary.url && diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index d180bbabf3..6a28a90b80 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -653,7 +653,7 @@ export async function addFile({ ); } - logger.succ(`drive file has been created ${file.id}`); + logger.info(`drive file has been created ${file.id}`); if (user) { DriveFiles.pack(file, { self: true }).then((packedFile) => { diff --git a/packages/backend/src/services/drive/upload-from-url.ts b/packages/backend/src/services/drive/upload-from-url.ts index e7b084bda1..a3b6fc7e51 100644 --- a/packages/backend/src/services/drive/upload-from-url.ts +++ b/packages/backend/src/services/drive/upload-from-url.ts @@ -86,7 +86,7 @@ export async function uploadFromUrl({ requestHeaders, usageHint, }); - logger.succ(`Got: ${driveFile.id}`); + logger.info(`Got: ${driveFile.id}`); return driveFile; } catch (e) { logger.error(`Failed to create drive file:\n${inspect(e)}`); diff --git a/packages/backend/src/services/fetch-instance-metadata.ts b/packages/backend/src/services/fetch-instance-metadata.ts index 18e6411e88..bb9f9d0bd1 100644 --- a/packages/backend/src/services/fetch-instance-metadata.ts +++ b/packages/backend/src/services/fetch-instance-metadata.ts @@ -49,7 +49,7 @@ export async function fetchInstanceMetadata( getDescription(info, dom, manifest).catch(() => null), ]); - logger.succ(`Successfuly fetched metadata of ${instance.host}`); + logger.info(`Successfuly fetched metadata of ${instance.host}`); const updates = { infoUpdatedAt: new Date(), @@ -105,7 +105,7 @@ export async function fetchInstanceMetadata( await Instances.update(instance.id, updates); - logger.succ(`Successfuly updated metadata of ${instance.host}`); + logger.info(`Successfuly updated metadata of ${instance.host}`); } catch (e) { logger.error( `Failed to update metadata of ${instance.host}:\n${inspect(e)}`, @@ -172,7 +172,7 @@ async function fetchNodeinfo(instance: Instance): Promise { throw new Error(inspect(e)); }); - logger.succ(`Successfuly fetched nodeinfo of ${instance.host}`); + logger.info(`Successfuly fetched nodeinfo of ${instance.host}`); return info as NodeInfo; } catch (e) { diff --git a/packages/backend/src/services/logger.ts b/packages/backend/src/services/logger.ts index aec4542b82..640cc41452 100644 --- a/packages/backend/src/services/logger.ts +++ b/packages/backend/src/services/logger.ts @@ -11,7 +11,7 @@ type Domain = { color?: string; }; -type Level = "error" | "success" | "warning" | "debug" | "info"; +type Level = "error" | "warning" | "debug" | "info" | "trace"; export default class Logger { private domain: Domain; @@ -47,6 +47,23 @@ export default class Logger { return logger; } + private showThisLog(logLevel: Level, configLevel: string) { + switch (configLevel) { + case "error": + return ["error"].includes(logLevel); + case "warning": + return ["error", "warning"].includes(logLevel); + case "info": + return ["error", "warning", "info"].includes(logLevel); + case "debug": + return ["error", "warning", "info", "debug"].includes(logLevel); + case "trace": + return true; + default: + return ["error", "warning", "info"].includes(logLevel); + } + } + private log( level: Level, message: string, @@ -56,12 +73,13 @@ export default class Logger { store = true, ): void { if ( - !(typeof config.logLevel === "undefined") && - !config.logLevel.includes(level) + (config.maxLogLevel != null && + !this.showThisLog(level, config.maxLogLevel)) || + (config.logLevel != null && !config.logLevel.includes(level)) ) return; if (!this.store) store = false; - if (level === "debug") store = false; + if (level === "debug" || level === "trace") store = false; if (this.parentLogger) { this.parentLogger.log( @@ -84,14 +102,12 @@ export default class Logger { : chalk.red("ERR ") : level === "warning" ? chalk.yellow("WARN") - : level === "success" - ? important - ? chalk.bgGreen.white("DONE") - : chalk.green("DONE") + : level === "info" + ? chalk.green("INFO") : level === "debug" - ? chalk.gray("VERB") - : level === "info" - ? chalk.blue("INFO") + ? chalk.blue("DEBUG") + : level === "trace" + ? chalk.gray("TRACE") : null; const domains = [this.domain] .concat(subDomains) @@ -105,11 +121,11 @@ export default class Logger { ? chalk.red(message) : level === "warning" ? chalk.yellow(message) - : level === "success" + : level === "info" ? chalk.green(message) : level === "debug" - ? chalk.gray(message) - : level === "info" + ? chalk.blue(message) + : level === "trace" ? message : null; @@ -129,11 +145,11 @@ export default class Logger { ? this.syslogClient.error : level === "warning" ? this.syslogClient.warning - : level === "success" + : level === "debug" ? this.syslogClient.info - : level === "debug" + : level === "info" ? this.syslogClient.info - : level === "info" + : level === "trace" ? this.syslogClient.info : (null as never); @@ -144,7 +160,7 @@ export default class Logger { } } - // Used when the process can't continue (fatal error) + // Only used when the process can't continue (fatal error) public error( x: string | Error, data?: Record | null, @@ -175,16 +191,16 @@ export default class Logger { this.log("warning", message, data, important); } - // Used when something is successful - public succ( + // Other generic logs + public info( message: string, data?: Record | null, important = false, ): void { - this.log("success", message, data, important); + this.log("info", message, data, important); } - // Used for debugging (information necessary for developers but unnecessary for users) + // Only used for debugging (information necessary for developers but unnecessary for users) public debug( message: string, data?: Record | null, @@ -200,12 +216,12 @@ export default class Logger { } } - // Other generic logs - public info( + // Extremely verbose logs for debugging (e.g., SQL Query) + public trace( message: string, data?: Record | null, important = false, ): void { - this.log("info", message, data, important); + this.log("trace", message, data, important); } }