Skip to content

Commit 4774399

Browse files
authored
feat(node): Add generic-pool integration (#13465)
Resolves #13308 Implement genericPool OTL instrumentation in `packages/node` - [x] If you've added code that should be tested, please add tests. - [x] Ensure your code lints and the test suite passes (`yarn lint`) & (`yarn test`). --------- Signed-off-by: Kaung Zin Hein <[email protected]>
1 parent ce8579c commit 4774399

File tree

15 files changed

+166
-1
lines changed

15 files changed

+166
-1
lines changed

dev-packages/node-integration-tests/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"cors": "^2.8.5",
4545
"cron": "^3.1.6",
4646
"express": "^4.17.3",
47+
"generic-pool": "^3.9.0",
4748
"graphql": "^16.3.0",
4849
"http-terminator": "^3.2.0",
4950
"ioredis": "^5.4.1",
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const { loggingTransport } = require('@sentry-internal/node-integration-tests');
2+
const Sentry = require('@sentry/node');
3+
4+
Sentry.init({
5+
dsn: 'https://[email protected]/1337',
6+
release: '1.0',
7+
tracesSampleRate: 1.0,
8+
transport: loggingTransport,
9+
});
10+
11+
// Stop the process from exiting before the transaction is sent
12+
setInterval(() => {}, 1000);
13+
14+
const mysql = require('mysql');
15+
const genericPool = require('generic-pool');
16+
17+
const factory = {
18+
create: function () {
19+
return mysql.createConnection({
20+
user: 'root',
21+
password: 'docker',
22+
});
23+
},
24+
destroy: function (client) {
25+
client.end(err => {
26+
if (err) {
27+
// eslint-disable-next-line no-console
28+
console.error('Error while disconnecting MySQL:', err);
29+
}
30+
});
31+
},
32+
};
33+
34+
const opts = {
35+
max: 10,
36+
min: 2,
37+
};
38+
39+
const myPool = genericPool.createPool(factory, opts);
40+
41+
async function run() {
42+
await Sentry.startSpan(
43+
{
44+
op: 'transaction',
45+
name: 'Test Transaction',
46+
},
47+
async () => {
48+
try {
49+
const client1 = await myPool.acquire();
50+
const client2 = await myPool.acquire();
51+
52+
client1.query('SELECT NOW()', function () {
53+
myPool.release(client1);
54+
});
55+
56+
client2.query('SELECT 1 + 1 AS solution', function () {
57+
myPool.release(client2);
58+
});
59+
} catch (err) {
60+
// eslint-disable-next-line no-console
61+
console.error('Error while pooling MySQL:', err);
62+
} finally {
63+
await myPool.drain();
64+
await myPool.clear();
65+
}
66+
},
67+
);
68+
}
69+
70+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
71+
run();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { cleanupChildProcesses, createRunner } from '../../../utils/runner';
2+
3+
describe('genericPool auto instrumentation', () => {
4+
afterAll(() => {
5+
cleanupChildProcesses();
6+
});
7+
8+
test('should auto-instrument `genericPool` package when calling pool.require()', done => {
9+
const EXPECTED_TRANSACTION = {
10+
transaction: 'Test Transaction',
11+
spans: expect.arrayContaining([
12+
expect.objectContaining({
13+
description: expect.stringMatching(/^generic-pool\.ac?quire/),
14+
origin: 'auto.db.otel.generic-pool',
15+
data: {
16+
'sentry.origin': 'auto.db.otel.generic-pool',
17+
},
18+
status: 'ok',
19+
}),
20+
21+
expect.objectContaining({
22+
description: expect.stringMatching(/^generic-pool\.ac?quire/),
23+
origin: 'auto.db.otel.generic-pool',
24+
data: {
25+
'sentry.origin': 'auto.db.otel.generic-pool',
26+
},
27+
status: 'ok',
28+
}),
29+
]),
30+
};
31+
32+
createRunner(__dirname, 'scenario.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done);
33+
});
34+
});

packages/astro/src/index.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export {
4343
fsIntegration,
4444
functionToStringIntegration,
4545
generateInstrumentOnce,
46+
genericPoolIntegration,
4647
getActiveSpan,
4748
getAutoPerformanceIntegrations,
4849
getClient,

packages/aws-serverless/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export {
8787
setupConnectErrorHandler,
8888
fastifyIntegration,
8989
fsIntegration,
90+
genericPoolIntegration,
9091
graphqlIntegration,
9192
mongoIntegration,
9293
mongooseIntegration,

packages/bun/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export {
108108
setupKoaErrorHandler,
109109
connectIntegration,
110110
setupConnectErrorHandler,
111+
genericPoolIntegration,
111112
graphqlIntegration,
112113
mongoIntegration,
113114
mongooseIntegration,

packages/google-cloud-serverless/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export {
8787
connectIntegration,
8888
setupConnectErrorHandler,
8989
fastifyIntegration,
90+
genericPoolIntegration,
9091
graphqlIntegration,
9192
mongoIntegration,
9293
mongooseIntegration,

packages/node/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"@opentelemetry/instrumentation-express": "0.41.1",
7474
"@opentelemetry/instrumentation-fastify": "0.38.0",
7575
"@opentelemetry/instrumentation-fs": "0.14.0",
76+
"@opentelemetry/instrumentation-generic-pool": "0.38.0",
7677
"@opentelemetry/instrumentation-graphql": "0.42.0",
7778
"@opentelemetry/instrumentation-hapi": "0.40.0",
7879
"@opentelemetry/instrumentation-http": "0.52.1",

packages/node/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export { hapiIntegration, setupHapiErrorHandler } from './integrations/tracing/h
2626
export { koaIntegration, setupKoaErrorHandler } from './integrations/tracing/koa';
2727
export { connectIntegration, setupConnectErrorHandler } from './integrations/tracing/connect';
2828
export { spotlightIntegration } from './integrations/spotlight';
29+
export { genericPoolIntegration } from './integrations/tracing/genericPool';
2930

3031
export { SentryContextManager } from './otel/contextManager';
3132
export { generateInstrumentOnce } from './otel/instrument';
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { GenericPoolInstrumentation } from '@opentelemetry/instrumentation-generic-pool';
2+
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, spanToJSON } from '@sentry/core';
3+
import type { IntegrationFn } from '@sentry/types';
4+
import { generateInstrumentOnce } from '../../otel/instrument';
5+
6+
const INTEGRATION_NAME = 'GenericPool';
7+
8+
export const instrumentGenericPool = generateInstrumentOnce(INTEGRATION_NAME, () => new GenericPoolInstrumentation({}));
9+
10+
const _genericPoolIntegration = (() => {
11+
return {
12+
name: INTEGRATION_NAME,
13+
setupOnce() {
14+
instrumentGenericPool();
15+
},
16+
17+
setup(client) {
18+
client.on('spanStart', span => {
19+
const spanJSON = spanToJSON(span);
20+
21+
const spanDescription = spanJSON.description;
22+
23+
// typo in emitted span for version <= 0.38.0 of @opentelemetry/instrumentation-generic-pool
24+
const isGenericPoolSpan =
25+
spanDescription === 'generic-pool.aquire' || spanDescription === 'generic-pool.acquire';
26+
27+
if (isGenericPoolSpan) {
28+
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.generic-pool');
29+
}
30+
});
31+
},
32+
};
33+
}) satisfies IntegrationFn;
34+
35+
/**
36+
* GenericPool integration
37+
*
38+
* Capture tracing data for GenericPool.
39+
*/
40+
export const genericPoolIntegration = defineIntegration(_genericPoolIntegration);

packages/node/src/integrations/tracing/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { instrumentHttp } from '../http';
44
import { connectIntegration, instrumentConnect } from './connect';
55
import { expressIntegration, instrumentExpress } from './express';
66
import { fastifyIntegration, instrumentFastify } from './fastify';
7+
import { genericPoolIntegration, instrumentGenericPool } from './genericPool';
78
import { graphqlIntegration, instrumentGraphql } from './graphql';
89
import { hapiIntegration, instrumentHapi } from './hapi';
910
import { instrumentKoa, koaIntegration } from './koa';
@@ -37,6 +38,7 @@ export function getAutoPerformanceIntegrations(): Integration[] {
3738
hapiIntegration(),
3839
koaIntegration(),
3940
connectIntegration(),
41+
genericPoolIntegration(),
4042
];
4143
}
4244

@@ -61,5 +63,6 @@ export function getOpenTelemetryInstrumentationToPreload(): (((options?: any) =>
6163
instrumentHapi,
6264
instrumentGraphql,
6365
instrumentRedis,
66+
instrumentGenericPool,
6467
];
6568
}

packages/remix/src/index.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export {
4747
flush,
4848
functionToStringIntegration,
4949
generateInstrumentOnce,
50+
genericPoolIntegration,
5051
getActiveSpan,
5152
getAutoPerformanceIntegrations,
5253
getClient,

packages/solidstart/src/server/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export {
3838
flush,
3939
functionToStringIntegration,
4040
generateInstrumentOnce,
41+
genericPoolIntegration,
4142
getActiveSpan,
4243
getAutoPerformanceIntegrations,
4344
getClient,

packages/sveltekit/src/server/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export {
3737
fastifyIntegration,
3838
flush,
3939
functionToStringIntegration,
40+
genericPoolIntegration,
4041
generateInstrumentOnce,
4142
getActiveSpan,
4243
getAutoPerformanceIntegrations,

yarn.lock

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7113,6 +7113,13 @@
71137113
"@opentelemetry/core" "^1.8.0"
71147114
"@opentelemetry/instrumentation" "^0.52.0"
71157115

7116+
"@opentelemetry/[email protected]":
7117+
version "0.38.0"
7118+
resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.38.0.tgz#9ea4d82da23541cda613d553bd405b2cbc0da184"
7119+
integrity sha512-0/ULi6pIco1fEnDPmmAul8ZoudFL7St0hjgBbWZlZPBCSyslDll1J7DFeEbjiRSSyUd+0tu73ae0DOKVKNd7VA==
7120+
dependencies:
7121+
"@opentelemetry/instrumentation" "^0.52.0"
7122+
71167123
"@opentelemetry/[email protected]":
71177124
version "0.42.0"
71187125
resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.42.0.tgz#588a18c39e3b3f655bc09243566172ab0b638d35"
@@ -19084,7 +19091,7 @@ generate-function@^2.3.1:
1908419091
dependencies:
1908519092
is-property "^1.0.2"
1908619093

19087-
19094+
[email protected], generic-pool@^3.9.0:
1908819095
version "3.9.0"
1908919096
resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4"
1909019097
integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==

0 commit comments

Comments
 (0)