8000 feat(profiling): attach sdk info to chunks (#13145) · benjick/sentry-javascript@98160a5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 98160a5

Browse files
authored
feat(profiling): attach sdk info to chunks (getsentry#13145)
Attach SDK info to individual profile chunks
1 parent 21b0dae commit 98160a5

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

packages/profiling-node/src/integration.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* eslint-disable max-lines */
2+
13
import {
24
defineIntegration,
35
getCurrentScope,
@@ -231,11 +233,17 @@ class ContinuousProfiler {
231233
}
232234

233235
DEBUG_BUILD && logger.log(`[Profiling] Profile chunk ${this._chunkData.id} sent to Sentry.`);
234-
const chunk = createProfilingChunkEvent(this._client, this._client.getOptions(), profile, {
235-
chunk_id: this._chunkData.id,
236-
trace_id: this._chunkData.startTraceID,
237-
profiler_id: this._profilerId,
238-
});
236+
const chunk = createProfilingChunkEvent(
237+
this._client,
238+
this._client.getOptions(),
239+
profile,
240+
this._client.getSdkMetadata()?.sdk,
241+
{
242+
chunk_id: this._chunkData.id,
243+
trace_id: this._chunkData.startTraceID,
244+
profiler_id: this._profilerId,
245+
},
246+
);
239247

240248
if (!chunk) {
241249
DEBUG_BUILD && logger.log(`[Profiling] Failed to create profile chunk for: ${this._chunkData.id}`);

packages/profiling-node/src/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,14 @@ function createProfileChunkPayload(
194194
trace_id,
195195
profiler_id,
196196
chunk_id,
197+
sdk,
197198
}: {
198199
release: string;
199200
environment: string;
200201
trace_id: string | undefined;
201202
chunk_id: string;
202203
profiler_id: string;
204+
sdk: SdkInfo | undefined;
203205
},
204206
): ProfileChunk {
205207
// Log a warning if the profile has an invalid traceId (should be uuidv4).
@@ -213,6 +215,10 @@ function createProfileChunkPayload(
213215

214216
const profile: ProfileChunk = {
215217
chunk_id: chunk_id,
218+
client_sdk: {
219+
name: sdk?.name ?? 'sentry.javascript.node',
220+
version: sdk?.version ?? '0.0.0',
221+
},
216222
profiler_id: profiler_id,
217223
platform: 'node',
218224
version: CONTINUOUS_FORMAT_VERSION,
@@ -235,6 +241,7 @@ export function createProfilingChunkEvent(
235241
client: Client,
236242
options: { release?: string; environment?: string },
237243
profile: RawChunkCpuProfile,
244+
sdk: SdkInfo | undefined,
238245
identifiers: { trace_id: string | undefined; chunk_id: string; profiler_id: string },
239246
): ProfileChunk | null {
240247
if (!isValidProfileChunk(profile)) {
@@ -247,6 +254,7 @@ export function createProfilingChunkEvent(
247254
trace_id: identifiers.trace_id ?? '',
248255
chunk_id: identifiers.chunk_id,
249256
profiler_id: identifiers.profiler_id,
257+
sdk,
250258
});
251259
}
252260

packages/profiling-node/test/spanProfileUtils.test.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as Sentry from '@sentry/node';
22

33
import { getMainCarrier } from '@sentry/core';
44
import type { NodeClientOptions } from '@sentry/node/build/types/types';
5-
import type { Transport } from '@sentry/types';
5+
import type { ProfileChunk, Transport } from '@sentry/types';
66
import { GLOBAL_OBJ, createEnvelope, logger } from '@sentry/utils';
77
import { CpuProfilerBindings } from '../src/cpu_profiler';
88
import { type ProfilingIntegration, _nodeProfilingIntegration } from '../src/integration';
@@ -402,6 +402,50 @@ describe('continuous profiling', () => {
402402
delete getMainCarrier().__SENTRY__;
403403
});
404404

405+
it('attaches sdk metadata to chunks', () => {
406+
// @ts-expect-error we just mock the return type and ignore the signature
407+
jest.spyOn(CpuProfilerBindings, 'stopProfiling').mockImplementation(() => {
408+
return {
409+
samples: [
410+
{
411+
stack_id: 0,
412+
thread_id: '0',
413+
elapsed_since_start_ns: '10',
414+
},
415+
{
416+
stack_id: 0,
417+
thread_id: '0',
418+
elapsed_since_start_ns: '10',
419+
},
420+
],
421+
measurements: {},
422+
stacks: [[0]],
423+
frames: [],
424+
resources: [],
425+
profiler_logging_mode: 'lazy',
426+
};
427+
});
428+
429+
const [client, transport] = makeContinuousProfilingClient();
430+
Sentry.setCurrentClient(client);
431+
client.init();
432+
433+
const transportSpy = jest.spyOn(transport, 'send').mockReturnValue(Promise.resolve({}));
434+
435+
const integration = client.getIntegrationByName<ProfilingIntegration>('ProfilingIntegration');
436+
if (!integration) {
437+
throw new Error('Profiling integration not found');
438+
}
439+
integration._profiler.start();
440+
jest.advanceTimersByTime(1000);
441+
integration._profiler.stop();
442+
jest.advanceTimersByTime(1000);
443+
444+
const profile = transportSpy.mock.calls?.[0]?.[0]?.[1]?.[0]?.[1] as ProfileChunk;
445+
expect(profile.client_sdk.name).toBe('sentry.javascript.node');
446+
expect(profile.client_sdk.version).toEqual(expect.stringMatching(/\d+\.\d+\.\d+/));
447+
});
448+
405449
it('initializes the continuous profiler and binds the sentry client', () => {
406450
const startProfilingSpy = jest.spyOn(CpuProfilerBindings, 'startProfiling');
407451

packages/types/src/profiling.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,8 @@ export interface Profile extends BaseProfile<ThreadCpuProfile> {
126126
export interface ProfileChunk extends BaseProfile<ContinuousThreadCpuProfile> {
127127
chunk_id: string;
128128
profiler_id: string;
129+
client_sdk: {
130+
name: string;
131+
version: string;
132+
};
129133
}

0 commit comments

Comments
 (0)
0