Skip to content

Commit aee1aeb

Browse files
committed
Merge branch 'refs/heads/develop' into sig/nuxt-4
# Conflicts: # yarn.lock
2 parents 8540aa1 + 39c0b1d commit aee1aeb

File tree

15 files changed

+1354
-1330
lines changed

15 files changed

+1354
-1330
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://public@dsn.ingest.sentry.io/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,
Lines changed: 25 additions & 0 deletions
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);

packages/replay-internal/src/coreHandlers/handleGlobalEvent.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import { shouldSampleForBufferEvent } from './util/shouldSampleForBufferEvent';
1414
export function handleGlobalEventListener(replay: ReplayContainer): (event: Event, hint: EventHint) => Event | null {
1515
return Object.assign(
1616
(event: Event, hint: EventHint) => {
17-
// Do nothing if replay has been disabled
18-
if (!replay.isEnabled()) {
17+
// Do nothing if replay has been disabled or paused
18+
if (!replay.isEnabled() || replay.isPaused()) {
1919
return event;
2020
}
2121

packages/replay-internal/test/integration/coreHandlers/handleGlobalEvent.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,4 +397,23 @@ describe('Integration | coreHandlers | handleGlobalEvent', () => {
397397

398398
expect(handleGlobalEventListener(replay)(errorEvent, {})).toEqual(errorEvent);
399399
});
400+
401+
it('does not add replayId if replay is paused', async () => {
402+
const transaction = Transaction();
403+
const error = Error();
404+
405+
replay['_isPaused'] = true;
406+
407+
expect(handleGlobalEventListener(replay)(transaction, {})).toEqual(
408+
expect.not.objectContaining({
409+
// no tags at all here by default
410+
tags: expect.anything(),
411+
}),
412+
);
413+
expect(handleGlobalEventListener(replay)(error, {})).toEqual(
414+
expect.objectContaining({
415+
tags: expect.not.objectContaining({ replayId: expect.anything() }),
416+
}),
417+
);
418+
});
400419
});

packages/types/src/checkin.ts

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { TraceContext } from './context';
22

33
interface CrontabSchedule {
44
type: 'crontab';
5-
// The crontab schedule string, e.g. 0 * * * *.
5+
/** The crontab schedule string, e.g. 0 * * * *. */
66
value: string;
77
}
88

@@ -14,32 +14,37 @@ interface IntervalSchedule {
1414

1515
type MonitorSchedule = CrontabSchedule | IntervalSchedule;
1616

17-
// https://develop.sentry.dev/sdk/check-ins/
1817
export interface SerializedCheckIn {
19-
// Check-In ID (unique and client generated).
18+
/** Check-In ID (unique and client generated). */
2019
check_in_id: string;
21-
// The distinct slug of the monitor.
20+
/** The distinct slug of the monitor. */
2221
monitor_slug: string;
23-
// The status of the check-in.
22+
/** The status of the check-in. */
2423
status: 'in_progress' | 'ok' | 'error';
25-
// The duration of the check-in in seconds. Will only take effect if the status is ok or error.
24+
/** The duration of the check-in in seconds. Will only take effect if the status is ok or error. */
2625
duration?: number;
2726
release?: string;
2827
environment?: string;
2928
monitor_config?: {
3029
schedule: MonitorSchedule;
31-
// The allowed allowed margin of minutes after the expected check-in time that
32-
// the monitor will not be considered missed for.
30+
/**
31+
* The allowed allowed margin of minutes after the expected check-in time that
32+
* the monitor will not be considered missed for.
33+
*/
3334
checkin_margin?: number;
34-
// The allowed allowed duration in minutes that the monitor may be `in_progress`
35-
// for before being considered failed due to timeout.
35+
/**
36+
* The allowed allowed duration in minutes that the monitor may be `in_progress`
37+
* for before being considered failed due to timeout.
38+
*/
3639
max_runtime?: number;
37-
// A tz database string representing the timezone which the monitor's execution schedule is in.
38-
// See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
40+
/**
41+
* A tz database string representing the timezone which the monitor's execution schedule is in.
42+
* See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
43+
*/
3944
timezone?: string;
40-
// How many consecutive failed check-ins it takes to create an issue.
45+
/** How many consecutive failed check-ins it takes to create an issue. */
4146
failure_issue_threshold?: number;
42-
// How many consecutive OK check-ins it takes to resolve an issue.
47+
/** How many consecutive OK check-ins it takes to resolve an issue. */
4348
recovery_threshold?: number;
4449
};
4550
contexts?: {
@@ -48,27 +53,27 @@ export interface SerializedCheckIn {
4853
}
4954

5055
export interface HeartbeatCheckIn {
51-
// The distinct slug of the monitor.
56+
/** The distinct slug of the monitor. */
5257
monitorSlug: SerializedCheckIn['monitor_slug'];
53-
// The status of the check-in.
58+
/** The status of the check-in. */
5459
status: 'ok' | 'error';
5560
}
5661

5762
export interface InProgressCheckIn {
58-
// The distinct slug of the monitor.
63+
/** The distinct slug of the monitor. */
5964
monitorSlug: SerializedCheckIn['monitor_slug'];
60-
// The status of the check-in.
65+
/** The status of the check-in. */
6166
status: 'in_progress';
6267
}
6368

6469
export interface FinishedCheckIn {
65-
// The distinct slug of the monitor.
70+
/** The distinct slug of the monitor. */
6671
monitorSlug: SerializedCheckIn['monitor_slug'];
67-
// The status of the check-in.
72+
/** The status of the check-in. */
6873
status: 'ok' | 'error';
69-
// Check-In ID (unique and client generated).
74+
/** Check-In ID (unique and client generated). */
7075
checkInId: SerializedCheckIn['check_in_id'];
71-
// The duration of the check-in in seconds. Will only take effect if the status is ok or error.
76+
/** The duration of the check-in in seconds. Will only take effect if the status is ok or error. */
7277
duration?: SerializedCheckIn['duration'];
7378
}
7479

@@ -77,18 +82,27 @@ export type CheckIn = HeartbeatCheckIn | InProgressCheckIn | FinishedCheckIn;
7782
type SerializedMonitorConfig = NonNullable<SerializedCheckIn['monitor_config']>;
7883

7984
export interface MonitorConfig {
85+
/**
86+
* The schedule on which the monitor should run. Either a crontab schedule string or an interval.
87+
*/
8088
schedule: MonitorSchedule;
81-
// The allowed allowed margin of minutes after the expected check-in time that
82-
// the monitor will not be considered missed for.
89+
/**
90+
* The allowed allowed margin of minutes after the expected check-in time that
91+
* the monitor will not be considered missed for.
92+
*/
8393
checkinMargin?: SerializedMonitorConfig['checkin_margin'];
84-
// The allowed allowed duration in minutes that the monitor may be `in_progress`
85-
// for before being considered failed due to timeout.
94+
/**
95+
* The allowed allowed duration in minutes that the monitor may be `in_progress`
96+
* for before being considered failed due to timeout.
97+
*/
8698
maxRuntime?: SerializedMonitorConfig['max_runtime'];
87-
// A tz database string representing the timezone which the monitor's execution schedule is in.
88-
// See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
99+
/**
100+
* A tz database string representing the timezone which the monitor's execution schedule is in.
101+
* See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
102+
*/
89103
timezone?: SerializedMonitorConfig['timezone'];
90-
// How many consecutive failed check-ins it takes to create an issue.
104+
/** How many consecutive failed check-ins it takes to create an issue. */
91105
failureIssueThreshold?: SerializedMonitorConfig['failure_issue_threshold'];
92-
// How many consecutive OK check-ins it takes to resolve an issue.
106+
/** How many consecutive OK check-ins it takes to resolve an issue. */
93107
recoveryThreshold?: SerializedMonitorConfig['recovery_threshold'];
94108
}

0 commit comments

Comments
 (0)