Skip to content

Commit 9564380

Browse files
feat(instrumentation-pg): add error type to db duration metric (open-telemetry#2476)
Co-authored-by: Marc Pichler <marc.pichler@dynatrace.com>
1 parent 9b43ccb commit 9564380

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ export class PgInstrumentation extends InstrumentationBase<PgInstrumentationConf
326326
instrumentationConfig,
327327
span,
328328
args[args.length - 1] as PostgresCallback, // nb: not type safe.
329+
attributes,
329330
recordDuration
330331
);
331332

@@ -342,6 +343,7 @@ export class PgInstrumentation extends InstrumentationBase<PgInstrumentationConf
342343
plugin.getConfig(),
343344
span,
344345
queryConfig.callback as PostgresCallback, // nb: not type safe.
346+
attributes,
345347
recordDuration
346348
);
347349

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ import {
2323
SpanKind,
2424
diag,
2525
UpDownCounter,
26+
Attributes,
2627
} from '@opentelemetry/api';
2728
import { AttributeNames } from './enums/AttributeNames';
2829
import {
30+
ATTR_ERROR_TYPE,
2931
SEMATTRS_DB_SYSTEM,
3032
SEMATTRS_DB_NAME,
3133
SEMATTRS_DB_CONNECTION_STRING,
@@ -244,6 +246,7 @@ export function patchCallback(
244246
instrumentationConfig: PgInstrumentationConfig,
245247
span: Span,
246248
cb: PostgresCallback,
249+
attributes: Attributes,
247250
recordDuration: { (): void }
248251
): PostgresCallback {
249252
return function patchedCallback(
@@ -252,6 +255,10 @@ export function patchCallback(
252255
res: object
253256
) {
254257
if (err) {
258+
if (Object.prototype.hasOwnProperty.call(err, 'code')) {
259+
attributes[ATTR_ERROR_TYPE] = (err as any)['code'];
260+
}
261+
255262
span.setStatus({
256263
code: SpanStatusCode.ERROR,
257264
message: err.message,

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,5 +1021,52 @@ describe('pg', () => {
10211021
done();
10221022
});
10231023
});
1024+
1025+
it('should generate db.client.operation.duration metric with error attribute', done => {
1026+
client.query('SELECT foo from bar', async (err, ret) => {
1027+
assert.notEqual(err, null);
1028+
const { resourceMetrics, errors } = await metricReader.collect();
1029+
assert.deepEqual(
1030+
errors,
1031+
[],
1032+
'expected no errors from the callback during metric collection'
1033+
);
1034+
1035+
const metrics = resourceMetrics.scopeMetrics[0].metrics;
1036+
assert.strictEqual(
1037+
metrics[0].descriptor.name,
1038+
METRIC_DB_CLIENT_OPERATION_DURATION
1039+
);
1040+
assert.strictEqual(
1041+
metrics[0].descriptor.description,
1042+
'Duration of database client operations.'
1043+
);
1044+
const dataPoint = metrics[0].dataPoints[0];
1045+
assert.strictEqual(
1046+
dataPoint.attributes[SEMATTRS_DB_SYSTEM],
1047+
DBSYSTEMVALUES_POSTGRESQL
1048+
);
1049+
assert.strictEqual(
1050+
dataPoint.attributes[ATTR_DB_OPERATION_NAME],
1051+
'SELECT'
1052+
);
1053+
assert.strictEqual(dataPoint.attributes[ATTR_ERROR_TYPE], '42P01');
1054+
1055+
const v = (dataPoint as DataPoint<Histogram>).value;
1056+
v.min = v.min ? v.min : 0;
1057+
v.max = v.max ? v.max : 0;
1058+
assert.equal(
1059+
v.min > 0,
1060+
true,
1061+
'expect min value for Histogram to be greater than 0'
1062+
);
1063+
assert.equal(
1064+
v.max > 0,
1065+
true,
1066+
'expect max value for Histogram to be greater than 0'
1067+
);
1068+
done();
1069+
});
1070+
});
10241071
});
10251072
});

0 commit comments

Comments
 (0)