Skip to content

Commit

Permalink
feat: add queryLabel option for logging (#14787)
Browse files Browse the repository at this point in the history
* feat: accept queryLabel query option for logging.

* Update test/integration/sequelize/query.test.js

Co-authored-by: Rik Smale <13023439+WikiRik@users.noreply.github.com>

* Mention queryLabel in constructor docstring.

* Drop serial comma

Co-authored-by: Rik Smale <13023439+WikiRik@users.noreply.github.com>

* Fix typo

Co-authored-by: Rik Smale <13023439+WikiRik@users.noreply.github.com>

Co-authored-by: Rik Smale <13023439+WikiRik@users.noreply.github.com>
  • Loading branch information
sandinmyjoints and WikiRik committed Jul 22, 2022
1 parent ec26c44 commit d6854c7
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/dialects/abstract/query.d.ts
Expand Up @@ -22,6 +22,7 @@ export interface AbstractQueryOptions {
* A function that gets executed while running the query to log the sql.
*/
logging?: boolean | ((sql: string, timing?: number) => void);
queryLabel?: string;

include: boolean;
includeNames: unknown[];
Expand Down
7 changes: 4 additions & 3 deletions src/dialects/abstract/query.js
Expand Up @@ -290,14 +290,15 @@ export class AbstractQuery {
}

const fmt = `(${connection.uuid || 'default'}): ${sql}${logParameter}`;
const msg = `Executing ${fmt}`;
const queryLabel = options.queryLabel ? `${options.queryLabel}\n` : '';
const msg = `${queryLabel}Executing ${fmt}`;
debugContext(msg);
if (!benchmark) {
this.sequelize.log(`Executing ${fmt}`, options);
this.sequelize.log(`${queryLabel}Executing ${fmt}`, options);
}

return () => {
const afterMsg = `Executed ${fmt}`;
const afterMsg = `${queryLabel}Executed ${fmt}`;
debugContext(afterMsg);
if (benchmark) {
this.sequelize.log(afterMsg, Date.now() - startTime, options);
Expand Down
5 changes: 3 additions & 2 deletions src/dialects/db2/query.js
Expand Up @@ -35,11 +35,12 @@ export class Db2Query extends AbstractQuery {

this.sql = sql;
const benchmark = this.sequelize.options.benchmark || this.options.benchmark;
const queryLabel = this.options.queryLabel ? `${this.options.queryLabel}\n` : '';
let queryBegin;
if (benchmark) {
queryBegin = Date.now();
} else {
this.sequelize.log(`Executing (${this.connection.uuid || 'default'}): ${this.sql}`, this.options);
this.sequelize.log(`${queryLabel}Executing (${this.connection.uuid || 'default'}): ${this.sql}`, this.options);
}

const errStack = new Error().stack;
Expand Down Expand Up @@ -126,7 +127,7 @@ export class Db2Query extends AbstractQuery {
}

if (benchmark) {
this.sequelize.log(`Executed (${this.connection.uuid || 'default'}): ${newSql} ${parameters ? util.inspect(parameters, { compact: true, breakLength: Infinity }) : ''}`, Date.now() - queryBegin, this.options);
this.sequelize.log(`${queryLabel}Executed (${this.connection.uuid || 'default'}): ${newSql} ${parameters ? util.inspect(parameters, { compact: true, breakLength: Infinity }) : ''}`, Date.now() - queryBegin, this.options);
}

if (err && err.message) {
Expand Down
1 change: 1 addition & 0 deletions src/sequelize.js
Expand Up @@ -159,6 +159,7 @@ export class Sequelize {
* @param {boolean} [options.standardConformingStrings=true] The PostgreSQL `standard_conforming_strings` session parameter. Set to `false` to not set the option. WARNING: Setting this to false may expose vulnerabilities and is not recommended!
* @param {Function} [options.logging=console.log] A function that gets executed every time Sequelize would log something. Function may receive multiple parameters but only first one is printed by `console.log`. To print all values use `(...msg) => console.log(msg)`
* @param {boolean} [options.benchmark=false] Pass query execution time in milliseconds as second argument to logging function (options.logging).
* @param {string} [options.queryLabel] A label to annotate queries in log output.
* @param {boolean} [options.omitNull=false] A flag that defines if null values should be passed as values to CREATE/UPDATE SQL queries or not.
* @param {boolean} [options.native=false] A flag that defines if native library shall be used or not. Currently only has an effect for postgres
* @param {boolean} [options.replication=false] Use read / write replication. To enable replication, pass an object, with two properties, read and write. Write should be an object (a single server for handling writes), and read an array of object (several servers to handle reads). Each read/write server can have the following properties: `host`, `port`, `username`, `password`, `database`. Connection strings can be used instead of objects.
Expand Down
40 changes: 40 additions & 0 deletions test/integration/sequelize/query.test.js
Expand Up @@ -130,6 +130,46 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => {
expect(typeof logger.args[0][1] === 'number').to.be.true;
});

it('executes a query with queryLabel option and custom logger', async () => {
const logger = sinon.spy();
const sequelize = Support.createSequelizeInstance({
logging: logger,
});

await sequelize.query(`select 1${dialect === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, {
queryLabel: 'tricky select',
});
expect(logger.calledOnce).to.be.true;
expect(logger.args[0][0]).to.be.match(/^tricky select[\n]Executing \((\d*|default)\): select 1/);
});

it('executes a query with empty string, queryLabel option and custom logger', async () => {
const logger = sinon.spy();
const sequelize = Support.createSequelizeInstance({
logging: logger,
});

await sequelize.query(`select 1${dialect === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, {
queryLabel: '',
});
expect(logger.calledOnce).to.be.true;
expect(logger.args[0][0]).to.be.match(/^Executing \((\d*|default)\): select 1/);
});

it('executes a query with benchmarking option, queryLabel option and custom logger', async () => {
const logger = sinon.spy();
const sequelize = Support.createSequelizeInstance({
logging: logger,
benchmark: true,
});

await sequelize.query(`select 1${dialect === 'ibmi' ? ' FROM SYSIBM.SYSDUMMY1' : ''};`, {
queryLabel: 'tricky select',
});
expect(logger.calledOnce).to.be.true;
expect(logger.args[0][0]).to.be.match(/^tricky select[\n]Executed \((\d*|default)\): select 1/);
});

describe('with logQueryParameters', () => {
beforeEach(async function () {
this.sequelize = Support.createSequelizeInstance({
Expand Down

0 comments on commit d6854c7

Please sign in to comment.