@spotlightjs/spotlight 4.3.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/instrument.js +56 -3
- package/bin/run.js +24 -35
- package/dist/overlay/assets/main.js +67 -67
- package/package.json +3 -3
package/bin/instrument.js
CHANGED
|
@@ -1,4 +1,56 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { consoleLoggingIntegration, getClient, init } from "@sentry/node";
|
|
2
|
+
import { parseCLIArgs } from "@spotlightjs/sidecar/cli";
|
|
3
|
+
import { DEFAULT_PORT } from "@spotlightjs/sidecar/constants";
|
|
4
|
+
|
|
5
|
+
// Parse CLI arguments to determine the port this Spotlight instance will use
|
|
6
|
+
const { port: instancePort } = parseCLIArgs();
|
|
7
|
+
|
|
8
|
+
// Check if SENTRY_SPOTLIGHT points to this instance
|
|
9
|
+
const spotlightEnv = process.env.SENTRY_SPOTLIGHT;
|
|
10
|
+
let disableSpotlight = false;
|
|
11
|
+
|
|
12
|
+
// Note: If port is set to 0 (dynamic port assignment), we cannot detect the actual port
|
|
13
|
+
// before starting the server, so we cannot prevent the feedback loop in that case.
|
|
14
|
+
// The server will be assigned a port by the OS after it starts, and if SENTRY_SPOTLIGHT
|
|
15
|
+
// happens to point to that same port, a feedback loop may occur.
|
|
16
|
+
if (spotlightEnv && instancePort !== 0) {
|
|
17
|
+
let targetPort;
|
|
18
|
+
let targetHost;
|
|
19
|
+
|
|
20
|
+
// SENTRY_SPOTLIGHT can be:
|
|
21
|
+
// 1. A full URL like "http://localhost:8969"
|
|
22
|
+
// 2. A truthy value (true, t, y, yes, on, 1) which means use the default URL
|
|
23
|
+
const TRUTHY_ENV_VALUES = new Set(["true", "t", "y", "yes", "on", "1"]);
|
|
24
|
+
const isTruthy = TRUTHY_ENV_VALUES.has(spotlightEnv.toLowerCase());
|
|
25
|
+
|
|
26
|
+
if (isTruthy) {
|
|
27
|
+
// Use default Spotlight URL
|
|
28
|
+
targetHost = "localhost";
|
|
29
|
+
targetPort = DEFAULT_PORT;
|
|
30
|
+
} else {
|
|
31
|
+
// Try to parse as URL
|
|
32
|
+
try {
|
|
33
|
+
const spotlightUrl = new URL(spotlightEnv);
|
|
34
|
+
targetHost = spotlightUrl.hostname;
|
|
35
|
+
targetPort = spotlightUrl.port ? Number(spotlightUrl.port) : spotlightUrl.protocol === "https:" ? 443 : 80;
|
|
36
|
+
} catch (_err) {
|
|
37
|
+
// If we can't parse it, we can't determine if it's a feedback loop, so do nothing
|
|
38
|
+
targetPort = null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Only disable if we successfully determined the target and it matches our instance
|
|
43
|
+
if (targetPort !== null && targetPort !== undefined) {
|
|
44
|
+
const isLocalhost = targetHost === "localhost" || targetHost === "127.0.0.1" || targetHost === "::1";
|
|
45
|
+
|
|
46
|
+
if (isLocalhost && targetPort === instancePort) {
|
|
47
|
+
disableSpotlight = true;
|
|
48
|
+
console.warn(
|
|
49
|
+
`⚠️ [Spotlight] SENTRY_SPOTLIGHT is set to ${spotlightEnv} which points to this Spotlight instance (port ${instancePort}). Disabling Spotlight integration to prevent feedback loop.`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
2
54
|
|
|
3
55
|
const sentry = init({
|
|
4
56
|
dsn: "https://51bcd92dba1128934afd1c5726c84442@o1.ingest.us.sentry.io/4508404727283713",
|
|
@@ -8,6 +60,7 @@ const sentry = init({
|
|
|
8
60
|
|
|
9
61
|
tracesSampleRate: 1,
|
|
10
62
|
enableLogs: true,
|
|
63
|
+
...(disableSpotlight && { spotlight: false }),
|
|
11
64
|
|
|
12
65
|
integrations: [
|
|
13
66
|
consoleLoggingIntegration({
|
|
@@ -15,12 +68,12 @@ const sentry = init({
|
|
|
15
68
|
}),
|
|
16
69
|
],
|
|
17
70
|
|
|
18
|
-
beforeSendTransaction:
|
|
71
|
+
beforeSendTransaction: event => {
|
|
19
72
|
event.server_name = undefined; // Server name might contain PII
|
|
20
73
|
return event;
|
|
21
74
|
},
|
|
22
75
|
|
|
23
|
-
beforeSend:
|
|
76
|
+
beforeSend: event => {
|
|
24
77
|
const exceptions = event.exception?.values;
|
|
25
78
|
if (!exceptions) {
|
|
26
79
|
return event;
|
package/bin/run.js
CHANGED
|
@@ -20,55 +20,44 @@ const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
|
20
20
|
setContext("CLI", {
|
|
21
21
|
sea: sea.isSea(),
|
|
22
22
|
// TODO: Be less naive with path obscuring
|
|
23
|
-
argv: process.argv.map(
|
|
23
|
+
argv: process.argv.map(arg => arg.replace(homeDir, "~")),
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
const withTracing =
|
|
27
27
|
(fn, spanArgs = {}) =>
|
|
28
28
|
(...args) =>
|
|
29
|
-
startSpan({ name: fn.name, attributes: { args }, ...spanArgs }, () =>
|
|
30
|
-
fn(...args)
|
|
31
|
-
);
|
|
29
|
+
startSpan({ name: fn.name, attributes: { args }, ...spanArgs }, () => fn(...args));
|
|
32
30
|
|
|
33
31
|
const readAsset = withTracing(
|
|
34
32
|
sea.isSea()
|
|
35
|
-
?
|
|
33
|
+
? name => Buffer.from(sea.getRawAsset(name))
|
|
36
34
|
: (() => {
|
|
37
|
-
const ASSET_DIR = join(
|
|
38
|
-
fileURLToPath(import.meta.url),
|
|
39
|
-
"../../dist/overlay/"
|
|
40
|
-
);
|
|
35
|
+
const ASSET_DIR = join(fileURLToPath(import.meta.url), "../../dist/overlay/");
|
|
41
36
|
|
|
42
|
-
return
|
|
37
|
+
return name => readFileSync(join(ASSET_DIR, name));
|
|
43
38
|
})(),
|
|
44
|
-
{ name: "readAsset", op: "cli.asset.read" }
|
|
39
|
+
{ name: "readAsset", op: "cli.asset.read" },
|
|
45
40
|
);
|
|
46
41
|
|
|
47
42
|
startSpan({ name: "Spotlight CLI", op: "cli" }, async () => {
|
|
48
|
-
await startSpan(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const ENTRY_POINT_NAME = "src/index.html";
|
|
53
|
-
const filesToServe = Object.create(null);
|
|
43
|
+
await startSpan({ name: "Setup Sidecar", op: "cli.setup.sidecar" }, async () => {
|
|
44
|
+
const MANIFEST_NAME = "manifest.json";
|
|
45
|
+
const ENTRY_POINT_NAME = "src/index.html";
|
|
46
|
+
const filesToServe = Object.create(null);
|
|
54
47
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
);
|
|
48
|
+
startSpan({ name: "Setup Server Assets", op: "cli.setup.sidecar.assets" }, () => {
|
|
49
|
+
// Following the guide here: https://vite.dev/guide/backend-integration.html
|
|
50
|
+
const manifest = JSON.parse(readAsset(MANIFEST_NAME));
|
|
51
|
+
filesToServe[ENTRY_POINT_NAME] = readAsset(ENTRY_POINT_NAME);
|
|
52
|
+
const entries = Object.values(manifest);
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
filesToServe[entry.file] = readAsset(entry.file);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
);
|
|
58
|
+
await main({
|
|
59
|
+
basePath: process.cwd(),
|
|
60
|
+
filesToServe,
|
|
61
|
+
});
|
|
62
|
+
});
|
|
74
63
|
});
|