-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathdenoRuntimeMetrics.ts
More file actions
113 lines (100 loc) · 3.25 KB
/
denoRuntimeMetrics.ts
File metadata and controls
113 lines (100 loc) · 3.25 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
import { _INTERNAL_safeDateNow, _INTERNAL_safeUnref, defineIntegration, metrics } from '@sentry/core';
const INTEGRATION_NAME = 'DenoRuntimeMetrics';
const DEFAULT_INTERVAL_MS = 30_000;
export interface DenoRuntimeMetricsOptions {
/**
* Which metrics to collect.
*
* Default on (4 metrics):
* - `memRss` — Resident Set Size (actual memory footprint)
* - `memHeapUsed` — V8 heap currently in use
* - `memHeapTotal` — total V8 heap allocated
* - `uptime` — process uptime (detect restarts/crashes)
*
* Default off (opt-in):
* - `memExternal` — external memory (JS objects outside the V8 isolate)
*
* Note: CPU utilization and event loop metrics are not available in Deno.
*/
collect?: {
memRss?: boolean;
memHeapUsed?: boolean;
memHeapTotal?: boolean;
memExternal?: boolean;
uptime?: boolean;
};
/**
* How often to collect metrics, in milliseconds.
* @default 30000
*/
collectionIntervalMs?: number;
}
/**
* Automatically collects Deno runtime metrics and emits them to Sentry.
*
* @example
* ```ts
* Sentry.init({
* integrations: [
* Sentry.denoRuntimeMetricsIntegration(),
* ],
* });
* ```
*/
export const denoRuntimeMetricsIntegration = defineIntegration((options: DenoRuntimeMetricsOptions = {}) => {
const collectionIntervalMs = options.collectionIntervalMs ?? DEFAULT_INTERVAL_MS;
const collect = {
// Default on
memRss: true,
memHeapUsed: true,
memHeapTotal: true,
uptime: true,
// Default off
memExternal: false,
...options.collect,
};
let intervalId: ReturnType<typeof setInterval> | undefined;
let prevFlushTime: number = 0;
const METRIC_ATTRIBUTES_BYTE = { unit: 'byte', attributes: { 'sentry.origin': 'auto.deno.runtime_metrics' } };
const METRIC_ATTRIBUTES_SECOND = { unit: 'second', attributes: { 'sentry.origin': 'auto.deno.runtime_metrics' } };
function collectMetrics(): void {
const now = _INTERNAL_safeDateNow();
const elapsed = now - prevFlushTime;
if (collect.memRss || collect.memHeapUsed || collect.memHeapTotal || collect.memExternal) {
const mem = Deno.memoryUsage();
if (collect.memRss) {
metrics.gauge('deno.runtime.mem.rss', mem.rss, METRIC_ATTRIBUTES_BYTE);
}
if (collect.memHeapUsed) {
metrics.gauge('deno.runtime.mem.heap_used', mem.heapUsed, METRIC_ATTRIBUTES_BYTE);
}
if (collect.memHeapTotal) {
metrics.gauge('deno.runtime.mem.heap_total', mem.heapTotal, METRIC_ATTRIBUTES_BYTE);
}
if (collect.memExternal) {
metrics.gauge('deno.runtime.mem.external', mem.external, METRIC_ATTRIBUTES_BYTE);
}
}
if (collect.uptime && elapsed > 0) {
metrics.count('deno.runtime.process.uptime', elapsed / 1000, METRIC_ATTRIBUTES_SECOND);
}
prevFlushTime = now;
}
return {
name: INTEGRATION_NAME,
setup(): void {
prevFlushTime = _INTERNAL_safeDateNow();
// Guard against double setup (e.g. re-init).
if (intervalId) {
clearInterval(intervalId);
}
intervalId = _INTERNAL_safeUnref(setInterval(collectMetrics, collectionIntervalMs));
},
teardown(): void {
if (intervalId) {
clearInterval(intervalId);
intervalId = undefined;
}
},
};
});