[backend] Improve custom TypeORM logger with configurable logging options

Co-authored-by: Laura Hausmann <laura@hausmann.dev>
This commit is contained in:
Ezeani Emmanuel 2024-04-11 11:53:41 +01:00 committed by Laura Hausmann
parent 74a3375886
commit 3fa791d71f
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
3 changed files with 47 additions and 8 deletions

View file

@ -57,6 +57,18 @@ db:
# host: localhost # host: localhost
# rejectUnauthorized: false # rejectUnauthorized: false
# You can enable different different logging levels by setting the value of logging to any of the values listed below
# * 'error' - logs all failed queries and errors
# * 'slow' - logs slow queries
# * 'query' - logs all queries
# * 'schema' - logs the schema build process
# * 'info' - logs internal orm informative messages
# * 'log' - logs internal orm log messages
# You can set multiple log level by specifying them as an array i.e ['log', 'info']
# You can set disable all log levels by specifying an empty array: []
# You can set enable all log levels by specifying the special value: 'all'
logging: ['error', 'slow']
# ┌─────────────────────┐ # ┌─────────────────────┐
#───┘ Redis configuration └───────────────────────────────────── #───┘ Redis configuration └─────────────────────────────────────

View file

@ -1,6 +1,17 @@
/** /**
* *
*/ */
export type TypeORMLoggingOptions =
| "error"
| "slow"
| "query"
| "schema"
| "info"
| "log";
export type TypeORMLoggingConfig = TypeORMLoggingOptions | TypeORMLoggingOptions[] | "all";
export type Source = { export type Source = {
repository_url?: string; repository_url?: string;
feedback_url?: string; feedback_url?: string;
@ -9,6 +20,7 @@ export type Source = {
port: number; port: number;
disableHsts?: boolean; disableHsts?: boolean;
db: { db: {
logging?: TypeORMLoggingConfig;
host: string; host: string;
port: number; port: number;
db: string; db: string;

View file

@ -76,8 +76,22 @@ import { OAuthApp } from "@/models/entities/oauth-app.js";
import { OAuthToken } from "@/models/entities/oauth-token.js"; import { OAuthToken } from "@/models/entities/oauth-token.js";
import { HtmlNoteCacheEntry } from "@/models/entities/html-note-cache-entry.js"; import { HtmlNoteCacheEntry } from "@/models/entities/html-note-cache-entry.js";
import { HtmlUserCacheEntry } from "@/models/entities/html-user-cache-entry.js"; import { HtmlUserCacheEntry } from "@/models/entities/html-user-cache-entry.js";
import { TypeORMLoggingOptions } from "@/config/types.js";
const sqlLogger = dbLogger.createSubLogger("sql", "gray", false); const sqlLogger = dbLogger.createSubLogger("sql", "gray", false);
const isLogEnabled = (level: TypeORMLoggingOptions): boolean => {
const logLevel = config.db.logging;
return Array.isArray(logLevel)
? logLevel.includes(level)
: logLevel === level || logLevel?.trim()?.toLowerCase() === "all";
};
const isLoggingEnabled = () => {
const logLevel = config.db.logging;
return Array.isArray(logLevel)
? logLevel.length > 0
: logLevel != null;
}
class MyCustomLogger implements Logger { class MyCustomLogger implements Logger {
private highlight(sql: string) { private highlight(sql: string) {
return highlight.highlight(sql, { return highlight.highlight(sql, {
@ -87,27 +101,28 @@ class MyCustomLogger implements Logger {
} }
public logQuery(query: string, parameters?: any[]) { public logQuery(query: string, parameters?: any[]) {
sqlLogger.info(this.highlight(query).substring(0, 100)); if (isLogEnabled("query"))
sqlLogger.info(this.highlight(query).substring(0, 100));
} }
public logQueryError(error: string, query: string, parameters?: any[]) { public logQueryError(error: string, query: string, parameters?: any[]) {
sqlLogger.error(this.highlight(query)); if (isLogEnabled("error")) sqlLogger.error(this.highlight(query));
} }
public logQuerySlow(time: number, query: string, parameters?: any[]) { public logQuerySlow(time: number, query: string, parameters?: any[]) {
sqlLogger.warn(this.highlight(query)); if (isLogEnabled("slow")) sqlLogger.warn(this.highlight(query));
} }
public logSchemaBuild(message: string) { public logSchemaBuild(message: string) {
sqlLogger.info(message); if (isLogEnabled("schema")) sqlLogger.info(message);
} }
public log(message: string) { public log(message: string) {
sqlLogger.info(message); if (isLogEnabled("log")) sqlLogger.info(message);
} }
public logMigration(message: string) { public logMigration(message: string) {
sqlLogger.info(message); if (isLogEnabled("info")) sqlLogger.info(message);
} }
} }
@ -182,7 +197,7 @@ export const entities = [
...charts, ...charts,
]; ];
const log = process.env.LOG_SQL === "true"; const log = isLoggingEnabled() || process.env.LOG_SQL === "true";
export const db = new DataSource({ export const db = new DataSource({
type: "postgres", type: "postgres",
@ -213,7 +228,7 @@ export const db = new DataSource({
} }
: false, : false,
logging: log, logging: log,
logger: log ? new MyCustomLogger() : undefined, logger: new MyCustomLogger(),
maxQueryExecutionTime: 300, maxQueryExecutionTime: 300,
entities: entities, entities: entities,
migrations: ["../../migration/*.js"], migrations: ["../../migration/*.js"],