Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get informative stack trace in node-pg

I am using node-pg with typescript.

I have a getPool utility from the doc https://node-postgres.com/features/pooling

export const getPool = (config?: PoolConfig) => {
  const pool = new Pool(config);
  pool.on('error', (err, client) => {
    console.error('Unexpected error on idle client', err);
    process.exit(-1);
  });
  return pool;
};

I use it like this in an async/await context

const pool = getPool();
await pool.query('my sql query here...');

When I have an invalid SQL query I get this kind of error:

error: null value in column "foo" violates not-null constraint

  at Parser.parseErrorMessage (node_modules/pg-protocol/src/parser.ts:357:11)
  at Parser.handlePacket (node_modules/pg-protocol/src/parser.ts:186:21)
  at Parser.parse (node_modules/pg-protocol/src/parser.ts:101:30)
  at Socket.<anonymous> (node_modules/pg-protocol/src/index.ts:7:48)

Note: I would understand if it was the pool.on('error')'s callback that stole my stack trace, but the errors are not prefixed with Unexpected error on idle client

Notice in the stack trace there is no line that points to a file in my codebase.

My problem is, I have hundereds of queries in my codebase, and I would like to be able to trace the line that called the failing pool.query(). This would help a lot to find which query triggered the error.

Expected :

error: null value in column "foo" violates not-null constraint

  at ...
  at mycodebase/src/myfile.ts:42
like image 427
Yann Pellegrini Avatar asked Dec 08 '20 14:12

Yann Pellegrini


1 Answers

I use dirty hack (patch Pool.prototype), but it works for me:

const originalPoolQuery = Pool.prototype.query;
Pool.prototype.query = async function query(...args) {
    try {
        return await originalPoolQuery.apply(this, args);
    } catch (e) {
        // All magic is here. new Error will generate new stack, but message will copyid from e
        throw new Error(e)
    }
}

// After hack create pool and good luck
const pool = new Pool({})

await pool.query('SELECT * FROM ...')

Stacktrace in this case will be more informative.

I think that pool.on('error', cb) is not for catching query errors, it for connection errors (i am not sure)

like image 92
MiF Avatar answered Nov 18 '22 08:11

MiF