Skip to content

Commit 1ab3b04

Browse files
kamilogoreklobsterkatieHazAT
authored
feat: PostgreSQL Tracing Support (#3064)
* feat: node-postgres tracing integration * ref: Span content Co-authored-by: Katie Byers <[email protected]> Co-authored-by: Daniel Griesser <[email protected]>
1 parent a1934b4 commit 1ab3b04

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { Express } from './express';
2+
export { Postgres } from './postgres';
23
export { Mysql } from './mysql';
34
export { Mongo } from './mongo';
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Hub } from '@sentry/hub';
2+
import { EventProcessor, Integration } from '@sentry/types';
3+
import { dynamicRequire, fill, logger } from '@sentry/utils';
4+
5+
interface PgClient {
6+
prototype: {
7+
query: () => void | Promise<unknown>;
8+
};
9+
}
10+
11+
/** Tracing integration for node-postgres package */
12+
export class Postgres implements Integration {
13+
/**
14+
* @inheritDoc
15+
*/
16+
public static id: string = 'Postgres';
17+
18+
/**
19+
* @inheritDoc
20+
*/
21+
public name: string = Postgres.id;
22+
23+
/**
24+
* @inheritDoc
25+
*/
26+
public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
27+
let client: PgClient;
28+
29+
try {
30+
const pgModule = dynamicRequire(module, 'pg') as { Client: PgClient };
31+
client = pgModule.Client;
32+
} catch (e) {
33+
logger.error('Postgres Integration was unable to require `pg` package.');
34+
return;
35+
}
36+
37+
/**
38+
* function (query, callback) => void
39+
* function (query, params, callback) => void
40+
* function (query) => Promise
41+
* function (query, params) => Promise
42+
*/
43+
fill(client.prototype, 'query', function(orig: () => void | Promise<unknown>) {
44+
return function(this: unknown, config: unknown, values: unknown, callback: unknown) {
45+
const scope = getCurrentHub().getScope();
46+
const parentSpan = scope?.getSpan();
47+
const span = parentSpan?.startChild({
48+
description: typeof config === 'string' ? config : (config as { text: string }).text,
49+
op: `db`,
50+
});
51+
52+
if (typeof callback === 'function') {
53+
return orig.call(this, config, values, function(err: Error, result: unknown) {
54+
span?.finish();
55+
callback(err, result);
56+
});
57+
}
58+
59+
if (typeof values === 'function') {
60+
return orig.call(this, config, function(err: Error, result: unknown) {
61+
span?.finish();
62+
values(err, result);
63+
});
64+
}
65+
66+
return (orig.call(this, config, values) as Promise<unknown>).then((res: unknown) => {
67+
span?.finish();
68+
return res;
69+
});
70+
};
71+
});
72+
}
73+
}

0 commit comments

Comments
 (0)