forked from getsentry/sentry-javascript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnode-cron.ts
More file actions
72 lines (66 loc) · 2.22 KB
/
Copy pathnode-cron.ts
File metadata and controls
72 lines (66 loc) · 2.22 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
import { captureException, withMonitor } from '@sentry/core';
import { replaceCronNames } from './common';
export interface NodeCronOptions {
name: string;
timezone?: string;
}
export interface NodeCron {
schedule: (cronExpression: string, callback: () => void, options: NodeCronOptions) => unknown;
}
/**
* Wraps the `node-cron` library with check-in monitoring.
*
* ```ts
* import * as Sentry from "@sentry/node";
* import * as cron from "node-cron";
*
* const cronWithCheckIn = Sentry.cron.instrumentNodeCron(cron);
*
* cronWithCheckIn.schedule(
* "* * * * *",
* () => {
* console.log("running a task every minute");
* },
* { name: "my-cron-job" },
* );
* ```
*/
export function instrumentNodeCron<T>(lib: Partial<NodeCron> & T): T {
return new Proxy(lib, {
get(target, prop: keyof NodeCron) {
if (prop === 'schedule' && target.schedule) {
// When 'get' is called for schedule, return a proxied version of the schedule function
return new Proxy(target.schedule, {
apply(target, thisArg, argArray: Parameters<NodeCron['schedule']>) {
const [expression, callback, options] = argArray;
if (!options?.name) {
throw new Error('Missing "name" for scheduled job. A name is required for Sentry check-in monitoring.');
}
async function monitoredCallback(): Promise<void> {
return withMonitor(
options.name,
async () => {
// We have to manually catch here and capture the exception because node-cron swallows errors
// https://github.com/node-cron/node-cron/issues/399
try {
return await callback();
} catch (e) {
captureException(e);
throw e;
}
},
{
schedule: { type: 'crontab', value: replaceCronNames(expression) },
timezone: options?.timezone,
},
);
}
return target.apply(thisArg, [expression, monitoredCallback, options]);
},
});
} else {
return target[prop];
}
},
});
}