-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathdeno-runtime-metrics.test.ts
More file actions
136 lines (108 loc) · 4.6 KB
/
deno-runtime-metrics.test.ts
File metadata and controls
136 lines (108 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// <reference lib="deno.ns" />
import type { Envelope } from '@sentry/core';
import { createStackParser, forEachEnvelopeItem, nodeStackLineParser } from '@sentry/core';
import { assertEquals, assertNotEquals, assertStringIncludes } from 'https://deno.land/std@0.212.0/assert/mod.ts';
import {
DenoClient,
denoRuntimeMetricsIntegration,
getCurrentScope,
getDefaultIntegrations,
} from '../build/esm/index.js';
import { makeTestTransport } from './transport.ts';
const DSN = 'https://233a45e5efe34c47a3536797ce15dafa@nothing.here/5650507';
function delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// deno-lint-ignore no-explicit-any
type MetricItem = { name: string; type: string; value: number; unit?: string; attributes?: Record<string, any> };
async function collectMetrics(
integrationOptions: Parameters<typeof denoRuntimeMetricsIntegration>[0] = {},
): Promise<MetricItem[]> {
const envelopes: Envelope[] = [];
// Hold a reference so we can call teardown() to stop the interval before the test ends.
const metricsIntegration = denoRuntimeMetricsIntegration({ collectionIntervalMs: 1000, ...integrationOptions });
const client = new DenoClient({
dsn: DSN,
integrations: [...getDefaultIntegrations({}), metricsIntegration],
stackParser: createStackParser(nodeStackLineParser()),
transport: makeTestTransport(envelope => {
envelopes.push(envelope);
}),
});
client.init();
getCurrentScope().setClient(client);
await delay(2500);
await client.flush(2000);
// Stop the collection interval so Deno's leak detector doesn't flag it.
metricsIntegration.teardown?.();
const items: MetricItem[] = [];
for (const envelope of envelopes) {
forEachEnvelopeItem(envelope, item => {
const [headers, body] = item;
if (headers.type === 'trace_metric') {
// deno-lint-ignore no-explicit-any
items.push(...(body as any).items);
}
});
}
return items;
}
Deno.test('denoRuntimeMetricsIntegration has the correct name', () => {
const integration = denoRuntimeMetricsIntegration();
assertEquals(integration.name, 'DenoRuntimeMetrics');
});
Deno.test('emits default memory metrics with correct shape', async () => {
const items = await collectMetrics();
const names = items.map(i => i.name);
assertEquals(names.includes('deno.runtime.mem.rss'), true);
assertEquals(names.includes('deno.runtime.mem.heap_used'), true);
assertEquals(names.includes('deno.runtime.mem.heap_total'), true);
const rss = items.find(i => i.name === 'deno.runtime.mem.rss');
assertEquals(rss?.type, 'gauge');
assertEquals(rss?.unit, 'byte');
assertEquals(typeof rss?.value, 'number');
});
Deno.test('emits uptime counter', async () => {
const items = await collectMetrics();
const uptime = items.find(i => i.name === 'deno.runtime.process.uptime');
assertNotEquals(uptime, undefined);
assertEquals(uptime?.type, 'counter');
assertEquals(uptime?.unit, 'second');
});
Deno.test('does not emit mem.external by default', async () => {
const items = await collectMetrics();
const names = items.map(i => i.name);
assertEquals(names.includes('deno.runtime.mem.external'), false);
});
Deno.test('emits mem.external when opted in', async () => {
const items = await collectMetrics({ collect: { memExternal: true } });
const external = items.find(i => i.name === 'deno.runtime.mem.external');
assertNotEquals(external, undefined);
assertEquals(external?.type, 'gauge');
assertEquals(external?.unit, 'byte');
});
Deno.test('respects opt-out: skips uptime when disabled', async () => {
const items = await collectMetrics({ collect: { uptime: false } });
const names = items.map(i => i.name);
assertEquals(names.includes('deno.runtime.mem.rss'), true);
assertEquals(names.includes('deno.runtime.process.uptime'), false);
});
Deno.test('attaches correct sentry.origin attribute', async () => {
const items = await collectMetrics();
const rss = items.find(i => i.name === 'deno.runtime.mem.rss');
// Attributes in the serialized envelope are { type, value } objects.
assertEquals(rss?.attributes?.['sentry.origin']?.value, 'auto.deno.runtime_metrics');
});
Deno.test('warns and clamps collectionIntervalMs below 1000ms', () => {
const warnings: string[] = [];
const originalWarn = console.warn;
console.warn = (msg: string) => warnings.push(msg);
try {
denoRuntimeMetricsIntegration({ collectionIntervalMs: 100 });
} finally {
console.warn = originalWarn;
}
assertEquals(warnings.length, 1);
assertStringIncludes(warnings[0]!, 'collectionIntervalMs');
assertStringIncludes(warnings[0]!, '1000');
});