@od-oneapp/observability 2026.2.1701 → 2026.2.2001-canary.1
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/CHANGELOG.md +3 -3
- package/README.md +6 -6
- package/client-next.d.mts +6 -6
- package/client-next.mjs +4 -4
- package/client.d.mts +3 -3
- package/client.mjs +1 -1
- package/client.mjs.map +1 -1
- package/core-BgKCqXjb.mjs +95 -0
- package/core-BgKCqXjb.mjs.map +1 -0
- package/env.mjs +1 -1
- package/env.mjs.map +1 -1
- package/{factory-DkY353r8.mjs → factory-d1469fpz.mjs} +2 -2
- package/factory-d1469fpz.mjs.map +1 -0
- package/hooks-useObservability.d.mts +1 -1
- package/hooks-useObservability.mjs +1 -1
- package/hooks-useObservability.mjs.map +1 -1
- package/{index-CpcdzWrF.d.mts → index-CktVJJqJ.d.mts} +3 -3
- package/{index-CpcdzWrF.d.mts.map → index-CktVJJqJ.d.mts.map} +1 -1
- package/index.mjs +1 -1
- package/index.mjs.map +1 -1
- package/logs-DkncIKEw.mjs +112 -0
- package/logs-DkncIKEw.mjs.map +1 -0
- package/{manager-BxQqOPEg.d.mts → manager-CONEYB97.d.mts} +2 -2
- package/{manager-BxQqOPEg.d.mts.map → manager-CONEYB97.d.mts.map} +1 -1
- package/package.json +33 -40
- package/{plugin-Bt-ygG1m.d.mts → plugin-81171XQL.d.mts} +4 -4
- package/{plugin-Bt-ygG1m.d.mts.map → plugin-81171XQL.d.mts.map} +1 -1
- package/{plugin-CaQxviDs.d.mts → plugin-CEOGIJFN.d.mts} +2 -2
- package/{plugin-CaQxviDs.d.mts.map → plugin-CEOGIJFN.d.mts.map} +1 -1
- package/plugin-CuRZ8qQf.mjs +593 -0
- package/plugin-CuRZ8qQf.mjs.map +1 -0
- package/{plugin-CP895lBx.mjs → plugin-DApSl5bY.mjs} +2 -2
- package/plugin-DApSl5bY.mjs.map +1 -0
- package/{plugin-lPdJirTY.mjs → plugin-LhaOv4eq.mjs} +2 -2
- package/plugin-LhaOv4eq.mjs.map +1 -0
- package/{plugin-Bfq-o3nr.d.mts → plugin-pvH_kv0a.d.mts} +1 -1
- package/{plugin-Bfq-o3nr.d.mts.map → plugin-pvH_kv0a.d.mts.map} +1 -1
- package/plugins-betterstack-env.mjs +1 -1
- package/plugins-betterstack-env.mjs.map +1 -1
- package/plugins-betterstack.d.mts +2 -2
- package/plugins-betterstack.mjs +1 -1
- package/plugins-console.d.mts +1 -1
- package/plugins-sentry-env.d.mts +4 -4
- package/plugins-sentry-env.mjs +1 -1
- package/plugins-sentry-env.mjs.map +1 -1
- package/plugins-sentry-microfrontend-env.mjs +1 -1
- package/plugins-sentry-microfrontend-env.mjs.map +1 -1
- package/plugins-sentry-microfrontend.d.mts +1 -1
- package/plugins-sentry-microfrontend.mjs +1 -1
- package/plugins-sentry.d.mts +2 -2
- package/plugins-sentry.mjs +1 -1
- package/server-edge.d.mts +4 -4
- package/server-edge.mjs +2 -2
- package/server-next.d.mts +6 -6
- package/server-next.mjs +4 -4
- package/server.d.mts +3 -3
- package/server.mjs +1 -1
- package/server.mjs.map +1 -1
- package/{utils-DjjqCeoW.d.mts → utils-6Gg4fkvH.d.mts} +4 -3
- package/utils-6Gg4fkvH.d.mts.map +1 -0
- package/factory-DkY353r8.mjs.map +0 -1
- package/plugin-CP895lBx.mjs.map +0 -1
- package/plugin-CxeJHHeJ.mjs +0 -1195
- package/plugin-CxeJHHeJ.mjs.map +0 -1
- package/plugin-lPdJirTY.mjs.map +0 -1
- package/utils-DjjqCeoW.d.mts.map +0 -1
package/plugin-CxeJHHeJ.mjs
DELETED
|
@@ -1,1195 +0,0 @@
|
|
|
1
|
-
import { createEnv } from "@t3-oss/env-core";
|
|
2
|
-
import { z } from "zod/v4";
|
|
3
|
-
import { logDebug, logError, logWarn } from "@od-oneapp/shared/logs";
|
|
4
|
-
|
|
5
|
-
//#region src/plugins/sentry-microfrontend/multiplexed-transport.ts
|
|
6
|
-
/**
|
|
7
|
-
* @fileoverview Multiplexed transport utilities for Sentry Micro Frontend Plugin
|
|
8
|
-
* Multiplexed transport utilities for Sentry Micro Frontend Plugin
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Create a multiplexed transport that routes events to different Sentry projects.
|
|
12
|
-
*
|
|
13
|
-
* Creates a Sentry transport that routes events to different DSNs based on the
|
|
14
|
-
* backstageApp information in the event. Supports edge runtime environments.
|
|
15
|
-
*
|
|
16
|
-
* @param backstage - Array of backstage app configurations with DSNs
|
|
17
|
-
* @param fallbackDsn - Optional fallback DSN if no backstageApp match is found
|
|
18
|
-
* @param sentryClient - Optional Sentry client instance (defaults to global Sentry)
|
|
19
|
-
* @returns Multiplexed transport instance, or undefined if Sentry is not available
|
|
20
|
-
*/
|
|
21
|
-
function createMultiplexedTransport(backstage, fallbackDsn, sentryClient) {
|
|
22
|
-
const Sentry = sentryClient !== void 0 ? sentryClient : typeof globalThis !== "undefined" ? globalThis.Sentry : null;
|
|
23
|
-
if (!Sentry?.makeMultiplexedTransport || !Sentry.makeFetchTransport) {
|
|
24
|
-
logWarn("Sentry multiplexed transport not available");
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
return Sentry.makeMultiplexedTransport(Sentry.makeFetchTransport, (args) => {
|
|
28
|
-
const event = args.getEvent();
|
|
29
|
-
if (!event) return [];
|
|
30
|
-
const backstageApp = event.tags?.backstageApp ?? event.extra?.backstageApp ?? event.contexts?.microFrontend?.backstageApp;
|
|
31
|
-
if (backstageApp) {
|
|
32
|
-
const backstageAppConfig = backstage.find((z) => z.name === backstageApp);
|
|
33
|
-
if (backstageAppConfig?.dsn) {
|
|
34
|
-
const envelope = [{
|
|
35
|
-
dsn: backstageAppConfig.dsn,
|
|
36
|
-
release: backstageAppConfig.release ?? event.release
|
|
37
|
-
}];
|
|
38
|
-
if (backstageAppConfig.tags && event.tags) Object.assign(event.tags, backstageAppConfig.tags);
|
|
39
|
-
return envelope;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (fallbackDsn) return [{ dsn: fallbackDsn }];
|
|
43
|
-
return [];
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Enhance an event with Backstage app information before sending.
|
|
48
|
-
*
|
|
49
|
-
* Adds backstageApp tags, context, and extra data to a Sentry event.
|
|
50
|
-
* This ensures events are properly tagged for micro frontend routing.
|
|
51
|
-
*
|
|
52
|
-
* @param event - Sentry event to enhance
|
|
53
|
-
* @param backstageApp - Name of the backstage app
|
|
54
|
-
* @param additionalContext - Optional additional context to add
|
|
55
|
-
* @returns Enhanced event with backstageApp information
|
|
56
|
-
*/
|
|
57
|
-
function enhanceEventWithBackstageApp(event, backstageApp, additionalContext) {
|
|
58
|
-
event.tags ??= {};
|
|
59
|
-
event.tags.backstageApp = backstageApp;
|
|
60
|
-
event.tags.microFrontend = true;
|
|
61
|
-
event.contexts ??= {};
|
|
62
|
-
event.contexts.microFrontend = {
|
|
63
|
-
backstageApp,
|
|
64
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
65
|
-
...additionalContext
|
|
66
|
-
};
|
|
67
|
-
event.extra ??= {};
|
|
68
|
-
event.extra.backstageApp = backstageApp;
|
|
69
|
-
return event;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Create a beforeSend hook that adds backstageApp information.
|
|
73
|
-
*
|
|
74
|
-
* Creates a Sentry beforeSend hook that enhances events with backstageApp information
|
|
75
|
-
* before they are sent. Can wrap an existing beforeSend hook.
|
|
76
|
-
*
|
|
77
|
-
* @param backstageApp - Name of the backstage app
|
|
78
|
-
* @param originalBeforeSend - Optional original beforeSend hook to wrap
|
|
79
|
-
* @returns beforeSend hook function
|
|
80
|
-
*/
|
|
81
|
-
function createBackstageBeforeSend(backstageApp, originalBeforeSend) {
|
|
82
|
-
return (event, hint) => {
|
|
83
|
-
enhanceEventWithBackstageApp(event, backstageApp);
|
|
84
|
-
if (originalBeforeSend) return originalBeforeSend(event, hint);
|
|
85
|
-
return event;
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
//#endregion
|
|
90
|
-
//#region ../../integrations/sentry/src/observability-plugin/env.ts
|
|
91
|
-
/**
|
|
92
|
-
* @fileoverview Sentry-specific environment configuration
|
|
93
|
-
* Sentry-specific environment configuration
|
|
94
|
-
* Apps can extend this configuration to inherit Sentry environment variables
|
|
95
|
-
*/
|
|
96
|
-
const env = createEnv({
|
|
97
|
-
server: {
|
|
98
|
-
SENTRY_DSN: z.string().url().optional(),
|
|
99
|
-
SENTRY_AUTH_TOKEN: z.string().optional(),
|
|
100
|
-
SENTRY_ORG: z.string().optional(),
|
|
101
|
-
SENTRY_PROJECT: z.string().optional(),
|
|
102
|
-
SENTRY_ENVIRONMENT: z.enum([
|
|
103
|
-
"development",
|
|
104
|
-
"preview",
|
|
105
|
-
"production"
|
|
106
|
-
]).optional(),
|
|
107
|
-
SENTRY_RELEASE: z.string().optional(),
|
|
108
|
-
SENTRY_TRACES_SAMPLE_RATE: z.coerce.number().min(0).max(1).optional(),
|
|
109
|
-
SENTRY_PROFILES_SAMPLE_RATE: z.coerce.number().min(0).max(1).optional(),
|
|
110
|
-
SENTRY_REPLAYS_SESSION_SAMPLE_RATE: z.coerce.number().min(0).max(1).optional(),
|
|
111
|
-
SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE: z.coerce.number().min(0).max(1).optional(),
|
|
112
|
-
SENTRY_DEBUG: z.string().optional().transform((val) => val === "true").default(false)
|
|
113
|
-
},
|
|
114
|
-
clientPrefix: "NEXT_PUBLIC_",
|
|
115
|
-
client: {
|
|
116
|
-
NEXT_PUBLIC_SENTRY_DSN: z.string().url().optional(),
|
|
117
|
-
NEXT_PUBLIC_SENTRY_ENVIRONMENT: z.enum([
|
|
118
|
-
"development",
|
|
119
|
-
"preview",
|
|
120
|
-
"production"
|
|
121
|
-
]).optional(),
|
|
122
|
-
NEXT_PUBLIC_SENTRY_RELEASE: z.string().optional()
|
|
123
|
-
},
|
|
124
|
-
runtimeEnv: process.env,
|
|
125
|
-
emptyStringAsUndefined: true,
|
|
126
|
-
onInvalidAccess: (variable) => {
|
|
127
|
-
if ([
|
|
128
|
-
"nodeType",
|
|
129
|
-
"$$typeof",
|
|
130
|
-
"constructor",
|
|
131
|
-
"prototype",
|
|
132
|
-
"toJSON",
|
|
133
|
-
"then"
|
|
134
|
-
].includes(variable)) return;
|
|
135
|
-
const message = `❌ Attempted to access a server-side environment variable on the client: ${variable}`;
|
|
136
|
-
if (Boolean(process.env.VITEST) || Boolean(process.env.VITEST_WORKER_ID) || Boolean(globalThis.vi) || Boolean(globalThis.vitest)) {
|
|
137
|
-
logWarn(message);
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
throw new Error(message);
|
|
141
|
-
},
|
|
142
|
-
onValidationError: (error) => {
|
|
143
|
-
logWarn("Sentry environment validation failed", { error });
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
/**
|
|
147
|
-
* Safe environment access for non-Next.js contexts.
|
|
148
|
-
*
|
|
149
|
-
* Provides fallback environment variable access for Node.js, workers, and test environments
|
|
150
|
-
* where the validated env object may not be available. Returns fallback values with proper
|
|
151
|
-
* type coercion and defaults.
|
|
152
|
-
*
|
|
153
|
-
* @returns Environment object with Sentry configuration values
|
|
154
|
-
*/
|
|
155
|
-
function safeEnv() {
|
|
156
|
-
if (env) return env;
|
|
157
|
-
return {
|
|
158
|
-
SENTRY_DSN: process.env.SENTRY_DSN ?? "",
|
|
159
|
-
SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN ?? "",
|
|
160
|
-
SENTRY_ORG: process.env.SENTRY_ORG ?? "",
|
|
161
|
-
SENTRY_PROJECT: process.env.SENTRY_PROJECT ?? "",
|
|
162
|
-
SENTRY_ENVIRONMENT: process.env.SENTRY_ENVIRONMENT ?? "development",
|
|
163
|
-
SENTRY_RELEASE: process.env.SENTRY_RELEASE ?? "",
|
|
164
|
-
SENTRY_TRACES_SAMPLE_RATE: Number(process.env.SENTRY_TRACES_SAMPLE_RATE) || 1,
|
|
165
|
-
SENTRY_PROFILES_SAMPLE_RATE: Number(process.env.SENTRY_PROFILES_SAMPLE_RATE) ?? 0,
|
|
166
|
-
SENTRY_REPLAYS_SESSION_SAMPLE_RATE: Number(process.env.SENTRY_REPLAYS_SESSION_SAMPLE_RATE) || 0,
|
|
167
|
-
SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE: Number(process.env.SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE) || 1,
|
|
168
|
-
SENTRY_DEBUG: process.env.SENTRY_DEBUG === "true",
|
|
169
|
-
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN ?? "",
|
|
170
|
-
NEXT_PUBLIC_SENTRY_ENVIRONMENT: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT ?? "development",
|
|
171
|
-
NEXT_PUBLIC_SENTRY_RELEASE: process.env.NEXT_PUBLIC_SENTRY_RELEASE ?? ""
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
//#endregion
|
|
176
|
-
//#region ../../integrations/sentry/src/observability-plugin/plugin.ts
|
|
177
|
-
/**
|
|
178
|
-
* @fileoverview Sentry plugin implementation
|
|
179
|
-
* Sentry plugin implementation
|
|
180
|
-
*/
|
|
181
|
-
/**
|
|
182
|
-
* Detect if code is running in a browser environment
|
|
183
|
-
*/
|
|
184
|
-
function isBrowser() {
|
|
185
|
-
const g = globalThis;
|
|
186
|
-
return typeof globalThis !== "undefined" && "window" in globalThis && typeof g.window?.document !== "undefined" && typeof g.window?.navigator !== "undefined";
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Default log filter function that filters out noisy development logs.
|
|
190
|
-
* Filters out:
|
|
191
|
-
* - Next.js Fast Refresh messages
|
|
192
|
-
* - HMR (Hot Module Replacement) messages
|
|
193
|
-
* - Prisma query logs (server-only)
|
|
194
|
-
* - Prisma engine/info logs
|
|
195
|
-
* - SQL queries matching Prisma's format
|
|
196
|
-
*
|
|
197
|
-
* Handles ANSI color codes, console formatting (%c, %s), and CSS styling.
|
|
198
|
-
*
|
|
199
|
-
* @param log - The log entry from Sentry
|
|
200
|
-
* @param isServer - Whether this is running on the server (defaults to true)
|
|
201
|
-
* @returns The log entry if it should be sent, or null to filter it out
|
|
202
|
-
*/
|
|
203
|
-
function defaultBeforeSendLog(log, isServer = true) {
|
|
204
|
-
const logObj = log;
|
|
205
|
-
const messageToCheck = logObj.message ?? logObj.formatted ?? "";
|
|
206
|
-
if (!messageToCheck) return log;
|
|
207
|
-
const messageWithoutAnsi = String(messageToCheck).replace(/\u001b\[[0-9;]*m/g, "").replace(/%[csdfiO]/g, "").replace(/background:[^;]+;?/g, "").replace(/color:[^;]+;?/g, "").replace(/border-radius:[^;]+;?/g, "").replace(/light-dark\([^)]+\)/g, "").replace(/rgba?\([^)]+\)/g, "").replace(/#[0-9a-fA-F]{3,8}/g, "").toLowerCase();
|
|
208
|
-
if (messageWithoutAnsi.includes("[fast refresh]") || messageWithoutAnsi.includes("[hmr]")) return null;
|
|
209
|
-
if (isServer) {
|
|
210
|
-
if (messageWithoutAnsi.includes("prisma:query") || messageWithoutAnsi.includes("prisma:engine") || messageWithoutAnsi.includes("prisma:info") || messageWithoutAnsi.includes("select") && messageWithoutAnsi.includes("from") && (messageWithoutAnsi.includes("\"public\".") || messageWithoutAnsi.includes("public."))) return null;
|
|
211
|
-
}
|
|
212
|
-
return log;
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Sentry plugin implementation
|
|
216
|
-
*/
|
|
217
|
-
/**
|
|
218
|
-
* Sentry plugin implementation.
|
|
219
|
-
*
|
|
220
|
-
* Integrates Sentry error tracking and performance monitoring into the observability system.
|
|
221
|
-
* Auto-detects the appropriate Sentry package (@sentry/node, @sentry/browser, @sentry/nextjs)
|
|
222
|
-
* based on the runtime environment.
|
|
223
|
-
*/
|
|
224
|
-
var SentryPlugin = class {
|
|
225
|
-
name = "sentry";
|
|
226
|
-
enabled;
|
|
227
|
-
client;
|
|
228
|
-
initialized = false;
|
|
229
|
-
sentryPackage;
|
|
230
|
-
config;
|
|
231
|
-
/**
|
|
232
|
-
* Create a new SentryPlugin instance.
|
|
233
|
-
*
|
|
234
|
-
* @param config - Sentry plugin configuration
|
|
235
|
-
*/
|
|
236
|
-
constructor(config = {}) {
|
|
237
|
-
this.config = config;
|
|
238
|
-
const env = safeEnv();
|
|
239
|
-
const hasDSN = config.dsn ?? env.SENTRY_DSN ?? env.NEXT_PUBLIC_SENTRY_DSN;
|
|
240
|
-
this.enabled = config.enabled ?? Boolean(hasDSN);
|
|
241
|
-
this.sentryPackage = config.sentryPackage ?? this.detectSentryPackage();
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Detect which Sentry package to use based on the runtime environment.
|
|
245
|
-
*
|
|
246
|
-
* @returns Package name ('@sentry/node', '@sentry/browser', or '@sentry/nextjs')
|
|
247
|
-
*/
|
|
248
|
-
detectSentryPackage() {
|
|
249
|
-
if (isBrowser()) return "@sentry/browser";
|
|
250
|
-
else if (process.env.NEXT_RUNTIME === "edge") return "@sentry/nextjs";
|
|
251
|
-
else if (process.env.NEXT_RUNTIME) return "@sentry/nextjs";
|
|
252
|
-
else return "@sentry/node";
|
|
253
|
-
}
|
|
254
|
-
getClient() {
|
|
255
|
-
return this.client;
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Get safe environment access (for testing/mocking).
|
|
259
|
-
*
|
|
260
|
-
* @returns Environment configuration object
|
|
261
|
-
*/
|
|
262
|
-
getSafeEnv() {
|
|
263
|
-
return safeEnv();
|
|
264
|
-
}
|
|
265
|
-
async initialize(config) {
|
|
266
|
-
if (this.initialized || !this.enabled) return;
|
|
267
|
-
const env = safeEnv();
|
|
268
|
-
const mergedConfig = {
|
|
269
|
-
...this.config,
|
|
270
|
-
...config
|
|
271
|
-
};
|
|
272
|
-
const dsn = mergedConfig.dsn ?? env.SENTRY_DSN ?? env.NEXT_PUBLIC_SENTRY_DSN;
|
|
273
|
-
if (!dsn) {
|
|
274
|
-
logWarn("Sentry plugin: No DSN provided, skipping initialization");
|
|
275
|
-
this.enabled = false;
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
try {
|
|
279
|
-
this.client = await import(
|
|
280
|
-
/* webpackIgnore: true */
|
|
281
|
-
this.sentryPackage
|
|
282
|
-
);
|
|
283
|
-
if (this.client && this.enabled) {
|
|
284
|
-
let { integrations } = mergedConfig;
|
|
285
|
-
if (!integrations && this.client.browserTracingIntegration) {
|
|
286
|
-
integrations = [];
|
|
287
|
-
if (mergedConfig.tracesSampleRate !== void 0 || env.SENTRY_TRACES_SAMPLE_RATE !== void 0) integrations.push(this.client.browserTracingIntegration());
|
|
288
|
-
if (this.client.replayIntegration && (mergedConfig.replaysSessionSampleRate !== void 0 || env.SENTRY_REPLAYS_SESSION_SAMPLE_RATE !== void 0)) integrations.push(this.client.replayIntegration());
|
|
289
|
-
if (this.client.profilesIntegration && (mergedConfig.profilesSampleRate !== void 0 || env.SENTRY_PROFILES_SAMPLE_RATE !== void 0)) integrations.push(this.client.profilesIntegration());
|
|
290
|
-
}
|
|
291
|
-
const enableLogs = mergedConfig.enableLogs ?? true;
|
|
292
|
-
if (enableLogs && this.client.consoleLoggingIntegration) {
|
|
293
|
-
const consoleLoggingConfig = mergedConfig.consoleLoggingIntegration || { levels: [
|
|
294
|
-
"log",
|
|
295
|
-
"warn",
|
|
296
|
-
"error"
|
|
297
|
-
] };
|
|
298
|
-
if (!integrations) integrations = [];
|
|
299
|
-
integrations.push(this.client.consoleLoggingIntegration(consoleLoggingConfig));
|
|
300
|
-
}
|
|
301
|
-
this.client.init({
|
|
302
|
-
dsn,
|
|
303
|
-
environment: mergedConfig.environment ?? env.SENTRY_ENVIRONMENT ?? "development",
|
|
304
|
-
release: mergedConfig.release ?? env.SENTRY_RELEASE,
|
|
305
|
-
debug: mergedConfig.debug ?? env.SENTRY_DEBUG,
|
|
306
|
-
enableLogs,
|
|
307
|
-
tracesSampleRate: mergedConfig.tracesSampleRate ?? env.SENTRY_TRACES_SAMPLE_RATE,
|
|
308
|
-
profilesSampleRate: mergedConfig.profilesSampleRate ?? env.SENTRY_PROFILES_SAMPLE_RATE,
|
|
309
|
-
replaysSessionSampleRate: mergedConfig.replaysSessionSampleRate ?? env.SENTRY_REPLAYS_SESSION_SAMPLE_RATE,
|
|
310
|
-
replaysOnErrorSampleRate: mergedConfig.replaysOnErrorSampleRate ?? env.SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE,
|
|
311
|
-
integrations,
|
|
312
|
-
beforeSend: mergedConfig.beforeSend,
|
|
313
|
-
beforeSendTransaction: mergedConfig.beforeSendTransaction,
|
|
314
|
-
beforeSendLog: mergedConfig.beforeSendLog || (enableLogs ? (log) => defaultBeforeSendLog(log, !isBrowser()) : void 0),
|
|
315
|
-
tracePropagationTargets: mergedConfig.tracePropagationTargets,
|
|
316
|
-
initialScope: mergedConfig.initialScope,
|
|
317
|
-
maxBreadcrumbs: mergedConfig.maxBreadcrumbs,
|
|
318
|
-
attachStacktrace: mergedConfig.attachStacktrace,
|
|
319
|
-
autoSessionTracking: mergedConfig.autoSessionTracking
|
|
320
|
-
});
|
|
321
|
-
this.initialized = true;
|
|
322
|
-
}
|
|
323
|
-
} catch (error) {
|
|
324
|
-
logError(`Failed to import Sentry package '${this.sentryPackage}'`, { error });
|
|
325
|
-
this.enabled = false;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
async shutdown() {
|
|
329
|
-
if (this.client && this.initialized) {
|
|
330
|
-
if (this.client.close) await this.client.close();
|
|
331
|
-
else if (this.client.flush) await this.client.flush();
|
|
332
|
-
this.initialized = false;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Clean up the plugin (alias for shutdown)
|
|
337
|
-
*/
|
|
338
|
-
async cleanup() {
|
|
339
|
-
await this.shutdown();
|
|
340
|
-
}
|
|
341
|
-
captureException(error, context) {
|
|
342
|
-
if (!this.enabled || !this.client) return;
|
|
343
|
-
if (typeof this.client.captureException !== "function") {
|
|
344
|
-
logError("[Sentry Fallback] Exception", { error });
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
try {
|
|
348
|
-
this.client.captureException(error, context);
|
|
349
|
-
} catch (captureError) {
|
|
350
|
-
logWarn("[Sentry Plugin] Failed to capture exception", { error: captureError });
|
|
351
|
-
logError("[Sentry Fallback] Exception", { error });
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
captureMessage(message, level = "info", context) {
|
|
355
|
-
if (!this.enabled || !this.client) return;
|
|
356
|
-
if (this.client.logger) try {
|
|
357
|
-
const attributes = context ? context.extra ?? context : void 0;
|
|
358
|
-
switch (level) {
|
|
359
|
-
case "debug":
|
|
360
|
-
this.client.logger.debug(message, attributes);
|
|
361
|
-
return;
|
|
362
|
-
case "info":
|
|
363
|
-
this.client.logger.info(message, attributes);
|
|
364
|
-
return;
|
|
365
|
-
case "warning":
|
|
366
|
-
this.client.logger.warn(message, attributes);
|
|
367
|
-
return;
|
|
368
|
-
case "error":
|
|
369
|
-
this.client.logger.error(message, attributes);
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
} catch (error) {
|
|
373
|
-
logWarn("[Sentry Plugin] Failed to log via logger", { error });
|
|
374
|
-
}
|
|
375
|
-
if (typeof this.client.captureMessage !== "function") {
|
|
376
|
-
if (level === "error") logError(`[Sentry Fallback] ${message}`);
|
|
377
|
-
else if (level === "warning") logWarn(`[Sentry Fallback] ${message}`);
|
|
378
|
-
else logDebug(`[Sentry Fallback] ${message}`);
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
const sentryLevel = level === "warning" ? "warning" : level === "error" ? "error" : level === "debug" ? "debug" : "info";
|
|
382
|
-
try {
|
|
383
|
-
const captureContext = context ? {
|
|
384
|
-
level: sentryLevel,
|
|
385
|
-
extra: context.extra ?? context,
|
|
386
|
-
tags: context.tags
|
|
387
|
-
} : sentryLevel;
|
|
388
|
-
this.client.captureMessage(message, captureContext);
|
|
389
|
-
} catch (error) {
|
|
390
|
-
logWarn("[Sentry Plugin] Failed to capture message", { error });
|
|
391
|
-
if (level === "error") logError(`[Sentry Fallback] ${message}`);
|
|
392
|
-
else if (level === "warning") logWarn(`[Sentry Fallback] ${message}`);
|
|
393
|
-
else logDebug(`[Sentry Fallback] ${message}`);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
setUser(user) {
|
|
397
|
-
if (!this.enabled || !this.client) return;
|
|
398
|
-
this.client.setUser(user);
|
|
399
|
-
}
|
|
400
|
-
addBreadcrumb(breadcrumb) {
|
|
401
|
-
if (!this.enabled || !this.client) return;
|
|
402
|
-
this.client.addBreadcrumb({
|
|
403
|
-
...breadcrumb,
|
|
404
|
-
timestamp: breadcrumb.timestamp ?? Date.now() / 1e3
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
withScope(callback) {
|
|
408
|
-
if (!this.enabled || !this.client) return;
|
|
409
|
-
this.client.withScope(callback);
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Start a new transaction
|
|
413
|
-
*/
|
|
414
|
-
startTransaction(context, customSamplingContext) {
|
|
415
|
-
if (!this.enabled || !this.client) return void 0;
|
|
416
|
-
if (this.client.startTransaction) return this.client.startTransaction(context, customSamplingContext);
|
|
417
|
-
logWarn("startTransaction not available in this Sentry version");
|
|
418
|
-
}
|
|
419
|
-
/**
|
|
420
|
-
* Start a new span
|
|
421
|
-
*/
|
|
422
|
-
startSpan(context) {
|
|
423
|
-
if (!this.enabled || !this.client) return void 0;
|
|
424
|
-
if (this.client.startSpan) return this.client.startSpan(context);
|
|
425
|
-
const transaction = this.getActiveTransaction();
|
|
426
|
-
if (transaction?.startChild) return transaction.startChild(context);
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Get the currently active transaction
|
|
430
|
-
*/
|
|
431
|
-
getActiveTransaction() {
|
|
432
|
-
if (!this.enabled || !this.client) return void 0;
|
|
433
|
-
if (this.client.getActiveTransaction) return this.client.getActiveTransaction();
|
|
434
|
-
if (this.client.getCurrentScope) {
|
|
435
|
-
const scope = this.client.getCurrentScope();
|
|
436
|
-
if (scope?.getTransaction) return scope.getTransaction();
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Configure the current scope
|
|
441
|
-
*/
|
|
442
|
-
configureScope(callback) {
|
|
443
|
-
if (!this.enabled || !this.client) return;
|
|
444
|
-
if (this.client.configureScope) this.client.configureScope(callback);
|
|
445
|
-
else if (this.client.withScope) this.client.withScope(callback);
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Get the current hub instance
|
|
449
|
-
*/
|
|
450
|
-
getCurrentHub() {
|
|
451
|
-
if (!this.enabled || !this.client) return void 0;
|
|
452
|
-
if (this.client.getCurrentHub) return this.client.getCurrentHub();
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* Set a measurement on the active transaction
|
|
456
|
-
*/
|
|
457
|
-
setMeasurement(name, value, unit) {
|
|
458
|
-
if (!this.enabled || !this.client) return;
|
|
459
|
-
const transaction = this.getActiveTransaction();
|
|
460
|
-
if (transaction?.setMeasurement) transaction.setMeasurement(name, value, unit);
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Add performance entries as breadcrumbs and measurements
|
|
464
|
-
*/
|
|
465
|
-
addPerformanceEntries(entries) {
|
|
466
|
-
if (!this.enabled || !this.client) return;
|
|
467
|
-
const transaction = this.getActiveTransaction();
|
|
468
|
-
entries.forEach((entry) => {
|
|
469
|
-
this.addBreadcrumb({
|
|
470
|
-
category: "performance",
|
|
471
|
-
message: `${entry.entryType}: ${entry.name}`,
|
|
472
|
-
data: {
|
|
473
|
-
name: entry.name,
|
|
474
|
-
duration: entry.duration,
|
|
475
|
-
startTime: entry.startTime,
|
|
476
|
-
...entry.entryType === "navigation" && {
|
|
477
|
-
transferSize: entry.transferSize,
|
|
478
|
-
encodedBodySize: entry.encodedBodySize,
|
|
479
|
-
decodedBodySize: entry.decodedBodySize
|
|
480
|
-
},
|
|
481
|
-
...entry.entryType === "resource" && {
|
|
482
|
-
initiatorType: entry.initiatorType,
|
|
483
|
-
transferSize: entry.transferSize
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
});
|
|
487
|
-
if (transaction && entry.entryType === "navigation") {
|
|
488
|
-
const navEntry = entry;
|
|
489
|
-
const fetchStart = navEntry.fetchStart ?? 0;
|
|
490
|
-
if (navEntry.responseStart !== void 0) this.setMeasurement("fcp", navEntry.responseStart - fetchStart, "millisecond");
|
|
491
|
-
if (navEntry.domInteractive !== void 0) this.setMeasurement("dom_interactive", navEntry.domInteractive - fetchStart, "millisecond");
|
|
492
|
-
if (navEntry.domComplete !== void 0) this.setMeasurement("dom_complete", navEntry.domComplete - fetchStart, "millisecond");
|
|
493
|
-
if (navEntry.loadEventEnd !== void 0) this.setMeasurement("load_event_end", navEntry.loadEventEnd - fetchStart, "millisecond");
|
|
494
|
-
}
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
|
-
* Record a Web Vital measurement
|
|
499
|
-
*/
|
|
500
|
-
recordWebVital(name, value, options) {
|
|
501
|
-
if (!this.enabled || !this.client) return;
|
|
502
|
-
const { unit = "millisecond", rating } = options ?? {};
|
|
503
|
-
const transaction = this.getActiveTransaction();
|
|
504
|
-
if (transaction) {
|
|
505
|
-
transaction.setMeasurement(name.toLowerCase(), value, unit);
|
|
506
|
-
if (rating) transaction.setTag(`webvital.${name.toLowerCase()}.rating`, rating);
|
|
507
|
-
this.client.captureMessage(`Web Vital: ${name}`, {
|
|
508
|
-
level: "info",
|
|
509
|
-
tags: {
|
|
510
|
-
"webvital.name": name,
|
|
511
|
-
"webvital.value": value,
|
|
512
|
-
"webvital.unit": unit,
|
|
513
|
-
...rating && { "webvital.rating": rating }
|
|
514
|
-
},
|
|
515
|
-
contexts: { trace: {
|
|
516
|
-
trace_id: transaction.traceId,
|
|
517
|
-
span_id: transaction.spanId
|
|
518
|
-
} }
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* Create a custom performance mark
|
|
524
|
-
*/
|
|
525
|
-
mark(name, options) {
|
|
526
|
-
if (!this.enabled) return;
|
|
527
|
-
if (typeof performance !== "undefined" && performance.mark) performance.mark(name, options);
|
|
528
|
-
this.addBreadcrumb({
|
|
529
|
-
category: "performance.mark",
|
|
530
|
-
message: name,
|
|
531
|
-
data: options?.detail,
|
|
532
|
-
timestamp: Date.now() / 1e3
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
/**
|
|
536
|
-
* Create a custom performance measure
|
|
537
|
-
*/
|
|
538
|
-
measure(name, startMarkOrOptions, endMark) {
|
|
539
|
-
if (!this.enabled) return;
|
|
540
|
-
if (typeof performance !== "undefined" && performance.measure) {
|
|
541
|
-
if (typeof startMarkOrOptions === "string") performance.measure(name, startMarkOrOptions, endMark);
|
|
542
|
-
else if (startMarkOrOptions) performance.measure(name, startMarkOrOptions);
|
|
543
|
-
else performance.measure(name);
|
|
544
|
-
const measures = performance.getEntriesByName(name, "measure");
|
|
545
|
-
const measure = measures[measures.length - 1];
|
|
546
|
-
if (measure) {
|
|
547
|
-
this.setMeasurement(name, measure.duration, "millisecond");
|
|
548
|
-
this.addBreadcrumb({
|
|
549
|
-
category: "performance.measure",
|
|
550
|
-
message: name,
|
|
551
|
-
data: {
|
|
552
|
-
duration: measure.duration,
|
|
553
|
-
startTime: measure.startTime
|
|
554
|
-
},
|
|
555
|
-
timestamp: measure.startTime / 1e3
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
/**
|
|
561
|
-
* Log a trace message using Sentry.logger (if available).
|
|
562
|
-
* Falls back to captureMessage if logger is not available.
|
|
563
|
-
*
|
|
564
|
-
* @param message - Trace message to log
|
|
565
|
-
* @param attributes - Optional attributes to include with the log
|
|
566
|
-
*/
|
|
567
|
-
logTrace(message, attributes) {
|
|
568
|
-
if (!this.enabled || !this.client) return;
|
|
569
|
-
if (this.client.logger?.trace) try {
|
|
570
|
-
this.client.logger.trace(message, attributes);
|
|
571
|
-
return;
|
|
572
|
-
} catch (error) {
|
|
573
|
-
logWarn("[Sentry Plugin] Failed to log trace", { error });
|
|
574
|
-
}
|
|
575
|
-
this.captureMessage(message, "debug", attributes);
|
|
576
|
-
}
|
|
577
|
-
/**
|
|
578
|
-
* Log a debug message using Sentry.logger (if available).
|
|
579
|
-
* Falls back to captureMessage if logger is not available.
|
|
580
|
-
*
|
|
581
|
-
* @param message - Debug message to log
|
|
582
|
-
* @param attributes - Optional attributes to include with the log
|
|
583
|
-
*/
|
|
584
|
-
logDebug(message, attributes) {
|
|
585
|
-
if (!this.enabled || !this.client) return;
|
|
586
|
-
if (this.client.logger?.debug) try {
|
|
587
|
-
this.client.logger.debug(message, attributes);
|
|
588
|
-
return;
|
|
589
|
-
} catch (error) {
|
|
590
|
-
logWarn("[Sentry Plugin] Failed to log debug", { error });
|
|
591
|
-
}
|
|
592
|
-
this.captureMessage(message, "debug", attributes);
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Log an info message using Sentry.logger (if available).
|
|
596
|
-
* Falls back to captureMessage if logger is not available.
|
|
597
|
-
*
|
|
598
|
-
* @param message - Info message to log
|
|
599
|
-
* @param attributes - Optional attributes to include with the log
|
|
600
|
-
*/
|
|
601
|
-
logInfo(message, attributes) {
|
|
602
|
-
if (!this.enabled || !this.client) return;
|
|
603
|
-
if (this.client.logger?.info) try {
|
|
604
|
-
this.client.logger.info(message, attributes);
|
|
605
|
-
return;
|
|
606
|
-
} catch (error) {
|
|
607
|
-
logWarn("[Sentry Plugin] Failed to log info", { error });
|
|
608
|
-
}
|
|
609
|
-
this.captureMessage(message, "info", attributes);
|
|
610
|
-
}
|
|
611
|
-
/**
|
|
612
|
-
* Log a warning message using Sentry.logger (if available).
|
|
613
|
-
* Falls back to captureMessage if logger is not available.
|
|
614
|
-
*
|
|
615
|
-
* @param message - Warning message to log
|
|
616
|
-
* @param attributes - Optional attributes to include with the log
|
|
617
|
-
*/
|
|
618
|
-
logWarn(message, attributes) {
|
|
619
|
-
if (!this.enabled || !this.client) return;
|
|
620
|
-
if (this.client.logger?.warn) try {
|
|
621
|
-
this.client.logger.warn(message, attributes);
|
|
622
|
-
return;
|
|
623
|
-
} catch (error) {
|
|
624
|
-
logWarn("[Sentry Plugin] Failed to log warn", { error });
|
|
625
|
-
}
|
|
626
|
-
this.captureMessage(message, "warning", attributes);
|
|
627
|
-
}
|
|
628
|
-
/**
|
|
629
|
-
* Log an error message using Sentry.logger (if available).
|
|
630
|
-
* Falls back to captureMessage if logger is not available.
|
|
631
|
-
*
|
|
632
|
-
* @param message - Error message to log
|
|
633
|
-
* @param attributes - Optional attributes to include with the log
|
|
634
|
-
*/
|
|
635
|
-
logError(message, attributes) {
|
|
636
|
-
if (!this.enabled || !this.client) return;
|
|
637
|
-
if (this.client.logger?.error) try {
|
|
638
|
-
this.client.logger.error(message, attributes);
|
|
639
|
-
return;
|
|
640
|
-
} catch (error) {
|
|
641
|
-
logWarn("[Sentry Plugin] Failed to log error", { error });
|
|
642
|
-
}
|
|
643
|
-
this.captureMessage(message, "error", attributes);
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
|
-
* Log a fatal message using Sentry.logger (if available).
|
|
647
|
-
* Falls back to captureMessage if logger is not available.
|
|
648
|
-
*
|
|
649
|
-
* @param message - Fatal message to log
|
|
650
|
-
* @param attributes - Optional attributes to include with the log
|
|
651
|
-
*/
|
|
652
|
-
logFatal(message, attributes) {
|
|
653
|
-
if (!this.enabled || !this.client) return;
|
|
654
|
-
if (this.client.logger?.fatal) try {
|
|
655
|
-
this.client.logger.fatal(message, attributes);
|
|
656
|
-
return;
|
|
657
|
-
} catch (error) {
|
|
658
|
-
logWarn("[Sentry Plugin] Failed to log fatal", { error });
|
|
659
|
-
}
|
|
660
|
-
this.captureMessage(message, "error", attributes);
|
|
661
|
-
}
|
|
662
|
-
/**
|
|
663
|
-
* Get the Sentry.logger instance if available.
|
|
664
|
-
* This allows direct access to Sentry.logger APIs including fmt.
|
|
665
|
-
*
|
|
666
|
-
* @returns Sentry.logger instance or undefined if not available
|
|
667
|
-
*
|
|
668
|
-
* @example
|
|
669
|
-
* ```typescript
|
|
670
|
-
* const logger = sentryPlugin.getLogger();
|
|
671
|
-
* if (logger) {
|
|
672
|
-
* logger.info(logger.fmt`User ${user.id} logged in`);
|
|
673
|
-
* }
|
|
674
|
-
* ```
|
|
675
|
-
*/
|
|
676
|
-
getLogger() {
|
|
677
|
-
if (!this.enabled || !this.client) return void 0;
|
|
678
|
-
return this.client.logger;
|
|
679
|
-
}
|
|
680
|
-
async flush(timeout) {
|
|
681
|
-
if (!this.enabled || !this.client || !this.client.flush) return true;
|
|
682
|
-
try {
|
|
683
|
-
return await this.client.flush(timeout);
|
|
684
|
-
} catch (_error) {
|
|
685
|
-
return false;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
|
|
690
|
-
//#endregion
|
|
691
|
-
//#region src/plugins/sentry-microfrontend/sentry-types.ts
|
|
692
|
-
/**
|
|
693
|
-
* Map LogLevel to Sentry Severity.
|
|
694
|
-
*
|
|
695
|
-
* Converts the observability package's LogLevel to Sentry's SeverityLevel format.
|
|
696
|
-
*
|
|
697
|
-
* @param level - Log level from observability package
|
|
698
|
-
* @returns Corresponding Sentry severity level
|
|
699
|
-
*/
|
|
700
|
-
function mapLogLevelToSentrySeverity(level) {
|
|
701
|
-
switch (level) {
|
|
702
|
-
case "error": return "error";
|
|
703
|
-
case "warning": return "warning";
|
|
704
|
-
case "info": return "info";
|
|
705
|
-
case "debug": return "debug";
|
|
706
|
-
default: return "info";
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
//#endregion
|
|
711
|
-
//#region src/plugins/sentry-microfrontend/utils.ts
|
|
712
|
-
/**
|
|
713
|
-
* @fileoverview Utility functions for Sentry Micro Frontend Plugin
|
|
714
|
-
* Utility functions for Sentry Micro Frontend Plugin
|
|
715
|
-
*/
|
|
716
|
-
/**
|
|
717
|
-
* Detect the current micro frontend backstageApp based on URL path.
|
|
718
|
-
*
|
|
719
|
-
* Analyzes the current URL pathname to determine which micro frontend application
|
|
720
|
-
* is active. Supports custom path patterns and falls back to default patterns.
|
|
721
|
-
*
|
|
722
|
-
* @param customPatterns - Optional array of custom backstage app configurations with path patterns
|
|
723
|
-
* @returns Detected backstage app name, or undefined if not detected
|
|
724
|
-
*
|
|
725
|
-
* @example
|
|
726
|
-
* ```typescript
|
|
727
|
-
* const app = detectCurrentBackstageApp([
|
|
728
|
-
* { name: 'admin', pathPatterns: ['/admin', '/manage'] },
|
|
729
|
-
* { name: 'dashboard', pathPatterns: [/^\/dashboard/] }
|
|
730
|
-
* ]);
|
|
731
|
-
* // Returns: 'admin' if pathname starts with '/admin' or '/manage'
|
|
732
|
-
* ```
|
|
733
|
-
*/
|
|
734
|
-
function detectCurrentBackstageApp(customPatterns) {
|
|
735
|
-
if (typeof globalThis === "undefined" || !globalThis.location) {
|
|
736
|
-
if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_BASE_PATH) return process.env.NEXT_PUBLIC_BASE_PATH.replace("/", "");
|
|
737
|
-
return;
|
|
738
|
-
}
|
|
739
|
-
const path = globalThis.location?.pathname;
|
|
740
|
-
if (!path) return;
|
|
741
|
-
if (customPatterns) {
|
|
742
|
-
for (const config of customPatterns) if (config.pathPatterns) {
|
|
743
|
-
for (const pattern of config.pathPatterns) if (typeof pattern === "string" && path.startsWith(pattern)) return config.name;
|
|
744
|
-
else if (pattern instanceof RegExp && pattern.test(path)) return config.name;
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
if (path.startsWith("/admin")) return "admin";
|
|
748
|
-
if (path.startsWith("/dashboard")) return "dashboard";
|
|
749
|
-
if (path.startsWith("/settings")) return "settings";
|
|
750
|
-
if (globalThis.__SENTRY_MICRO_FRONTEND_APP__) return globalThis.__SENTRY_MICRO_FRONTEND_APP__;
|
|
751
|
-
if (globalThis.__SENTRY_MICRO_FRONTEND_ZONE__) return globalThis.__SENTRY_MICRO_FRONTEND_ZONE__;
|
|
752
|
-
return "main";
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Check if running in a host environment.
|
|
756
|
-
*
|
|
757
|
-
* Determines whether the current application is acting as a host for micro frontends
|
|
758
|
-
* or as a child micro frontend. Checks for explicit host markers and Sentry initialization state.
|
|
759
|
-
*
|
|
760
|
-
* @returns True if running as host, false if child or standalone
|
|
761
|
-
*/
|
|
762
|
-
function isHostEnvironment() {
|
|
763
|
-
if (typeof globalThis === "undefined") return false;
|
|
764
|
-
if (globalThis.__SENTRY_MICRO_FRONTEND_HOST__) return true;
|
|
765
|
-
if (globalThis.Sentry && typeof globalThis.Sentry.getCurrentHub === "function") return false;
|
|
766
|
-
return false;
|
|
767
|
-
}
|
|
768
|
-
/**
|
|
769
|
-
* Create a Sentry scope with backstageApp-specific context.
|
|
770
|
-
*
|
|
771
|
-
* Creates a new Sentry scope configured with micro frontend tags and context.
|
|
772
|
-
* Includes backstageApp tag, microFrontend context, and any additional tags provided.
|
|
773
|
-
*
|
|
774
|
-
* @param backstageApp - Name of the backstage app
|
|
775
|
-
* @param additionalTags - Optional additional tags to set on the scope
|
|
776
|
-
* @returns Sentry scope instance, or null if Sentry is not available
|
|
777
|
-
*/
|
|
778
|
-
function createBackstageScope(backstageApp, additionalTags) {
|
|
779
|
-
if (typeof globalThis === "undefined" || !globalThis.Sentry) return null;
|
|
780
|
-
const { Sentry } = globalThis;
|
|
781
|
-
if (!Sentry.Scope || typeof Sentry.Scope !== "function") return null;
|
|
782
|
-
try {
|
|
783
|
-
const scope = new Sentry.Scope();
|
|
784
|
-
scope.setTag("backstageApp", backstageApp);
|
|
785
|
-
scope.setTag("microFrontend", true);
|
|
786
|
-
scope.setContext("microFrontend", {
|
|
787
|
-
backstageApp,
|
|
788
|
-
isHost: globalThis.__SENTRY_MICRO_FRONTEND_HOST__ ?? false,
|
|
789
|
-
url: globalThis.location?.href ?? void 0
|
|
790
|
-
});
|
|
791
|
-
if (additionalTags) Object.entries(additionalTags).forEach(([key, value]) => {
|
|
792
|
-
scope.setTag(key, value);
|
|
793
|
-
});
|
|
794
|
-
return scope;
|
|
795
|
-
} catch (error) {
|
|
796
|
-
logError("[SentryMicroFrontendPlugin] Failed to create Backstage scope", { error });
|
|
797
|
-
return null;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* Check if Sentry is already initialized by a parent application.
|
|
802
|
-
*
|
|
803
|
-
* Verifies whether a parent Sentry instance exists in the global scope.
|
|
804
|
-
* Used to determine if the current micro frontend should use the parent's Sentry
|
|
805
|
-
* or initialize its own instance.
|
|
806
|
-
*
|
|
807
|
-
* @returns True if parent Sentry is available, false otherwise
|
|
808
|
-
*/
|
|
809
|
-
function hasParentSentry() {
|
|
810
|
-
if (typeof globalThis === "undefined") return false;
|
|
811
|
-
const { Sentry } = globalThis;
|
|
812
|
-
if (!Sentry) return false;
|
|
813
|
-
return [
|
|
814
|
-
"captureException",
|
|
815
|
-
"captureMessage",
|
|
816
|
-
"withScope"
|
|
817
|
-
].every((method) => typeof Sentry[method] === "function");
|
|
818
|
-
}
|
|
819
|
-
/**
|
|
820
|
-
* Get the parent Sentry instance if available.
|
|
821
|
-
*
|
|
822
|
-
* Returns the global Sentry instance if it exists and has been initialized
|
|
823
|
-
* by a parent application. Returns null if no parent Sentry is available.
|
|
824
|
-
*
|
|
825
|
-
* @returns Parent Sentry SDK instance, or null if not available
|
|
826
|
-
*/
|
|
827
|
-
function getParentSentry() {
|
|
828
|
-
if (hasParentSentry()) return globalThis.Sentry;
|
|
829
|
-
return null;
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* Mark the current environment as a host.
|
|
833
|
-
*
|
|
834
|
-
* Sets global flags indicating that this application is acting as a host
|
|
835
|
-
* for micro frontends. This affects how Sentry events are routed and tagged.
|
|
836
|
-
*
|
|
837
|
-
* @param backstageApp - Optional backstage app name to set
|
|
838
|
-
*/
|
|
839
|
-
function markAsHost(backstageApp) {
|
|
840
|
-
if (typeof globalThis !== "undefined") {
|
|
841
|
-
globalThis.__SENTRY_MICRO_FRONTEND_HOST__ = true;
|
|
842
|
-
if (backstageApp) {
|
|
843
|
-
globalThis.__SENTRY_MICRO_FRONTEND_APP__ = backstageApp;
|
|
844
|
-
globalThis.__SENTRY_MICRO_FRONTEND_ZONE__ = backstageApp;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* Ensure only one Sentry initialization happens (thread-safe).
|
|
850
|
-
*
|
|
851
|
-
* Prevents multiple Sentry initializations using global state tracking.
|
|
852
|
-
* Uses timestamps and unique IDs to detect concurrent initialization attempts.
|
|
853
|
-
* Throws an error if Sentry is already initialized or if concurrent initialization is detected.
|
|
854
|
-
*
|
|
855
|
-
* @throws Error if Sentry is already initialized or concurrent initialization detected
|
|
856
|
-
*/
|
|
857
|
-
function ensureSingleInit() {
|
|
858
|
-
const initKey = "__SENTRY_INIT_STATE__";
|
|
859
|
-
const now = Date.now();
|
|
860
|
-
if (typeof globalThis !== "undefined") {
|
|
861
|
-
const globalState = globalThis[initKey];
|
|
862
|
-
if (globalState) {
|
|
863
|
-
const { status, timestamp, id } = globalState;
|
|
864
|
-
if (status === "initialized") throw new Error("Sentry has already been initialized! Use hasParentSentry() to check before initializing.");
|
|
865
|
-
if (status === "initializing" && now - timestamp < 5e3) throw new Error(`Sentry initialization already in progress (started ${now - timestamp}ms ago by ${id})`);
|
|
866
|
-
}
|
|
867
|
-
const initId = `${now}-${Math.random().toString(36).substr(2, 9)}`;
|
|
868
|
-
globalThis[initKey] = {
|
|
869
|
-
status: "initializing",
|
|
870
|
-
timestamp: now,
|
|
871
|
-
id: initId
|
|
872
|
-
};
|
|
873
|
-
if (globalThis[initKey].id !== initId) throw new Error("Concurrent Sentry initialization detected");
|
|
874
|
-
globalThis[initKey] = {
|
|
875
|
-
status: "initialized",
|
|
876
|
-
timestamp: now,
|
|
877
|
-
id: initId
|
|
878
|
-
};
|
|
879
|
-
globalThis.__SENTRY_INITIALIZED__ = true;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
//#endregion
|
|
884
|
-
//#region src/plugins/sentry-microfrontend/plugin.ts
|
|
885
|
-
/**
|
|
886
|
-
* @fileoverview Sentry Micro Frontend Plugin
|
|
887
|
-
* Sentry Micro Frontend Plugin
|
|
888
|
-
*
|
|
889
|
-
* Extends the base Sentry plugin with micro frontend-specific functionality
|
|
890
|
-
*/
|
|
891
|
-
/**
|
|
892
|
-
* Sentry plugin optimized for micro frontend architectures
|
|
893
|
-
*/
|
|
894
|
-
/**
|
|
895
|
-
* Sentry plugin optimized for micro frontend architectures.
|
|
896
|
-
*
|
|
897
|
-
* Extends SentryPlugin with micro frontend-specific features:
|
|
898
|
-
* - Host/child/standalone mode detection
|
|
899
|
-
* - Multiplexed transport for routing events to different Sentry projects
|
|
900
|
-
* - Backstage app context management
|
|
901
|
-
* - Parent Sentry instance detection and reuse
|
|
902
|
-
*/
|
|
903
|
-
var SentryMicroFrontendPlugin = class SentryMicroFrontendPlugin extends SentryPlugin {
|
|
904
|
-
mode;
|
|
905
|
-
backstageApp;
|
|
906
|
-
parentSentry;
|
|
907
|
-
backstageScope;
|
|
908
|
-
microFrontendConfig;
|
|
909
|
-
eventProcessorCleanup;
|
|
910
|
-
/**
|
|
911
|
-
* Create a new SentryMicroFrontendPlugin instance.
|
|
912
|
-
*
|
|
913
|
-
* @param config - Sentry micro frontend plugin configuration
|
|
914
|
-
*/
|
|
915
|
-
constructor(config = {}) {
|
|
916
|
-
const mode = SentryMicroFrontendPlugin.determineMode(config);
|
|
917
|
-
const baseConfig = SentryMicroFrontendPlugin.prepareConfig(config, mode);
|
|
918
|
-
super(baseConfig);
|
|
919
|
-
this.mode = mode;
|
|
920
|
-
this.microFrontendConfig = config;
|
|
921
|
-
this.backstageApp = config.backstageApp ?? detectCurrentBackstageApp(config.backstageApps);
|
|
922
|
-
if (this.mode === "child") {
|
|
923
|
-
const parent = getParentSentry();
|
|
924
|
-
if (parent) {
|
|
925
|
-
this.parentSentry = parent;
|
|
926
|
-
this.enabled = true;
|
|
927
|
-
if (this.backstageApp && this.parentSentry.Scope) this.backstageScope = createBackstageScope(this.backstageApp, config.globalTags);
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
if (this.mode === "host") markAsHost(this.backstageApp);
|
|
931
|
-
}
|
|
932
|
-
/**
|
|
933
|
-
* Determine the operation mode based on configuration and environment.
|
|
934
|
-
*
|
|
935
|
-
* @param config - Plugin configuration
|
|
936
|
-
* @returns Operation mode ('host', 'child', or 'standalone')
|
|
937
|
-
*/
|
|
938
|
-
static determineMode(config) {
|
|
939
|
-
if (config.isHost) return "host";
|
|
940
|
-
if (config.detectParent !== false && hasParentSentry()) return "child";
|
|
941
|
-
return "standalone";
|
|
942
|
-
}
|
|
943
|
-
/**
|
|
944
|
-
* Prepare configuration based on operation mode.
|
|
945
|
-
*
|
|
946
|
-
* Adjusts configuration settings based on whether running as host, child, or standalone.
|
|
947
|
-
*
|
|
948
|
-
* @param config - Original plugin configuration
|
|
949
|
-
* @param mode - Determined operation mode
|
|
950
|
-
* @returns Prepared configuration object
|
|
951
|
-
*/
|
|
952
|
-
static prepareConfig(config, mode) {
|
|
953
|
-
const preparedConfig = { ...config };
|
|
954
|
-
if (mode === "child") preparedConfig.enabled = false;
|
|
955
|
-
else if (mode === "host" && config.backstageApps && config.useMultiplexedTransport !== false) {}
|
|
956
|
-
return preparedConfig;
|
|
957
|
-
}
|
|
958
|
-
/**
|
|
959
|
-
* Initialize the plugin
|
|
960
|
-
*/
|
|
961
|
-
async initialize(config) {
|
|
962
|
-
const mergedConfig = {
|
|
963
|
-
...this.microFrontendConfig,
|
|
964
|
-
...config
|
|
965
|
-
};
|
|
966
|
-
if (this.mode === "child") {
|
|
967
|
-
if (this.parentSentry) {
|
|
968
|
-
this.client = this.parentSentry;
|
|
969
|
-
this.initialized = true;
|
|
970
|
-
if (this.backstageApp && mergedConfig.addBackstageContext !== false) this.configureParentSentry();
|
|
971
|
-
}
|
|
972
|
-
return;
|
|
973
|
-
}
|
|
974
|
-
if (mergedConfig.preventDuplicateInit !== false) try {
|
|
975
|
-
ensureSingleInit();
|
|
976
|
-
} catch (error) {
|
|
977
|
-
logError("Sentry initialization prevented", { error });
|
|
978
|
-
this.enabled = false;
|
|
979
|
-
return;
|
|
980
|
-
}
|
|
981
|
-
await super.initialize(mergedConfig);
|
|
982
|
-
if (this.mode === "host" && this.client && mergedConfig.backstageApps) this.setupHostMode(mergedConfig);
|
|
983
|
-
}
|
|
984
|
-
/**
|
|
985
|
-
* Configure parent Sentry instance for child mode
|
|
986
|
-
*/
|
|
987
|
-
configureParentSentry() {
|
|
988
|
-
if (!this.parentSentry || !this.backstageApp) {
|
|
989
|
-
logWarn("[SentryMicroFrontendPlugin] Cannot configure parent Sentry: missing parentSentry or backstageApp");
|
|
990
|
-
return;
|
|
991
|
-
}
|
|
992
|
-
try {
|
|
993
|
-
const processor = (event) => {
|
|
994
|
-
try {
|
|
995
|
-
if (this.shouldProcessEvent(event)) enhanceEventWithBackstageApp(event, this.backstageApp ?? "", {
|
|
996
|
-
mode: this.mode,
|
|
997
|
-
plugin: "SentryMicroFrontendPlugin"
|
|
998
|
-
});
|
|
999
|
-
} catch (error) {
|
|
1000
|
-
logError("[SentryMicroFrontendPlugin] Error processing event", {
|
|
1001
|
-
error,
|
|
1002
|
-
event
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1005
|
-
return event;
|
|
1006
|
-
};
|
|
1007
|
-
if (typeof this.parentSentry.addEventProcessor === "function") {
|
|
1008
|
-
this.parentSentry.addEventProcessor(processor);
|
|
1009
|
-
this.eventProcessorCleanup = () => {};
|
|
1010
|
-
} else logWarn("[SentryMicroFrontendPlugin] Parent Sentry does not support addEventProcessor");
|
|
1011
|
-
} catch (error) {
|
|
1012
|
-
logError("[SentryMicroFrontendPlugin] Failed to configure parent Sentry", { error });
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
/**
|
|
1016
|
-
* Set up host mode with multiplexed transport
|
|
1017
|
-
*/
|
|
1018
|
-
setupHostMode(config) {
|
|
1019
|
-
if (!config.backstageApps || !this.client) {
|
|
1020
|
-
logWarn("[SentryMicroFrontendPlugin] Cannot setup host mode: missing backstageApps or client");
|
|
1021
|
-
return;
|
|
1022
|
-
}
|
|
1023
|
-
try {
|
|
1024
|
-
const transport = createMultiplexedTransport(config.backstageApps, config.fallbackDsn ?? config.dsn, this.client);
|
|
1025
|
-
if (transport && typeof this.client.init === "function") {
|
|
1026
|
-
const currentOptions = typeof this.client.getOptions === "function" ? this.client.getOptions() : {};
|
|
1027
|
-
this.client.init({
|
|
1028
|
-
...currentOptions,
|
|
1029
|
-
transport,
|
|
1030
|
-
beforeSend: createBackstageBeforeSend(this.backstageApp ?? "main", config.beforeSend)
|
|
1031
|
-
});
|
|
1032
|
-
} else logWarn("[SentryMicroFrontendPlugin] Client does not support init method or transport creation failed");
|
|
1033
|
-
} catch (error) {
|
|
1034
|
-
logError("[SentryMicroFrontendPlugin] Failed to setup host mode", { error });
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
/**
|
|
1038
|
-
* Check if we should process this event
|
|
1039
|
-
*/
|
|
1040
|
-
shouldProcessEvent(event) {
|
|
1041
|
-
if (event.tags?.microFrontendProcessed) return false;
|
|
1042
|
-
if (this.backstageApp && event.tags?.backstageApp && event.tags.backstageApp !== this.backstageApp) return false;
|
|
1043
|
-
return true;
|
|
1044
|
-
}
|
|
1045
|
-
/**
|
|
1046
|
-
* Capture an exception with backstageApp context
|
|
1047
|
-
*/
|
|
1048
|
-
captureException(error, context) {
|
|
1049
|
-
if (!this.enabled) return;
|
|
1050
|
-
try {
|
|
1051
|
-
if (this.mode === "child" && this.parentSentry && this.backstageScope) if (typeof this.parentSentry.withScope === "function") this.parentSentry.withScope((scope) => {
|
|
1052
|
-
try {
|
|
1053
|
-
if (this.backstageScope && typeof scope.setTag === "function") {
|
|
1054
|
-
scope.setTag("backstageApp", this.backstageApp ?? "unknown");
|
|
1055
|
-
scope.setTag("microFrontend", true);
|
|
1056
|
-
scope.setContext("microFrontend", {
|
|
1057
|
-
backstageApp: this.backstageApp,
|
|
1058
|
-
mode: this.mode
|
|
1059
|
-
});
|
|
1060
|
-
}
|
|
1061
|
-
if (context && typeof scope.setContext === "function") scope.setContext("additional", context);
|
|
1062
|
-
if (this.parentSentry && typeof this.parentSentry.captureException === "function") this.parentSentry.captureException(error);
|
|
1063
|
-
} catch (scopeError) {
|
|
1064
|
-
logError("[SentryMicroFrontendPlugin] Error in scope callback", { error: scopeError });
|
|
1065
|
-
}
|
|
1066
|
-
});
|
|
1067
|
-
else logWarn("[SentryMicroFrontendPlugin] Parent Sentry does not support withScope");
|
|
1068
|
-
else {
|
|
1069
|
-
const enhancedContext = {
|
|
1070
|
-
...context,
|
|
1071
|
-
microFrontend: {
|
|
1072
|
-
backstageApp: this.backstageApp,
|
|
1073
|
-
mode: this.mode
|
|
1074
|
-
}
|
|
1075
|
-
};
|
|
1076
|
-
super.captureException(error, enhancedContext);
|
|
1077
|
-
}
|
|
1078
|
-
} catch (captureError) {
|
|
1079
|
-
logError("[SentryMicroFrontendPlugin] Failed to capture exception", { error: captureError });
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
/**
|
|
1083
|
-
* Capture a message with backstageApp context
|
|
1084
|
-
*/
|
|
1085
|
-
captureMessage(message, level = "info", context) {
|
|
1086
|
-
if (!this.enabled) return;
|
|
1087
|
-
try {
|
|
1088
|
-
const sentryLevel = mapLogLevelToSentrySeverity(level);
|
|
1089
|
-
if (this.mode === "child" && this.parentSentry && this.backstageScope) if (typeof this.parentSentry.withScope === "function") this.parentSentry.withScope((scope) => {
|
|
1090
|
-
try {
|
|
1091
|
-
if (this.backstageScope && typeof scope.setTag === "function") {
|
|
1092
|
-
scope.setTag("backstageApp", this.backstageApp ?? "unknown");
|
|
1093
|
-
scope.setTag("microFrontend", true);
|
|
1094
|
-
if (typeof scope.setContext === "function") scope.setContext("microFrontend", {
|
|
1095
|
-
backstageApp: this.backstageApp,
|
|
1096
|
-
mode: this.mode
|
|
1097
|
-
});
|
|
1098
|
-
}
|
|
1099
|
-
if (context && typeof scope.setContext === "function") scope.setContext("additional", context);
|
|
1100
|
-
if (this.parentSentry && typeof this.parentSentry.captureMessage === "function") this.parentSentry.captureMessage(message, sentryLevel);
|
|
1101
|
-
} catch (scopeError) {
|
|
1102
|
-
logError("[SentryMicroFrontendPlugin] Error in scope callback", { error: scopeError });
|
|
1103
|
-
}
|
|
1104
|
-
});
|
|
1105
|
-
else logWarn("[SentryMicroFrontendPlugin] Parent Sentry does not support withScope");
|
|
1106
|
-
else super.captureMessage(message, level, context);
|
|
1107
|
-
} catch (captureError) {
|
|
1108
|
-
logError("[SentryMicroFrontendPlugin] Failed to capture message", { error: captureError });
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
/**
|
|
1112
|
-
* Get the current operation mode
|
|
1113
|
-
*/
|
|
1114
|
-
getMode() {
|
|
1115
|
-
return this.mode;
|
|
1116
|
-
}
|
|
1117
|
-
/**
|
|
1118
|
-
* Get the current Backstage app identifier
|
|
1119
|
-
*/
|
|
1120
|
-
getBackstageApp() {
|
|
1121
|
-
return this.backstageApp;
|
|
1122
|
-
}
|
|
1123
|
-
/**
|
|
1124
|
-
* @deprecated Use getBackstageApp instead.
|
|
1125
|
-
*/
|
|
1126
|
-
getZone() {
|
|
1127
|
-
return this.getBackstageApp();
|
|
1128
|
-
}
|
|
1129
|
-
/**
|
|
1130
|
-
* Get debug information about the plugin state
|
|
1131
|
-
*/
|
|
1132
|
-
getDebugInfo() {
|
|
1133
|
-
return {
|
|
1134
|
-
mode: this.mode,
|
|
1135
|
-
backstageApp: this.backstageApp,
|
|
1136
|
-
enabled: this.enabled,
|
|
1137
|
-
initialized: this.initialized,
|
|
1138
|
-
hasParentSentry: this.mode === "child" && Boolean(this.parentSentry),
|
|
1139
|
-
clientType: this.client ? this.client.constructor.name : "none"
|
|
1140
|
-
};
|
|
1141
|
-
}
|
|
1142
|
-
/**
|
|
1143
|
-
* Clean up the plugin and release resources
|
|
1144
|
-
*/
|
|
1145
|
-
async cleanup() {
|
|
1146
|
-
try {
|
|
1147
|
-
if (this.eventProcessorCleanup) {
|
|
1148
|
-
this.eventProcessorCleanup();
|
|
1149
|
-
this.eventProcessorCleanup = void 0;
|
|
1150
|
-
}
|
|
1151
|
-
if (this.backstageScope && typeof this.backstageScope.clear === "function") this.backstageScope.clear();
|
|
1152
|
-
this.backstageScope = void 0;
|
|
1153
|
-
this.parentSentry = void 0;
|
|
1154
|
-
await super.cleanup();
|
|
1155
|
-
this.initialized = false;
|
|
1156
|
-
this.enabled = false;
|
|
1157
|
-
logDebug("[SentryMicroFrontendPlugin] Cleanup completed");
|
|
1158
|
-
} catch (error) {
|
|
1159
|
-
logError("[SentryMicroFrontendPlugin] Error during cleanup", { error });
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
/**
|
|
1163
|
-
* Destroy the plugin (alias for cleanup)
|
|
1164
|
-
*/
|
|
1165
|
-
async destroy() {
|
|
1166
|
-
await this.cleanup();
|
|
1167
|
-
}
|
|
1168
|
-
};
|
|
1169
|
-
/**
|
|
1170
|
-
* Factory function to create a Sentry Micro Frontend plugin.
|
|
1171
|
-
*
|
|
1172
|
-
* Creates a configured SentryMicroFrontendPlugin instance with micro frontend-specific
|
|
1173
|
-
* features like multiplexed transport and backstage app routing.
|
|
1174
|
-
*
|
|
1175
|
-
* @param config - Optional Sentry micro frontend plugin configuration
|
|
1176
|
-
* @returns SentryMicroFrontendPlugin instance
|
|
1177
|
-
*
|
|
1178
|
-
* @example
|
|
1179
|
-
* ```typescript
|
|
1180
|
-
* const sentry = createSentryMicroFrontendPlugin({
|
|
1181
|
-
* dsn: 'https://...',
|
|
1182
|
-
* backstage: [
|
|
1183
|
-
* { name: 'admin', dsn: 'https://admin-dsn...' },
|
|
1184
|
-
* { name: 'dashboard', dsn: 'https://dashboard-dsn...' },
|
|
1185
|
-
* ],
|
|
1186
|
-
* });
|
|
1187
|
-
* ```
|
|
1188
|
-
*/
|
|
1189
|
-
const createSentryMicroFrontendPlugin = (config) => {
|
|
1190
|
-
return new SentryMicroFrontendPlugin(config);
|
|
1191
|
-
};
|
|
1192
|
-
|
|
1193
|
-
//#endregion
|
|
1194
|
-
export { isHostEnvironment as a, detectCurrentBackstageApp as i, createSentryMicroFrontendPlugin as n, createMultiplexedTransport as o, createBackstageScope as r, SentryMicroFrontendPlugin as t };
|
|
1195
|
-
//# sourceMappingURL=plugin-CxeJHHeJ.mjs.map
|