Skip to content

Commit 6af1022

Browse files
feat(opentelemetry-plugin-pg): omit pg.values by default (#174)
* refactor(opentelemetry-plugin-pg): fix eslint warnings * refactor(opentelemetry-plugin-pg): do not intersect types all the time * refactor(opentelemetry-plugin-pg): rename interface to reduce confusion * refactor(opentelemetry-plugin-pg): clarify method signatures * feat(opentelemetry-plugin-pg): do not track values by default
1 parent 711f2ce commit 6af1022

File tree

6 files changed

+215
-50
lines changed

6 files changed

+215
-50
lines changed

plugins/node/opentelemetry-plugin-pg/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ const provider = new NodeTracerProvider({
6565

6666
See [examples/postgres](https://github.com/open-telemetry/opentelemetry-js/tree/master/examples/postgres) for a short example.
6767

68+
### PostgreSQL Plugin Options
69+
70+
PostgreSQL plugin has few options available to choose from. You can set the following:
71+
72+
| Options | Type | Description |
73+
| ------- | ---- | ----------- |
74+
| [`enhancedDatabaseReporting`](https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-api/src/trace/instrumentation/Plugin.ts#L90) | `boolean` | If true, additional information about query parameters and results will be attached (as `attributes`) to spans representing database operations |
75+
6876
## Supported Versions
6977

7078
- [pg](https://npmjs.com/package/pg): `7.x`

plugins/node/opentelemetry-plugin-pg/src/pg.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@ import * as pgTypes from 'pg';
2020
import * as shimmer from 'shimmer';
2121
import {
2222
PgClientExtended,
23-
PgPluginQueryConfig,
23+
NormalizedQueryConfig,
2424
PostgresCallback,
2525
} from './types';
2626
import * as utils from './utils';
2727
import { VERSION } from './version';
2828

2929
export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
30-
protected _config: {};
31-
3230
static readonly COMPONENT = 'pg';
3331
static readonly DB_TYPE = 'sql';
3432

@@ -62,25 +60,32 @@ export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
6260
plugin._logger.debug(
6361
`Patching ${PostgresPlugin.COMPONENT}.Client.prototype.query`
6462
);
65-
return function query(
66-
this: pgTypes.Client & PgClientExtended,
67-
...args: unknown[]
68-
) {
63+
return function query(this: PgClientExtended, ...args: unknown[]) {
6964
let span: Span;
7065

7166
// Handle different client.query(...) signatures
7267
if (typeof args[0] === 'string') {
68+
const query = args[0];
7369
if (args.length > 1 && args[1] instanceof Array) {
70+
const params = args[1];
7471
span = utils.handleParameterizedQuery.call(
7572
this,
7673
plugin._tracer,
77-
...args
74+
plugin._config,
75+
query,
76+
params
7877
);
7978
} else {
80-
span = utils.handleTextQuery.call(this, plugin._tracer, ...args);
79+
span = utils.handleTextQuery.call(this, plugin._tracer, query);
8180
}
8281
} else if (typeof args[0] === 'object') {
83-
span = utils.handleConfigQuery.call(this, plugin._tracer, ...args);
82+
const queryConfig = args[0] as NormalizedQueryConfig;
83+
span = utils.handleConfigQuery.call(
84+
this,
85+
plugin._tracer,
86+
plugin._config,
87+
queryConfig
88+
);
8489
} else {
8590
return utils.handleInvalidQuery.call(
8691
this,
@@ -106,12 +111,12 @@ export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
106111
);
107112
}
108113
} else if (
109-
typeof (args[0] as PgPluginQueryConfig).callback === 'function'
114+
typeof (args[0] as NormalizedQueryConfig).callback === 'function'
110115
) {
111116
// Patch ConfigQuery callback
112117
let callback = utils.patchCallback(
113118
span,
114-
(args[0] as PgPluginQueryConfig).callback!
119+
(args[0] as NormalizedQueryConfig).callback!
115120
);
116121
// If a parent span existed, bind the callback
117122
if (parentSpan) {
@@ -132,7 +137,7 @@ export class PostgresPlugin extends BasePlugin<typeof pgTypes> {
132137
return result
133138
.then((result: unknown) => {
134139
// Return a pass-along promise which ends the span and then goes to user's orig resolvers
135-
return new Promise((resolve, _) => {
140+
return new Promise(resolve => {
136141
span.setStatus({ code: CanonicalCode.OK });
137142
span.end();
138143
resolve(result);

plugins/node/opentelemetry-plugin-pg/src/types.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ export interface PgClientConnectionParams {
2727
user: string;
2828
}
2929

30-
export interface PgClientExtended {
30+
export interface PgClientExtended extends pgTypes.Client {
3131
connectionParameters: PgClientConnectionParams;
3232
}
3333

34-
export interface PgPluginQueryConfig extends pgTypes.QueryConfig {
34+
// Interface name based on original driver implementation
35+
// https://github.com/brianc/node-postgres/blob/2ef55503738eb2cbb6326744381a92c0bc0439ab/packages/pg/lib/utils.js#L157
36+
export interface NormalizedQueryConfig extends pgTypes.QueryConfig {
3537
callback?: PostgresCallback;
3638
}

plugins/node/opentelemetry-plugin-pg/src/utils.ts

+36-31
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { Span, CanonicalCode, Tracer, SpanKind } from '@opentelemetry/api';
17+
import {
18+
Span,
19+
CanonicalCode,
20+
Tracer,
21+
SpanKind,
22+
PluginConfig,
23+
} from '@opentelemetry/api';
1824
import { AttributeNames } from './enums';
1925
import {
2026
PgClientExtended,
21-
PgPluginQueryConfig,
27+
NormalizedQueryConfig,
2228
PostgresCallback,
2329
PgClientConnectionParams,
2430
} from './types';
@@ -44,11 +50,7 @@ function getJDBCString(params: PgClientConnectionParams) {
4450
}
4551

4652
// Private helper function to start a span
47-
function pgStartSpan(
48-
tracer: Tracer,
49-
client: pgTypes.Client & PgClientExtended,
50-
name: string
51-
) {
53+
function pgStartSpan(tracer: Tracer, client: PgClientExtended, name: string) {
5254
const jdbcString = getJDBCString(client.connectionParameters);
5355
return tracer.startSpan(name, {
5456
kind: SpanKind.CLIENT,
@@ -66,69 +68,72 @@ function pgStartSpan(
6668

6769
// Queries where args[0] is a QueryConfig
6870
export function handleConfigQuery(
69-
this: pgTypes.Client & PgClientExtended,
71+
this: PgClientExtended,
7072
tracer: Tracer,
71-
...args: unknown[]
73+
pluginConfig: PluginConfig,
74+
queryConfig: NormalizedQueryConfig
7275
) {
73-
const argsConfig = args[0] as PgPluginQueryConfig;
74-
7576
// Set child span name
76-
const queryCommand = getCommandFromText(argsConfig.name || argsConfig.text);
77+
const queryCommand = getCommandFromText(queryConfig.name || queryConfig.text);
7778
const name = PostgresPlugin.BASE_SPAN_NAME + ':' + queryCommand;
7879
const span = pgStartSpan(tracer, this, name);
7980

8081
// Set attributes
81-
if (argsConfig.text) {
82-
span.setAttribute(AttributeNames.DB_STATEMENT, argsConfig.text);
82+
if (queryConfig.text) {
83+
span.setAttribute(AttributeNames.DB_STATEMENT, queryConfig.text);
8384
}
84-
85-
if (argsConfig.values instanceof Array) {
85+
if (
86+
pluginConfig.enhancedDatabaseReporting &&
87+
queryConfig.values instanceof Array
88+
) {
8689
span.setAttribute(
8790
AttributeNames.PG_VALUES,
88-
arrayStringifyHelper(argsConfig.values)
91+
arrayStringifyHelper(queryConfig.values)
8992
);
9093
}
9194
// Set plan name attribute, if present
92-
if (argsConfig.name) {
93-
span.setAttribute(AttributeNames.PG_PLAN, argsConfig.name);
95+
if (queryConfig.name) {
96+
span.setAttribute(AttributeNames.PG_PLAN, queryConfig.name);
9497
}
9598

9699
return span;
97100
}
98101

99102
// Queries where args[1] is a 'values' array
100103
export function handleParameterizedQuery(
101-
this: pgTypes.Client & PgClientExtended,
104+
this: PgClientExtended,
102105
tracer: Tracer,
103-
...args: unknown[]
106+
pluginConfig: PluginConfig,
107+
query: string,
108+
values: unknown[]
104109
) {
105110
// Set child span name
106-
const queryCommand = getCommandFromText(args[0] as string);
111+
const queryCommand = getCommandFromText(query);
107112
const name = PostgresPlugin.BASE_SPAN_NAME + ':' + queryCommand;
108113
const span = pgStartSpan(tracer, this, name);
109114

110115
// Set attributes
111-
span.setAttribute(AttributeNames.DB_STATEMENT, args[0]);
112-
if (args[1] instanceof Array) {
113-
span.setAttribute(AttributeNames.PG_VALUES, arrayStringifyHelper(args[1]));
116+
span.setAttribute(AttributeNames.DB_STATEMENT, query);
117+
if (pluginConfig.enhancedDatabaseReporting) {
118+
span.setAttribute(AttributeNames.PG_VALUES, arrayStringifyHelper(values));
114119
}
115120

116121
return span;
117122
}
118123

119124
// Queries where args[0] is a text query and 'values' was not specified
120125
export function handleTextQuery(
121-
this: pgTypes.Client & PgClientExtended,
126+
this: PgClientExtended,
122127
tracer: Tracer,
123-
...args: unknown[]
128+
query: string
124129
) {
125130
// Set child span name
126-
const queryCommand = getCommandFromText(args[0] as string);
131+
const queryCommand = getCommandFromText(query);
127132
const name = PostgresPlugin.BASE_SPAN_NAME + ':' + queryCommand;
128133
const span = pgStartSpan(tracer, this, name);
129134

130135
// Set attributes
131-
span.setAttribute(AttributeNames.DB_STATEMENT, args[0]);
136+
span.setAttribute(AttributeNames.DB_STATEMENT, query);
132137

133138
return span;
134139
}
@@ -138,7 +143,7 @@ export function handleTextQuery(
138143
* Create and immediately end a new span
139144
*/
140145
export function handleInvalidQuery(
141-
this: pgTypes.Client & PgClientExtended,
146+
this: PgClientExtended,
142147
tracer: Tracer,
143148
originalQuery: typeof pgTypes.Client.prototype.query,
144149
...args: unknown[]
@@ -162,7 +167,7 @@ export function patchCallback(
162167
cb: PostgresCallback
163168
): PostgresCallback {
164169
return function patchedCallback(
165-
this: pgTypes.Client & PgClientExtended,
170+
this: PgClientExtended,
166171
err: Error,
167172
res: object
168173
) {

plugins/node/opentelemetry-plugin-pg/test/pg.test.ts

-4
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ describe('[email protected]', () => {
211211
const attributes = {
212212
...DEFAULT_ATTRIBUTES,
213213
[AttributeNames.DB_STATEMENT]: query,
214-
[AttributeNames.PG_VALUES]: '[0]',
215214
};
216215
const events: TimedEvent[] = [];
217216
const span = tracer.startSpan('test span');
@@ -273,7 +272,6 @@ describe('[email protected]', () => {
273272
const attributes = {
274273
...DEFAULT_ATTRIBUTES,
275274
[AttributeNames.DB_STATEMENT]: query,
276-
[AttributeNames.PG_VALUES]: '[0]',
277275
};
278276
const events: TimedEvent[] = [];
279277
const span = tracer.startSpan('test span');
@@ -294,7 +292,6 @@ describe('[email protected]', () => {
294292
const attributes = {
295293
...DEFAULT_ATTRIBUTES,
296294
[AttributeNames.DB_STATEMENT]: query,
297-
[AttributeNames.PG_VALUES]: '[0]',
298295
};
299296
const events: TimedEvent[] = [];
300297
const span = tracer.startSpan('test span');
@@ -320,7 +317,6 @@ describe('[email protected]', () => {
320317
...DEFAULT_ATTRIBUTES,
321318
[AttributeNames.PG_PLAN]: name,
322319
[AttributeNames.DB_STATEMENT]: query,
323-
[AttributeNames.PG_VALUES]: '[0]',
324320
};
325321
const events: TimedEvent[] = [];
326322
const span = tracer.startSpan('test span');

0 commit comments

Comments
 (0)