Skip to content

Commit 751b463

Browse files
committed
feat(node): Add lru-memoizer instrumentation
1 parent efd7a70 commit 751b463

File tree

8 files changed

+129
-7
lines changed

8 files changed

+129
-7
lines changed

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

+1
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",
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();
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/node/package.json

+1
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

+1
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

+3
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,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { LruMemoizerInstrumentation } from '@opentelemetry/instrumentation-lru-memoizer';
2+
3+
import { defineIntegration } from '@sentry/core';
4+
import type { IntegrationFn } from '@sentry/types';
5+
import { generateInstrumentOnce } from '../../otel/instrument';
6+
7+
const INTEGRATION_NAME = 'LruMemoizer';
8+
9+
export const instrumentLruMemoizer = generateInstrumentOnce(INTEGRATION_NAME, () => new LruMemoizerInstrumentation());
10+
11+
const _lruMemoizerIntegration = (() => {
12+
return {
13+
name: INTEGRATION_NAME,
14+
setupOnce() {
15+
instrumentLruMemoizer();
16+
},
17+
};
18+
}) satisfies IntegrationFn;
19+
20+
/**
21+
* LruMemoizer integration
22+
*
23+
* Propagate traces through LruMemoizer.
24+
*/
25+
export const lruMemoizerIntegration = defineIntegration(_lruMemoizerIntegration);

yarn.lock

+22-7
Original file line numberDiff line numberDiff line change
@@ -7211,6 +7211,13 @@
72117211
"@opentelemetry/instrumentation" "^0.53.0"
72127212
"@opentelemetry/semantic-conventions" "^1.27.0"
72137213

7214+
"@opentelemetry/[email protected]":
7215+
version "0.40.0"
7216+
resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.40.0.tgz#dc60d7fdfd2a0c681cb23e7ed4f314d1506ccdc0"
7217+
integrity sha512-21xRwZsEdMPnROu/QsaOIODmzw59IYpGFmuC4aFWvMj6stA8+Ei1tX67nkarJttlNjoM94um0N4X26AD7ff54A==
7218+
dependencies:
7219+
"@opentelemetry/instrumentation" "^0.53.0"
7220+
72147221
"@opentelemetry/[email protected]":
72157222
version "0.47.0"
72167223
resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.47.0.tgz#f8107d878281433905e717f223fb4c0f10356a7b"
@@ -23303,6 +23310,13 @@ lowercase-keys@^2.0.0:
2330323310
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
2330423311
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
2330523312

23313+
[email protected], lru-cache@^6.0.0:
23314+
version "6.0.0"
23315+
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
23316+
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
23317+
dependencies:
23318+
yallist "^4.0.0"
23319+
2330623320
lru-cache@^10.0.1, lru-cache@^10.2.0:
2330723321
version "10.2.2"
2330823322
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878"
@@ -23315,13 +23329,6 @@ lru-cache@^5.1.1:
2331523329
dependencies:
2331623330
yallist "^3.0.2"
2331723331

23318-
lru-cache@^6.0.0:
23319-
version "6.0.0"
23320-
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
23321-
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
23322-
dependencies:
23323-
yallist "^4.0.0"
23324-
2332523332
lru-cache@^7.10.1, lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1:
2332623333
version "7.14.1"
2332723334
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.14.1.tgz#8da8d2f5f59827edb388e63e459ac23d6d408fea"
@@ -23347,6 +23354,14 @@ lru-cache@^9.0.0:
2334723354
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61"
2334823355
integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==
2334923356

23357+
23358+
version "2.3.0"
23359+
resolved "https://registry.yarnpkg.com/lru-memoizer/-/lru-memoizer-2.3.0.tgz#ef0fbc021bceb666794b145eefac6be49dc47f31"
23360+
integrity sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==
23361+
dependencies:
23362+
lodash.clonedeep "^4.5.0"
23363+
lru-cache "6.0.0"
23364+
2335023365
lunr@^2.3.8:
2335123366
version "2.3.9"
2335223367
resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1"

0 commit comments

Comments
 (0)