Skip to content

Commit 9d8464b

Browse files
chore(profiling): Move profiling types to types and cache to utils (#8270)
1 parent 50ead24 commit 9d8464b

File tree

8 files changed

+162
-138
lines changed

8 files changed

+162
-138
lines changed
Lines changed: 2 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,4 @@
11
import type { Event } from '@sentry/types';
2+
import { makeFifoCache } from '@sentry/utils';
23

3-
/**
4-
* Creates a cache that evicts keys in fifo order
5-
* @param size {Number}
6-
*/
7-
export function makeProfilingCache<Key extends string, Value extends Event>(
8-
size: number,
9-
): {
10-
get: (key: Key) => Value | undefined;
11-
add: (key: Key, value: Value) => void;
12-
delete: (key: Key) => boolean;
13-
clear: () => void;
14-
size: () => number;
15-
} {
16-
// Maintain a fifo queue of keys, we cannot rely on Object.keys as the browser may not support it.
17-
let evictionOrder: Key[] = [];
18-
let cache: Record<string, Value> = {};
19-
20-
return {
21-
add(key: Key, value: Value) {
22-
while (evictionOrder.length >= size) {
23-
// shift is O(n) but this is small size and only happens if we are
24-
// exceeding the cache size so it should be fine.
25-
const evictCandidate = evictionOrder.shift();
26-
27-
if (evictCandidate !== undefined) {
28-
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
29-
delete cache[evictCandidate];
30-
}
31-
}
32-
33-
// in case we have a collision, delete the old key.
34-
if (cache[key]) {
35-
this.delete(key);
36-
}
37-
38-
evictionOrder.push(key);
39-
cache[key] = value;
40-
},
41-
clear() {
42-
cache = {};
43-
evictionOrder = [];
44-
},
45-
get(key: Key): Value | undefined {
46-
return cache[key];
47-
},
48-
size() {
49-
return evictionOrder.length;
50-
},
51-
// Delete cache key and return true if it existed, false otherwise.
52-
delete(key: Key): boolean {
53-
if (!cache[key]) {
54-
return false;
55-
}
56-
57-
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
58-
delete cache[key];
59-
60-
for (let i = 0; i < evictionOrder.length; i++) {
61-
if (evictionOrder[i] === key) {
62-
evictionOrder.splice(i, 1);
63-
break;
64-
}
65-
}
66-
67-
return true;
68-
},
69-
};
70-
}
71-
72-
export const PROFILING_EVENT_CACHE = makeProfilingCache<string, Event>(20);
4+
export const PROFILING_EVENT_CACHE = makeFifoCache<string, Event>(20);

packages/browser/src/profiling/jsSelfProfiling.ts

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -53,63 +53,3 @@ declare global {
5353
export interface RawThreadCpuProfile extends JSSelfProfile {
5454
profile_id: string;
5555
}
56-
export interface ThreadCpuProfile {
57-
samples: {
58-
stack_id: number;
59-
thread_id: string;
60-
elapsed_since_start_ns: string;
61-
}[];
62-
stacks: number[][];
63-
frames: {
64-
function: string;
65-
file: string | undefined;
66-
line: number | undefined;
67-
column: number | undefined;
68-
}[];
69-
thread_metadata: Record<string, { name?: string; priority?: number }>;
70-
queue_metadata?: Record<string, { label: string }>;
71-
}
72-
73-
export interface SentryProfile {
74-
event_id: string;
75-
version: string;
76-
os: {
77-
name: string;
78-
version: string;
79-
build_number: string;
80-
};
81-
runtime: {
82-
name: string;
83-
version: string;
84-
};
85-
device: {
86-
architecture: string;
87-
is_emulator: boolean;
88-
locale: string;
89-
manufacturer: string;
90-
model: string;
91-
};
92-
timestamp: string;
93-
release: string;
94-
environment: string;
95-
platform: string;
96-
profile: ThreadCpuProfile;
97-
debug_meta?: {
98-
images: {
99-
debug_id: string;
100-
image_addr: string;
101-
code_file: string;
102-
type: string;
103-
image_size: number;
104-
image_vmaddr: string;
105-
}[];
106-
};
107-
transactions: {
108-
name: string;
109-
trace_id: string;
110-
id: string;
111-
active_thread_id: string;
112-
relative_start_ns: string;
113-
relative_end_ns: string;
114-
}[];
115-
}

packages/browser/src/profiling/utils.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,15 @@ import type {
66
EventEnvelope,
77
EventEnvelopeHeaders,
88
EventItem,
9+
Profile as SentryProfile,
910
SdkInfo,
1011
SdkMetadata,
12+
ThreadCpuProfile,
1113
} from '@sentry/types';
1214
import { createEnvelope, dropUndefinedKeys, dsnToString, logger, uuid4 } from '@sentry/utils';
1315

1416
import { WINDOW } from '../helpers';
15-
import type {
16-
JSSelfProfile,
17-
JSSelfProfileStack,
18-
RawThreadCpuProfile,
19-
SentryProfile,
20-
ThreadCpuProfile,
21-
} from './jsSelfProfiling';
17+
import type { JSSelfProfile, JSSelfProfileStack, RawThreadCpuProfile } from './jsSelfProfiling';
2218

2319
const MS_TO_NS = 1e6;
2420
// Use 0 as main thread id which is identical to threadId in node:worker_threads

packages/hub/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"lint:eslint": "eslint . --format stylish",
4141
"lint:prettier": "prettier --check \"{src,test,scripts}/**/**.ts\"",
4242
"test": "jest",
43-
"test:watch": "jest --watch"
43+
"test:watch": "jest --watch",
44+
"yalc:publish": "ts-node ../../scripts/prepack.ts && yalc publish build --push"
4445
},
4546
"volta": {
4647
"extends": "../../package.json"

packages/types/src/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ export type { ExtractedNodeRequestData, HttpHeaderValue, Primitive, WorkerLocati
4949
export type { ClientOptions, Options } from './options';
5050
export type { Package } from './package';
5151
export type { PolymorphicEvent, PolymorphicRequest } from './polymorphics';
52+
export type {
53+
ThreadId,
54+
FrameId,
55+
StackId,
56+
ThreadCpuSample,
57+
ThreadCpuStack,
58+
ThreadCpuFrame,
59+
ThreadCpuProfile,
60+
Profile,
61+
} from './profiling';
5262
export type { ReplayEvent, ReplayRecordingData, ReplayRecordingMode } from './replay';
5363
export type { QueryParams, Request, SanitizedRequestData } from './request';
5464
export type { Runtime } from './runtime';

packages/types/src/profiling.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
export type ThreadId = string;
2+
export type FrameId = number;
3+
export type StackId = number;
4+
5+
export interface ThreadCpuSample {
6+
stack_id: StackId;
7+
thread_id: ThreadId;
8+
elapsed_since_start_ns: string;
9+
}
10+
11+
export type ThreadCpuStack = FrameId[];
12+
13+
export type ThreadCpuFrame = {
14+
function: string;
15+
file?: string;
16+
line?: number;
17+
column?: number;
18+
};
19+
20+
export interface ThreadCpuProfile {
21+
samples: ThreadCpuSample[];
22+
stacks: ThreadCpuStack[];
23+
frames: ThreadCpuFrame[];
24+
thread_metadata: Record<ThreadId, { name?: string; priority?: number }>;
25+
queue_metadata?: Record<string, { label: string }>;
26+
}
27+
28+
export interface Profile {
29+
event_id: string;
30+
version: string;
31+
os: {
32+
name: string;
33+
version: string;
34+
build_number?: string;
35+
};
36+
runtime: {
37+
name: string;
38+
version: string;
39+
};
40+
device: {
41+
architecture: string;
42+
is_emulator: boolean;
43+
locale: string;
44+
manufacturer: string;
45+
model: string;
46+
};
47+
timestamp: string;
48+
release: string;
49+
environment: string;
50+
platform: string;
51+
profile: ThreadCpuProfile;
52+
debug_meta?: {
53+
images: {
54+
debug_id: string;
55+
image_addr: string;
56+
code_file: string;
57+
type: string;
58+
image_size: number;
59+
image_vmaddr: string;
60+
}[];
61+
};
62+
transaction?: {
63+
name: string;
64+
id: string;
65+
trace_id: string;
66+
active_thread_id: string;
67+
};
68+
transactions?: {
69+
name: string;
70+
id: string;
71+
trace_id: string;
72+
active_thread_id: string;
73+
relative_start_ns: string;
74+
relative_end_ns: string;
75+
}[];
76+
}

packages/utils/src/cache.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Creates a cache that evicts keys in fifo order
3+
* @param size {Number}
4+
*/
5+
export function makeFifoCache<Key extends string, Value>(
6+
size: number,
7+
): {
8+
get: (key: Key) => Value | undefined;
9+
add: (key: Key, value: Value) => void;
10+
delete: (key: Key) => boolean;
11+
clear: () => void;
12+
size: () => number;
13+
} {
14+
// Maintain a fifo queue of keys, we cannot rely on Object.keys as the browser may not support it.
15+
let evictionOrder: Key[] = [];
16+
let cache: Record<string, Value> = {};
17+
18+
return {
19+
add(key: Key, value: Value) {
20+
while (evictionOrder.length >= size) {
21+
// shift is O(n) but this is small size and only happens if we are
22+
// exceeding the cache size so it should be fine.
23+
const evictCandidate = evictionOrder.shift();
24+
25+
if (evictCandidate !== undefined) {
26+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
27+
delete cache[evictCandidate];
28+
}
29+
}
30+
31+
// in case we have a collision, delete the old key.
32+
if (cache[key]) {
33+
this.delete(key);
34+
}
35+
36+
evictionOrder.push(key);
37+
cache[key] = value;
38+
},
39+
clear() {
40+
cache = {};
41+
evictionOrder = [];
42+
},
43+
get(key: Key): Value | undefined {
44+
return cache[key];
45+
},
46+
size() {
47+
return evictionOrder.length;
48+
},
49+
// Delete cache key and return true if it existed, false otherwise.
50+
delete(key: Key): boolean {
51+
if (!cache[key]) {
52+
return false;
53+
}
54+
55+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
56+
delete cache[key];
57+
58+
for (let i = 0; i < evictionOrder.length; i++) {
59+
if (evictionOrder[i] === key) {
60+
evictionOrder.splice(i, 1);
61+
break;
62+
}
63+
}
64+
65+
return true;
66+
},
67+
};
68+
}

packages/utils/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ export * from './ratelimit';
2828
export * from './baggage';
2929
export * from './url';
3030
export * from './userIntegrations';
31+
export * from './cache';

0 commit comments

Comments
 (0)