Skip to content

Commit 2343380

Browse files
authored
feat(node): Add lru-memoizer instrumentation (#13796)
Resolves: #13309 Adds integration for `lru-memoizer` using [@opentelemetry/instrumentation-lru-memoizer](https://www.npmjs.com/package/@opentelemetry/instrumentation-lru-memoizer). This instrumentation does not create any spans. It only assigns the span context into memoized callbacks used in `lru-memoizer`'s `load`. Ported a test case from the original implementation and tested manually to validate.
1 parent 5e2bc47 commit 2343380

File tree

12 files changed

+133
-7
lines changed

12 files changed

+133
-7
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"http-terminator": "^3.2.0",
5252
"ioredis": "^5.4.1",
5353
"kafkajs": "2.2.4",
54+
"lru-memoizer": "2.3.0",
5455
"mongodb": "^3.7.3",
5556
"mongodb-memory-server-global": "^7.6.3",
5657
"mongoose": "^5.13.22",
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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 run = async () => {
15+
// Test ported from the OTEL implementation:
16+
// https://github.com/open-telemetry/opentelemetry-js-contrib/blob/0d6ebded313bb75b5a0e7a6422206c922daf3943/plugins/node/instrumentation-lru-memoizer/test/index.test.ts#L28
17+
const memoizer = require('lru-memoizer');
18+
19+
let memoizerLoadCallback;
20+
const memoizedFoo = memoizer({
21+
load: (_param, callback) => {
22+
memoizerLoadCallback = callback;
23+
},
24+
hash: () => 'bar',
25+
});
26+
27+
Sentry.startSpan({ op: 'run' }, async span => {
28+
const outerSpanContext = span.spanContext();
29+
30+
memoizedFoo({ foo: 'bar' }, () => {
31+
const innerContext = Sentry.getActiveSpan().spanContext();
32+
33+
// The span context should be the same as the outer span
34+
// Throwing an error here will cause the test to fail
35+
if (outerSpanContext !== innerContext) {
36+
throw new Error('Outer and inner span context should match');
37+
}
38+
});
39+
40+
span.end();
41+
});
42+
43+
// Invoking the load callback outside the span
44+
memoizerLoadCallback();
45+
};
46+
47+
run();
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { cleanupChildProcesses, createRunner } from '../../../utils/runner';
2+
3+
describe('lru-memoizer', () => {
4+
afterAll(() => {
5+
cleanupChildProcesses();
6+
});
7+
8+
test('keeps outer context inside the memoized inner functions', done => {
9+
createRunner(__dirname, 'scenario.js')
10+
// We expect only one transaction and nothing else.
11+
// A failed test will result in an error event being sent to Sentry.
12+
// Which will fail this suite.
13+
.expect({
14+
transaction: {
15+
transaction: '<unknown>',
16+
contexts: {
17+
trace: expect.objectContaining({
18+
op: 'run',
19+
data: expect.objectContaining({
20+
'sentry.op': 'run',
21+
'sentry.origin': 'manual',
22+
}),
23+
}),
24+
},
25+
},
26+
})
27+
.start(done);
28+
});
29+
});

packages/astro/src/index.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export {
7272
lastEventId,
7373
linkedErrorsIntegration,
7474
localVariablesIntegration,
75+
lruMemoizerIntegration,
7576
makeNodeTransport,
7677
metrics,
7778
modulesIntegration,

packages/aws-serverless/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export {
9191
genericPoolIntegration,
9292
graphqlIntegration,
9393
kafkaIntegration,
94+
lruMemoizerIntegration,
9495
mongoIntegration,
9596
mongooseIntegration,
9697
mysqlIntegration,

packages/bun/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export {
112112
genericPoolIntegration,
113113
graphqlIntegration,
114114
kafkaIntegration,
115+
lruMemoizerIntegration,
115116
mongoIntegration,
116117
mongooseIntegration,
117118
mysqlIntegration,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export {
9191
genericPoolIntegration,
9292
graphqlIntegration,
9393
kafkaIntegration,
94+
lruMemoizerIntegration,
9495
mongoIntegration,
9596
mongooseIntegration,
9697
mysqlIntegration,

packages/node/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"@opentelemetry/instrumentation-ioredis": "0.43.0",
8383
"@opentelemetry/instrumentation-kafkajs": "0.3.0",
8484
"@opentelemetry/instrumentation-koa": "0.43.0",
85+
"@opentelemetry/instrumentation-lru-memoizer": "0.40.0",
8586
"@opentelemetry/instrumentation-mongodb": "0.47.0",
8687
"@opentelemetry/instrumentation-mongoose": "0.42.0",
8788
"@opentelemetry/instrumentation-mysql": "0.41.0",

packages/node/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export { expressIntegration, expressErrorHandler, setupExpressErrorHandler } fro
1515
export { fastifyIntegration, setupFastifyErrorHandler } from './integrations/tracing/fastify';
1616
export { graphqlIntegration } from './integrations/tracing/graphql';
1717
export { kafkaIntegration } from './integrations/tracing/kafka';
18+
export { lruMemoizerIntegration } from './integrations/tracing/lrumemoizer';
1819
export { mongoIntegration } from './integrations/tracing/mongo';
1920
export { mongooseIntegration } from './integrations/tracing/mongoose';
2021
export { mysqlIntegration } from './integrations/tracing/mysql';

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { graphqlIntegration, instrumentGraphql } from './graphql';
1111
import { hapiIntegration, instrumentHapi } from './hapi';
1212
import { instrumentKafka, kafkaIntegration } from './kafka';
1313
import { instrumentKoa, koaIntegration } from './koa';
14+
import { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';
1415
import { instrumentMongo, mongoIntegration } from './mongo';
1516
import { instrumentMongoose, mongooseIntegration } from './mongoose';
1617
import { instrumentMysql, mysqlIntegration } from './mysql';
@@ -45,6 +46,7 @@ export function getAutoPerformanceIntegrations(): Integration[] {
4546
kafkaIntegration(),
4647
dataloaderIntegration(),
4748
amqplibIntegration(),
49+
lruMemoizerIntegration(),
4850
];
4951
}
5052

@@ -61,6 +63,7 @@ export function getOpenTelemetryInstrumentationToPreload(): (((options?: any) =>
6163
instrumentHapi,
6264
instrumentKafka,
6365
instrumentKoa,
66+
instrumentLruMemoizer,
6467
instrumentNest,
6568
instrumentMongo,
6669
instrumentMongoose,

0 commit comments

Comments
 (0)