limit the logging from TypeORM instead of disabling

Viewed 1201

I had set logging: true when createConnection() from TypeORM, which works fine for most of times.

But there is a situation where one of my data field from a specific query/mutation may contains a long string (50000 - 300000 char depends on the input, it could be more). When typeORM try to log the content in VScode terminal, it can crush VScode, I wonder if there is anything that TypeORM can hide such a long string instead of completely disable all the query loggings.

My ideal approach would be something like longstring=== (modification based on the string and text ellipsis) ===> long.... Or just apply a custom logger for specific query if necessary.

So it can still log to indicate the bit of code is running with minimal info.

From the doc, it seems like I can only add additional information instead of modifying. https://github.com/typeorm/typeorm/blob/master/docs/logging.md

=============== Update ==============

Based on the accepted solution, it seems like I did not understand the doc properly. We can custom the logger based on our needs. Since I want to cut off the parameter. So I can do the following.

import { AdvancedConsoleLogger, Logger, LoggerOptions, QueryRunner } from "typeorm";

export class CustomLogger extends AdvancedConsoleLogger implements Logger {
    constructor(options?: LoggerOptions) {
        super(options);
    }
    //override logquery
    logQuery(query: string, paramters?: any[], queryRunner?: QueryRunner) {
        const limit = 100;
        const paramTextEllipsis = paramters?.map((param) => {
            //only cut off string and length longer than 100
            if(typeof param === "string" && param.length > limit){
                return param.substring(0, limit) + "...";
            }
            return param;
        });
        super.logQuery(query, paramTextEllipsis, queryRunner);
    }
};

The result from terminal. Note that the json string originally has more than 100k which can easily crush editor. enter image description here

1 Answers

It is explained under changing default logger on the TypeOrm logging page.

You need to implement your own logger. This is simple as you can subclass one of the standard loggers provided by TypeOrm, check if log query string if it is too long, and call the inherited log method.

For example, to subclass the "advanced-console" logger, which is the default logger TypeOrm uses.

import { Logger, QueryRunner, AdvancedConsoleLogger, LoggerOptions } from "typeorm";

export class MyCustomLogger extends AdvancedConsoleLogger implements Logger {

    constructor(options?: LoggerOptions) {
        super(options);
    }    

    logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) {
        let logText = query;
        if (logText.length > 100)
            // Truncate the log text if it's too long:
            logText = logText.substring(0, 10) + "...";
        super.logQuery(logText, parameters, queryRunner);
    }
}

There are more 4 methods you can override, but you can omit these from your implementation and it will use the inherited methods:

logQueryError(error: string, query: string, parameters?: any[], queryRunner?: QueryRunner)
logQuerySlow(time: number, query: string, parameters?: any[], queryRunner?: QueryRunner)
logSchemaBuild(message: string, queryRunner?: QueryRunner) 
logMigration(message: string, queryRunner?: QueryRunner)
log(level: "log" | "info" | "warn", message: any, queryRunner?: QueryRunner)

Now you have created your custom logger, how to use is is explained under using custom logger.

You need to change the examples on the page slightly to add the logging option(s) you want; logging options are explained under logging options, e.g: (true) or ("All") or (["query", "error"])

import {createConnection} from "typeorm";
import {MyCustomLogger} from "./logger/MyCustomLogger";

createConnection({
    name: "mysql",
    type: "mysql",
    host: "localhost",
    port: 3306,
    username: "test",
    password: "test",
    database: "test",
    logger: new MyCustomLogger(true) // Logging option "true" = enable logging
});

Or when using the ormconfig.json configuration file:

import {createConnection, getConnectionOptions} from "typeorm";
import {MyCustomLogger} from "./logger/MyCustomLogger";

// getConnectionOptions will read options from your ormconfig file
// and return it in connectionOptions object
// then you can simply append additional properties to it
getConnectionOptions().then(connectionOptions => {
    return createConnection(Object.assign(connectionOptions, {
        logger: new MyCustomLogger(connectionOptions.logging) // pass in logging options specified in the ormconfig.json file
    }))
});

If you are using async/await instead of promises, you can rewrite the latter code more clearly:

// getConnectionOptions reads options from your ormconfig file
const options = await getConnectionOptions();
// append MyCustomLogger to the connection options
await createConnection({ ...options, logger: new MyCustomLogger(options.logging) });
Related