@sentry/browser 8.38.0 → 8.39.0-beta.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.
Files changed (29) hide show
  1. package/build/npm/cjs/index.js +3 -0
  2. package/build/npm/cjs/index.js.map +1 -1
  3. package/build/npm/cjs/integrations/featureFlags/launchdarkly/integration.js +71 -0
  4. package/build/npm/cjs/integrations/featureFlags/launchdarkly/integration.js.map +1 -0
  5. package/build/npm/cjs/utils/featureFlags.js +64 -0
  6. package/build/npm/cjs/utils/featureFlags.js.map +1 -0
  7. package/build/npm/esm/index.js +1 -0
  8. package/build/npm/esm/index.js.map +1 -1
  9. package/build/npm/esm/integrations/featureFlags/launchdarkly/integration.js +68 -0
  10. package/build/npm/esm/integrations/featureFlags/launchdarkly/integration.js.map +1 -0
  11. package/build/npm/esm/package.json +1 -1
  12. package/build/npm/esm/utils/featureFlags.js +61 -0
  13. package/build/npm/esm/utils/featureFlags.js.map +1 -0
  14. package/build/npm/types/index.d.ts +1 -0
  15. package/build/npm/types/index.d.ts.map +1 -1
  16. package/build/npm/types/integrations/featureFlags/launchdarkly/index.d.ts +2 -0
  17. package/build/npm/types/integrations/featureFlags/launchdarkly/index.d.ts.map +1 -0
  18. package/build/npm/types/integrations/featureFlags/launchdarkly/integration.d.ts +25 -0
  19. package/build/npm/types/integrations/featureFlags/launchdarkly/integration.d.ts.map +1 -0
  20. package/build/npm/types/integrations/featureFlags/launchdarkly/types.d.ts +44 -0
  21. package/build/npm/types/integrations/featureFlags/launchdarkly/types.d.ts.map +1 -0
  22. package/build/npm/types/utils/featureFlags.d.ts +26 -0
  23. package/build/npm/types/utils/featureFlags.d.ts.map +1 -0
  24. package/build/npm/types-ts3.8/index.d.ts +1 -0
  25. package/build/npm/types-ts3.8/integrations/featureFlags/launchdarkly/index.d.ts +2 -0
  26. package/build/npm/types-ts3.8/integrations/featureFlags/launchdarkly/integration.d.ts +25 -0
  27. package/build/npm/types-ts3.8/integrations/featureFlags/launchdarkly/types.d.ts +44 -0
  28. package/build/npm/types-ts3.8/utils/featureFlags.d.ts +26 -0
  29. package/package.json +9 -9
@@ -28,6 +28,7 @@ const browserTracingIntegration = require('./tracing/browserTracingIntegration.j
28
28
  const offline = require('./transports/offline.js');
29
29
  const integration = require('./profiling/integration.js');
30
30
  const spotlight = require('./integrations/spotlight.js');
31
+ const integration$1 = require('./integrations/featureFlags/launchdarkly/integration.js');
31
32
 
32
33
 
33
34
 
@@ -143,4 +144,6 @@ exports.startBrowserTracingPageLoadSpan = browserTracingIntegration.startBrowser
143
144
  exports.makeBrowserOfflineTransport = offline.makeBrowserOfflineTransport;
144
145
  exports.browserProfilingIntegration = integration.browserProfilingIntegration;
145
146
  exports.spotlightBrowserIntegration = spotlight.spotlightBrowserIntegration;
147
+ exports.buildLaunchDarklyFlagUsedHandler = integration$1.buildLaunchDarklyFlagUsedHandler;
148
+ exports.launchDarklyIntegration = integration$1.launchDarklyIntegration;
146
149
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,71 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ const core = require('@sentry/core');
4
+ const featureFlags = require('../../../utils/featureFlags.js');
5
+
6
+ /**
7
+ * Sentry integration for capturing feature flags from LaunchDarkly.
8
+ *
9
+ * See the [feature flag documentation](https://develop.sentry.dev/sdk/expected-features/#feature-flags) for more information.
10
+ *
11
+ * @example
12
+ * ```
13
+ * import * as Sentry from '@sentry/browser';
14
+ * import {launchDarklyIntegration, buildLaunchDarklyFlagUsedInspector} from '@sentry/browser';
15
+ * import * as LaunchDarkly from 'launchdarkly-js-client-sdk';
16
+ *
17
+ * Sentry.init(..., integrations: [launchDarklyIntegration()])
18
+ * const ldClient = LaunchDarkly.initialize(..., {inspectors: [buildLaunchDarklyFlagUsedHandler()]});
19
+ * ```
20
+ */
21
+ const launchDarklyIntegration = core.defineIntegration(() => {
22
+ return {
23
+ name: 'LaunchDarkly',
24
+
25
+ processEvent(event, _hint, _client) {
26
+ const scope = core.getCurrentScope();
27
+ const flagContext = scope.getScopeData().contexts.flags;
28
+ const flagBuffer = flagContext ? flagContext.values : [];
29
+
30
+ if (event.contexts === undefined) {
31
+ event.contexts = {};
32
+ }
33
+ event.contexts.flags = { values: [...flagBuffer] };
34
+ return event;
35
+ },
36
+ };
37
+ }) ;
38
+
39
+ /**
40
+ * LaunchDarkly hook that listens for flag evaluations and updates the `flags`
41
+ * context in our Sentry scope. This needs to be registered as an
42
+ * 'inspector' in LaunchDarkly initialize() options, separately from
43
+ * `launchDarklyIntegration`. Both are needed to collect feature flags on error.
44
+ */
45
+ function buildLaunchDarklyFlagUsedHandler() {
46
+ return {
47
+ name: 'sentry-flag-auditor',
48
+ type: 'flag-used',
49
+
50
+ synchronous: true,
51
+
52
+ /**
53
+ * Handle a flag evaluation by storing its name and value on the current scope.
54
+ */
55
+ method: (flagKey, flagDetail, _context) => {
56
+ if (typeof flagDetail.value === 'boolean') {
57
+ const scopeContexts = core.getCurrentScope().getScopeData().contexts;
58
+ if (!scopeContexts.flags) {
59
+ scopeContexts.flags = { values: [] };
60
+ }
61
+ const flagBuffer = scopeContexts.flags.values;
62
+ featureFlags.insertToFlagBuffer(flagBuffer, flagKey, flagDetail.value);
63
+ }
64
+ return;
65
+ },
66
+ };
67
+ }
68
+
69
+ exports.buildLaunchDarklyFlagUsedHandler = buildLaunchDarklyFlagUsedHandler;
70
+ exports.launchDarklyIntegration = launchDarklyIntegration;
71
+ //# sourceMappingURL=integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.js","sources":["../../../../../../src/integrations/featureFlags/launchdarkly/integration.ts"],"sourcesContent":["import type { Client, Event, EventHint, IntegrationFn } from '@sentry/types';\nimport type { LDContext, LDEvaluationDetail, LDInspectionFlagUsedHandler } from './types';\n\nimport { defineIntegration, getCurrentScope } from '@sentry/core';\nimport { insertToFlagBuffer } from '../../../utils/featureFlags';\n\n/**\n * Sentry integration for capturing feature flags from LaunchDarkly.\n *\n * See the [feature flag documentation](https://develop.sentry.dev/sdk/expected-features/#feature-flags) for more information.\n *\n * @example\n * ```\n * import * as Sentry from '@sentry/browser';\n * import {launchDarklyIntegration, buildLaunchDarklyFlagUsedInspector} from '@sentry/browser';\n * import * as LaunchDarkly from 'launchdarkly-js-client-sdk';\n *\n * Sentry.init(..., integrations: [launchDarklyIntegration()])\n * const ldClient = LaunchDarkly.initialize(..., {inspectors: [buildLaunchDarklyFlagUsedHandler()]});\n * ```\n */\nexport const launchDarklyIntegration = defineIntegration(() => {\n return {\n name: 'LaunchDarkly',\n\n processEvent(event: Event, _hint: EventHint, _client: Client): Event {\n const scope = getCurrentScope();\n const flagContext = scope.getScopeData().contexts.flags;\n const flagBuffer = flagContext ? flagContext.values : [];\n\n if (event.contexts === undefined) {\n event.contexts = {};\n }\n event.contexts.flags = { values: [...flagBuffer] };\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * LaunchDarkly hook that listens for flag evaluations and updates the `flags`\n * context in our Sentry scope. This needs to be registered as an\n * 'inspector' in LaunchDarkly initialize() options, separately from\n * `launchDarklyIntegration`. Both are needed to collect feature flags on error.\n */\nexport function buildLaunchDarklyFlagUsedHandler(): LDInspectionFlagUsedHandler {\n return {\n name: 'sentry-flag-auditor',\n type: 'flag-used',\n\n synchronous: true,\n\n /**\n * Handle a flag evaluation by storing its name and value on the current scope.\n */\n method: (flagKey: string, flagDetail: LDEvaluationDetail, _context: LDContext) => {\n if (typeof flagDetail.value === 'boolean') {\n const scopeContexts = getCurrentScope().getScopeData().contexts;\n if (!scopeContexts.flags) {\n scopeContexts.flags = { values: [] };\n }\n const flagBuffer = scopeContexts.flags.values;\n insertToFlagBuffer(flagBuffer, flagKey, flagDetail.value);\n }\n return;\n },\n };\n}\n"],"names":["defineIntegration","getCurrentScope","insertToFlagBuffer"],"mappings":";;;;;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,uBAAwB,GAAEA,sBAAiB,CAAC,MAAM;AAC/D,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,cAAc;;AAExB,IAAI,YAAY,CAAC,KAAK,EAAS,KAAK,EAAa,OAAO,EAAiB;AACzE,MAAM,MAAM,KAAA,GAAQC,oBAAe,EAAE;AACrC,MAAM,MAAM,WAAY,GAAE,KAAK,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC,KAAK;AAC7D,MAAM,MAAM,UAAW,GAAE,WAAY,GAAE,WAAW,CAAC,MAAA,GAAS,EAAE;;AAE9D,MAAM,IAAI,KAAK,CAAC,QAAS,KAAI,SAAS,EAAE;AACxC,QAAQ,KAAK,CAAC,QAAS,GAAE,EAAE;AAC3B;AACA,MAAM,KAAK,CAAC,QAAQ,CAAC,KAAM,GAAE,EAAE,MAAM,EAAE,CAAC,GAAG,UAAU,GAAG;AACxD,MAAM,OAAO,KAAK;AAClB,KAAK;AACL,GAAG;AACH,CAAC,CAAE;;AAEH;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gCAAgC,GAAgC;AAChF,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,qBAAqB;AAC/B,IAAI,IAAI,EAAE,WAAW;;AAErB,IAAI,WAAW,EAAE,IAAI;;AAErB;AACA;AACA;AACA,IAAI,MAAM,EAAE,CAAC,OAAO,EAAU,UAAU,EAAsB,QAAQ,KAAgB;AACtF,MAAM,IAAI,OAAO,UAAU,CAAC,KAAM,KAAI,SAAS,EAAE;AACjD,QAAQ,MAAM,aAAc,GAAEA,oBAAe,EAAE,CAAC,YAAY,EAAE,CAAC,QAAQ;AACvE,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;AAClC,UAAU,aAAa,CAAC,KAAM,GAAE,EAAE,MAAM,EAAE,EAAC,EAAG;AAC9C;AACA,QAAQ,MAAM,UAAW,GAAE,aAAa,CAAC,KAAK,CAAC,MAAM;AACrD,QAAQC,+BAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC;AACjE;AACA,MAAM;AACN,KAAK;AACL,GAAG;AACH;;;;;"}
@@ -0,0 +1,64 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ const utils = require('@sentry/utils');
4
+ const debugBuild = require('../debug-build.js');
5
+
6
+ /**
7
+ * Ordered LRU cache for storing feature flags in the scope context. The name
8
+ * of each flag in the buffer is unique, and the output of getAll() is ordered
9
+ * from oldest to newest.
10
+ */
11
+
12
+ /**
13
+ * Max size of the LRU flag buffer stored in Sentry scope and event contexts.
14
+ */
15
+ const FLAG_BUFFER_SIZE = 100;
16
+
17
+ /**
18
+ * Insert into a FeatureFlag array while maintaining ordered LRU properties. Not
19
+ * thread-safe. After inserting:
20
+ * - `flags` is sorted in order of recency, with the newest flag at the end.
21
+ * - No other flags with the same name exist in `flags`.
22
+ * - The length of `flags` does not exceed `maxSize`. The oldest flag is evicted
23
+ * as needed.
24
+ *
25
+ * @param flags The array to insert into.
26
+ * @param name Name of the feature flag to insert.
27
+ * @param value Value of the feature flag.
28
+ * @param maxSize Max number of flags the buffer should store. It's recommended
29
+ * to keep this consistent across insertions. Default is DEFAULT_MAX_SIZE
30
+ */
31
+ function insertToFlagBuffer(
32
+ flags,
33
+ name,
34
+ value,
35
+ maxSize = FLAG_BUFFER_SIZE,
36
+ ) {
37
+ if (flags.length > maxSize) {
38
+ debugBuild.DEBUG_BUILD && utils.logger.error(`[Feature Flags] insertToFlagBuffer called on a buffer larger than maxSize=${maxSize}`);
39
+ return;
40
+ }
41
+
42
+ // Check if the flag is already in the buffer - O(n)
43
+ const index = flags.findIndex(f => f.flag === name);
44
+
45
+ if (index !== -1) {
46
+ // The flag was found, remove it from its current position - O(n)
47
+ flags.splice(index, 1);
48
+ }
49
+
50
+ if (flags.length === maxSize) {
51
+ // If at capacity, pop the earliest flag - O(n)
52
+ flags.shift();
53
+ }
54
+
55
+ // Push the flag to the end - O(1)
56
+ flags.push({
57
+ flag: name,
58
+ result: value,
59
+ });
60
+ }
61
+
62
+ exports.FLAG_BUFFER_SIZE = FLAG_BUFFER_SIZE;
63
+ exports.insertToFlagBuffer = insertToFlagBuffer;
64
+ //# sourceMappingURL=featureFlags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"featureFlags.js","sources":["../../../../src/utils/featureFlags.ts"],"sourcesContent":["import type { FeatureFlag } from '@sentry/types';\nimport { logger } from '@sentry/utils';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/**\n * Ordered LRU cache for storing feature flags in the scope context. The name\n * of each flag in the buffer is unique, and the output of getAll() is ordered\n * from oldest to newest.\n */\n\n/**\n * Max size of the LRU flag buffer stored in Sentry scope and event contexts.\n */\nexport const FLAG_BUFFER_SIZE = 100;\n\n/**\n * Insert into a FeatureFlag array while maintaining ordered LRU properties. Not\n * thread-safe. After inserting:\n * - `flags` is sorted in order of recency, with the newest flag at the end.\n * - No other flags with the same name exist in `flags`.\n * - The length of `flags` does not exceed `maxSize`. The oldest flag is evicted\n * as needed.\n *\n * @param flags The array to insert into.\n * @param name Name of the feature flag to insert.\n * @param value Value of the feature flag.\n * @param maxSize Max number of flags the buffer should store. It's recommended\n * to keep this consistent across insertions. Default is DEFAULT_MAX_SIZE\n */\nexport function insertToFlagBuffer(\n flags: FeatureFlag[],\n name: string,\n value: boolean,\n maxSize: number = FLAG_BUFFER_SIZE,\n): void {\n if (flags.length > maxSize) {\n DEBUG_BUILD && logger.error(`[Feature Flags] insertToFlagBuffer called on a buffer larger than maxSize=${maxSize}`);\n return;\n }\n\n // Check if the flag is already in the buffer - O(n)\n const index = flags.findIndex(f => f.flag === name);\n\n if (index !== -1) {\n // The flag was found, remove it from its current position - O(n)\n flags.splice(index, 1);\n }\n\n if (flags.length === maxSize) {\n // If at capacity, pop the earliest flag - O(n)\n flags.shift();\n }\n\n // Push the flag to the end - O(1)\n flags.push({\n flag: name,\n result: value,\n });\n}\n"],"names":["DEBUG_BUILD","logger"],"mappings":";;;;;AAIA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACO,MAAM,gBAAiB,GAAE;;AAEhC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,kBAAkB;AAClC,EAAE,KAAK;AACP,EAAE,IAAI;AACN,EAAE,KAAK;AACP,EAAE,OAAO,GAAW,gBAAgB;AACpC,EAAQ;AACR,EAAE,IAAI,KAAK,CAAC,MAAO,GAAE,OAAO,EAAE;AAC9B,IAAIA,sBAAA,IAAeC,YAAM,CAAC,KAAK,CAAC,CAAC,0EAA0E,EAAE,OAAO,CAAC,CAAA,CAAA;AACA,IAAA;AACA;;AAEA;AACA,EAAA,MAAA,KAAA,GAAA,KAAA,CAAA,SAAA,CAAA,CAAA,IAAA,CAAA,CAAA,IAAA,KAAA,IAAA,CAAA;;AAEA,EAAA,IAAA,KAAA,KAAA,CAAA,CAAA,EAAA;AACA;AACA,IAAA,KAAA,CAAA,MAAA,CAAA,KAAA,EAAA,CAAA,CAAA;AACA;;AAEA,EAAA,IAAA,KAAA,CAAA,MAAA,KAAA,OAAA,EAAA;AACA;AACA,IAAA,KAAA,CAAA,KAAA,EAAA;AACA;;AAEA;AACA,EAAA,KAAA,CAAA,IAAA,CAAA;AACA,IAAA,IAAA,EAAA,IAAA;AACA,IAAA,MAAA,EAAA,KAAA;AACA,GAAA,CAAA;AACA;;;;;"}
@@ -26,4 +26,5 @@ export { browserTracingIntegration, startBrowserTracingNavigationSpan, startBrow
26
26
  export { makeBrowserOfflineTransport } from './transports/offline.js';
27
27
  export { browserProfilingIntegration } from './profiling/integration.js';
28
28
  export { spotlightBrowserIntegration } from './integrations/spotlight.js';
29
+ export { buildLaunchDarklyFlagUsedHandler, launchDarklyIntegration } from './integrations/featureFlags/launchdarkly/integration.js';
29
30
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,68 @@
1
+ import { defineIntegration, getCurrentScope } from '@sentry/core';
2
+ import { insertToFlagBuffer } from '../../../utils/featureFlags.js';
3
+
4
+ /**
5
+ * Sentry integration for capturing feature flags from LaunchDarkly.
6
+ *
7
+ * See the [feature flag documentation](https://develop.sentry.dev/sdk/expected-features/#feature-flags) for more information.
8
+ *
9
+ * @example
10
+ * ```
11
+ * import * as Sentry from '@sentry/browser';
12
+ * import {launchDarklyIntegration, buildLaunchDarklyFlagUsedInspector} from '@sentry/browser';
13
+ * import * as LaunchDarkly from 'launchdarkly-js-client-sdk';
14
+ *
15
+ * Sentry.init(..., integrations: [launchDarklyIntegration()])
16
+ * const ldClient = LaunchDarkly.initialize(..., {inspectors: [buildLaunchDarklyFlagUsedHandler()]});
17
+ * ```
18
+ */
19
+ const launchDarklyIntegration = defineIntegration(() => {
20
+ return {
21
+ name: 'LaunchDarkly',
22
+
23
+ processEvent(event, _hint, _client) {
24
+ const scope = getCurrentScope();
25
+ const flagContext = scope.getScopeData().contexts.flags;
26
+ const flagBuffer = flagContext ? flagContext.values : [];
27
+
28
+ if (event.contexts === undefined) {
29
+ event.contexts = {};
30
+ }
31
+ event.contexts.flags = { values: [...flagBuffer] };
32
+ return event;
33
+ },
34
+ };
35
+ }) ;
36
+
37
+ /**
38
+ * LaunchDarkly hook that listens for flag evaluations and updates the `flags`
39
+ * context in our Sentry scope. This needs to be registered as an
40
+ * 'inspector' in LaunchDarkly initialize() options, separately from
41
+ * `launchDarklyIntegration`. Both are needed to collect feature flags on error.
42
+ */
43
+ function buildLaunchDarklyFlagUsedHandler() {
44
+ return {
45
+ name: 'sentry-flag-auditor',
46
+ type: 'flag-used',
47
+
48
+ synchronous: true,
49
+
50
+ /**
51
+ * Handle a flag evaluation by storing its name and value on the current scope.
52
+ */
53
+ method: (flagKey, flagDetail, _context) => {
54
+ if (typeof flagDetail.value === 'boolean') {
55
+ const scopeContexts = getCurrentScope().getScopeData().contexts;
56
+ if (!scopeContexts.flags) {
57
+ scopeContexts.flags = { values: [] };
58
+ }
59
+ const flagBuffer = scopeContexts.flags.values;
60
+ insertToFlagBuffer(flagBuffer, flagKey, flagDetail.value);
61
+ }
62
+ return;
63
+ },
64
+ };
65
+ }
66
+
67
+ export { buildLaunchDarklyFlagUsedHandler, launchDarklyIntegration };
68
+ //# sourceMappingURL=integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.js","sources":["../../../../../../src/integrations/featureFlags/launchdarkly/integration.ts"],"sourcesContent":["import type { Client, Event, EventHint, IntegrationFn } from '@sentry/types';\nimport type { LDContext, LDEvaluationDetail, LDInspectionFlagUsedHandler } from './types';\n\nimport { defineIntegration, getCurrentScope } from '@sentry/core';\nimport { insertToFlagBuffer } from '../../../utils/featureFlags';\n\n/**\n * Sentry integration for capturing feature flags from LaunchDarkly.\n *\n * See the [feature flag documentation](https://develop.sentry.dev/sdk/expected-features/#feature-flags) for more information.\n *\n * @example\n * ```\n * import * as Sentry from '@sentry/browser';\n * import {launchDarklyIntegration, buildLaunchDarklyFlagUsedInspector} from '@sentry/browser';\n * import * as LaunchDarkly from 'launchdarkly-js-client-sdk';\n *\n * Sentry.init(..., integrations: [launchDarklyIntegration()])\n * const ldClient = LaunchDarkly.initialize(..., {inspectors: [buildLaunchDarklyFlagUsedHandler()]});\n * ```\n */\nexport const launchDarklyIntegration = defineIntegration(() => {\n return {\n name: 'LaunchDarkly',\n\n processEvent(event: Event, _hint: EventHint, _client: Client): Event {\n const scope = getCurrentScope();\n const flagContext = scope.getScopeData().contexts.flags;\n const flagBuffer = flagContext ? flagContext.values : [];\n\n if (event.contexts === undefined) {\n event.contexts = {};\n }\n event.contexts.flags = { values: [...flagBuffer] };\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * LaunchDarkly hook that listens for flag evaluations and updates the `flags`\n * context in our Sentry scope. This needs to be registered as an\n * 'inspector' in LaunchDarkly initialize() options, separately from\n * `launchDarklyIntegration`. Both are needed to collect feature flags on error.\n */\nexport function buildLaunchDarklyFlagUsedHandler(): LDInspectionFlagUsedHandler {\n return {\n name: 'sentry-flag-auditor',\n type: 'flag-used',\n\n synchronous: true,\n\n /**\n * Handle a flag evaluation by storing its name and value on the current scope.\n */\n method: (flagKey: string, flagDetail: LDEvaluationDetail, _context: LDContext) => {\n if (typeof flagDetail.value === 'boolean') {\n const scopeContexts = getCurrentScope().getScopeData().contexts;\n if (!scopeContexts.flags) {\n scopeContexts.flags = { values: [] };\n }\n const flagBuffer = scopeContexts.flags.values;\n insertToFlagBuffer(flagBuffer, flagKey, flagDetail.value);\n }\n return;\n },\n };\n}\n"],"names":[],"mappings":";;;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,uBAAwB,GAAE,iBAAiB,CAAC,MAAM;AAC/D,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,cAAc;;AAExB,IAAI,YAAY,CAAC,KAAK,EAAS,KAAK,EAAa,OAAO,EAAiB;AACzE,MAAM,MAAM,KAAA,GAAQ,eAAe,EAAE;AACrC,MAAM,MAAM,WAAY,GAAE,KAAK,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC,KAAK;AAC7D,MAAM,MAAM,UAAW,GAAE,WAAY,GAAE,WAAW,CAAC,MAAA,GAAS,EAAE;;AAE9D,MAAM,IAAI,KAAK,CAAC,QAAS,KAAI,SAAS,EAAE;AACxC,QAAQ,KAAK,CAAC,QAAS,GAAE,EAAE;AAC3B;AACA,MAAM,KAAK,CAAC,QAAQ,CAAC,KAAM,GAAE,EAAE,MAAM,EAAE,CAAC,GAAG,UAAU,GAAG;AACxD,MAAM,OAAO,KAAK;AAClB,KAAK;AACL,GAAG;AACH,CAAC,CAAE;;AAEH;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gCAAgC,GAAgC;AAChF,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,qBAAqB;AAC/B,IAAI,IAAI,EAAE,WAAW;;AAErB,IAAI,WAAW,EAAE,IAAI;;AAErB;AACA;AACA;AACA,IAAI,MAAM,EAAE,CAAC,OAAO,EAAU,UAAU,EAAsB,QAAQ,KAAgB;AACtF,MAAM,IAAI,OAAO,UAAU,CAAC,KAAM,KAAI,SAAS,EAAE;AACjD,QAAQ,MAAM,aAAc,GAAE,eAAe,EAAE,CAAC,YAAY,EAAE,CAAC,QAAQ;AACvE,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;AAClC,UAAU,aAAa,CAAC,KAAM,GAAE,EAAE,MAAM,EAAE,EAAC,EAAG;AAC9C;AACA,QAAQ,MAAM,UAAW,GAAE,aAAa,CAAC,KAAK,CAAC,MAAM;AACrD,QAAQ,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC;AACjE;AACA,MAAM;AACN,KAAK;AACL,GAAG;AACH;;;;"}
@@ -1 +1 @@
1
- {"type":"module","version":"8.38.0","sideEffects":false}
1
+ {"type":"module","version":"8.39.0-beta.0","sideEffects":false}
@@ -0,0 +1,61 @@
1
+ import { logger } from '@sentry/utils';
2
+ import { DEBUG_BUILD } from '../debug-build.js';
3
+
4
+ /**
5
+ * Ordered LRU cache for storing feature flags in the scope context. The name
6
+ * of each flag in the buffer is unique, and the output of getAll() is ordered
7
+ * from oldest to newest.
8
+ */
9
+
10
+ /**
11
+ * Max size of the LRU flag buffer stored in Sentry scope and event contexts.
12
+ */
13
+ const FLAG_BUFFER_SIZE = 100;
14
+
15
+ /**
16
+ * Insert into a FeatureFlag array while maintaining ordered LRU properties. Not
17
+ * thread-safe. After inserting:
18
+ * - `flags` is sorted in order of recency, with the newest flag at the end.
19
+ * - No other flags with the same name exist in `flags`.
20
+ * - The length of `flags` does not exceed `maxSize`. The oldest flag is evicted
21
+ * as needed.
22
+ *
23
+ * @param flags The array to insert into.
24
+ * @param name Name of the feature flag to insert.
25
+ * @param value Value of the feature flag.
26
+ * @param maxSize Max number of flags the buffer should store. It's recommended
27
+ * to keep this consistent across insertions. Default is DEFAULT_MAX_SIZE
28
+ */
29
+ function insertToFlagBuffer(
30
+ flags,
31
+ name,
32
+ value,
33
+ maxSize = FLAG_BUFFER_SIZE,
34
+ ) {
35
+ if (flags.length > maxSize) {
36
+ DEBUG_BUILD && logger.error(`[Feature Flags] insertToFlagBuffer called on a buffer larger than maxSize=${maxSize}`);
37
+ return;
38
+ }
39
+
40
+ // Check if the flag is already in the buffer - O(n)
41
+ const index = flags.findIndex(f => f.flag === name);
42
+
43
+ if (index !== -1) {
44
+ // The flag was found, remove it from its current position - O(n)
45
+ flags.splice(index, 1);
46
+ }
47
+
48
+ if (flags.length === maxSize) {
49
+ // If at capacity, pop the earliest flag - O(n)
50
+ flags.shift();
51
+ }
52
+
53
+ // Push the flag to the end - O(1)
54
+ flags.push({
55
+ flag: name,
56
+ result: value,
57
+ });
58
+ }
59
+
60
+ export { FLAG_BUFFER_SIZE, insertToFlagBuffer };
61
+ //# sourceMappingURL=featureFlags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"featureFlags.js","sources":["../../../../src/utils/featureFlags.ts"],"sourcesContent":["import type { FeatureFlag } from '@sentry/types';\nimport { logger } from '@sentry/utils';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/**\n * Ordered LRU cache for storing feature flags in the scope context. The name\n * of each flag in the buffer is unique, and the output of getAll() is ordered\n * from oldest to newest.\n */\n\n/**\n * Max size of the LRU flag buffer stored in Sentry scope and event contexts.\n */\nexport const FLAG_BUFFER_SIZE = 100;\n\n/**\n * Insert into a FeatureFlag array while maintaining ordered LRU properties. Not\n * thread-safe. After inserting:\n * - `flags` is sorted in order of recency, with the newest flag at the end.\n * - No other flags with the same name exist in `flags`.\n * - The length of `flags` does not exceed `maxSize`. The oldest flag is evicted\n * as needed.\n *\n * @param flags The array to insert into.\n * @param name Name of the feature flag to insert.\n * @param value Value of the feature flag.\n * @param maxSize Max number of flags the buffer should store. It's recommended\n * to keep this consistent across insertions. Default is DEFAULT_MAX_SIZE\n */\nexport function insertToFlagBuffer(\n flags: FeatureFlag[],\n name: string,\n value: boolean,\n maxSize: number = FLAG_BUFFER_SIZE,\n): void {\n if (flags.length > maxSize) {\n DEBUG_BUILD && logger.error(`[Feature Flags] insertToFlagBuffer called on a buffer larger than maxSize=${maxSize}`);\n return;\n }\n\n // Check if the flag is already in the buffer - O(n)\n const index = flags.findIndex(f => f.flag === name);\n\n if (index !== -1) {\n // The flag was found, remove it from its current position - O(n)\n flags.splice(index, 1);\n }\n\n if (flags.length === maxSize) {\n // If at capacity, pop the earliest flag - O(n)\n flags.shift();\n }\n\n // Push the flag to the end - O(1)\n flags.push({\n flag: name,\n result: value,\n });\n}\n"],"names":[],"mappings":";;;AAIA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACO,MAAM,gBAAiB,GAAE;;AAEhC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,kBAAkB;AAClC,EAAE,KAAK;AACP,EAAE,IAAI;AACN,EAAE,KAAK;AACP,EAAE,OAAO,GAAW,gBAAgB;AACpC,EAAQ;AACR,EAAE,IAAI,KAAK,CAAC,MAAO,GAAE,OAAO,EAAE;AAC9B,IAAI,WAAA,IAAe,MAAM,CAAC,KAAK,CAAC,CAAC,0EAA0E,EAAE,OAAO,CAAC,CAAA,CAAA;AACA,IAAA;AACA;;AAEA;AACA,EAAA,MAAA,KAAA,GAAA,KAAA,CAAA,SAAA,CAAA,CAAA,IAAA,CAAA,CAAA,IAAA,KAAA,IAAA,CAAA;;AAEA,EAAA,IAAA,KAAA,KAAA,CAAA,CAAA,EAAA;AACA;AACA,IAAA,KAAA,CAAA,MAAA,CAAA,KAAA,EAAA,CAAA,CAAA;AACA;;AAEA,EAAA,IAAA,KAAA,CAAA,MAAA,KAAA,OAAA,EAAA;AACA;AACA,IAAA,KAAA,CAAA,KAAA,EAAA;AACA;;AAEA;AACA,EAAA,KAAA,CAAA,IAAA,CAAA;AACA,IAAA,IAAA,EAAA,IAAA;AACA,IAAA,MAAA,EAAA,KAAA;AACA,GAAA,CAAA;AACA;;;;"}
@@ -19,4 +19,5 @@ export type { Span } from '@sentry/types';
19
19
  export { makeBrowserOfflineTransport } from './transports/offline';
20
20
  export { browserProfilingIntegration } from './profiling/integration';
21
21
  export { spotlightBrowserIntegration } from './integrations/spotlight';
22
+ export { launchDarklyIntegration, buildLaunchDarklyFlagUsedHandler } from './integrations/featureFlags/launchdarkly';
22
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAE1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,SAAS,GACV,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,uBAAuB,IAAI,mBAAmB,EAAE,CAAC;AAC7G,OAAO,EACL,WAAW,EACX,YAAY,GACb,MAAM,2BAA2B,CAAC;AAEnC,cAAc,WAAW,CAAC;AAE1B,OAAO,EACL,oCAAoC,EACpC,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,yBAAyB,EACzB,iCAAiC,EACjC,+BAA+B,GAChC,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAEL,oBAAoB,EACpB,gCAAgC,EAChC,aAAa,EACb,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,yBAAyB,EACzB,aAAa,EACb,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,gCAAgC,GACjC,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAE1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,SAAS,GACV,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,uBAAuB,IAAI,mBAAmB,EAAE,CAAC;AAC7G,OAAO,EACL,WAAW,EACX,YAAY,GACb,MAAM,2BAA2B,CAAC;AAEnC,cAAc,WAAW,CAAC;AAE1B,OAAO,EACL,oCAAoC,EACpC,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,yBAAyB,EACzB,iCAAiC,EACjC,+BAA+B,GAChC,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAEL,oBAAoB,EACpB,gCAAgC,EAChC,aAAa,EACb,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,yBAAyB,EACzB,aAAa,EACb,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,gCAAgC,GACjC,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,MAAM,0CAA0C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { launchDarklyIntegration, buildLaunchDarklyFlagUsedHandler } from './integration';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/integrations/featureFlags/launchdarkly/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { LDInspectionFlagUsedHandler } from './types';
2
+ /**
3
+ * Sentry integration for capturing feature flags from LaunchDarkly.
4
+ *
5
+ * See the [feature flag documentation](https://develop.sentry.dev/sdk/expected-features/#feature-flags) for more information.
6
+ *
7
+ * @example
8
+ * ```
9
+ * import * as Sentry from '@sentry/browser';
10
+ * import {launchDarklyIntegration, buildLaunchDarklyFlagUsedInspector} from '@sentry/browser';
11
+ * import * as LaunchDarkly from 'launchdarkly-js-client-sdk';
12
+ *
13
+ * Sentry.init(..., integrations: [launchDarklyIntegration()])
14
+ * const ldClient = LaunchDarkly.initialize(..., {inspectors: [buildLaunchDarklyFlagUsedHandler()]});
15
+ * ```
16
+ */
17
+ export declare const launchDarklyIntegration: () => import("@sentry/types").Integration;
18
+ /**
19
+ * LaunchDarkly hook that listens for flag evaluations and updates the `flags`
20
+ * context in our Sentry scope. This needs to be registered as an
21
+ * 'inspector' in LaunchDarkly initialize() options, separately from
22
+ * `launchDarklyIntegration`. Both are needed to collect feature flags on error.
23
+ */
24
+ export declare function buildLaunchDarklyFlagUsedHandler(): LDInspectionFlagUsedHandler;
25
+ //# sourceMappingURL=integration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../../../src/integrations/featureFlags/launchdarkly/integration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiC,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAK1F;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,2CAgBV,CAAC;AAE3B;;;;;GAKG;AACH,wBAAgB,gCAAgC,IAAI,2BAA2B,CAsB9E"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Inline definitions of LaunchDarkly types so we don't have to include their
3
+ * SDK in devDependencies. These are only for type-checking and can be extended
4
+ * as needed - for exact definitions, reference `launchdarkly-js-client-sdk`.
5
+ */
6
+ /**
7
+ * Currently, the Sentry integration does not read from values of this type.
8
+ */
9
+ export type LDContext = object;
10
+ /**
11
+ * An object that combines the result of a feature flag evaluation with information about
12
+ * how it was calculated.
13
+ */
14
+ export interface LDEvaluationDetail {
15
+ value: unknown;
16
+ }
17
+ /**
18
+ * Callback interface for collecting information about the SDK at runtime.
19
+ *
20
+ * This interface is used to collect information about flag usage.
21
+ *
22
+ * This interface should not be used by the application to access flags for the purpose of controlling application
23
+ * flow. It is intended for monitoring, analytics, or debugging purposes.
24
+ */
25
+ export interface LDInspectionFlagUsedHandler {
26
+ type: 'flag-used';
27
+ /**
28
+ * Name of the inspector. Will be used for logging issues with the inspector.
29
+ */
30
+ name: string;
31
+ /**
32
+ * If `true`, then the inspector will be ran synchronously with evaluation.
33
+ * Synchronous inspectors execute inline with evaluation and care should be taken to ensure
34
+ * they have minimal performance overhead.
35
+ */
36
+ synchronous?: boolean;
37
+ /**
38
+ * This method is called when a flag is accessed via a variation method, or it can be called based on actions in
39
+ * wrapper SDKs which have different methods of tracking when a flag was accessed. It is not called when a call is made
40
+ * to allFlags.
41
+ */
42
+ method: (flagKey: string, flagDetail: LDEvaluationDetail, context: LDContext) => void;
43
+ }
44
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/integrations/featureFlags/launchdarkly/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;CAEhB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,WAAW,CAAC;IAElB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;CACvF"}
@@ -0,0 +1,26 @@
1
+ import type { FeatureFlag } from '@sentry/types';
2
+ /**
3
+ * Ordered LRU cache for storing feature flags in the scope context. The name
4
+ * of each flag in the buffer is unique, and the output of getAll() is ordered
5
+ * from oldest to newest.
6
+ */
7
+ /**
8
+ * Max size of the LRU flag buffer stored in Sentry scope and event contexts.
9
+ */
10
+ export declare const FLAG_BUFFER_SIZE = 100;
11
+ /**
12
+ * Insert into a FeatureFlag array while maintaining ordered LRU properties. Not
13
+ * thread-safe. After inserting:
14
+ * - `flags` is sorted in order of recency, with the newest flag at the end.
15
+ * - No other flags with the same name exist in `flags`.
16
+ * - The length of `flags` does not exceed `maxSize`. The oldest flag is evicted
17
+ * as needed.
18
+ *
19
+ * @param flags The array to insert into.
20
+ * @param name Name of the feature flag to insert.
21
+ * @param value Value of the feature flag.
22
+ * @param maxSize Max number of flags the buffer should store. It's recommended
23
+ * to keep this consistent across insertions. Default is DEFAULT_MAX_SIZE
24
+ */
25
+ export declare function insertToFlagBuffer(flags: FeatureFlag[], name: string, value: boolean, maxSize?: number): void;
26
+ //# sourceMappingURL=featureFlags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"featureFlags.d.ts","sourceRoot":"","sources":["../../../../src/utils/featureFlags.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAIjD;;;;GAIG;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,WAAW,EAAE,EACpB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,MAAyB,GACjC,IAAI,CAwBN"}
@@ -19,4 +19,5 @@ export { Span } from '@sentry/types';
19
19
  export { makeBrowserOfflineTransport } from './transports/offline';
20
20
  export { browserProfilingIntegration } from './profiling/integration';
21
21
  export { spotlightBrowserIntegration } from './integrations/spotlight';
22
+ export { launchDarklyIntegration, buildLaunchDarklyFlagUsedHandler } from './integrations/featureFlags/launchdarkly';
22
23
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { launchDarklyIntegration, buildLaunchDarklyFlagUsedHandler } from './integration';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { LDInspectionFlagUsedHandler } from './types';
2
+ /**
3
+ * Sentry integration for capturing feature flags from LaunchDarkly.
4
+ *
5
+ * See the [feature flag documentation](https://develop.sentry.dev/sdk/expected-features/#feature-flags) for more information.
6
+ *
7
+ * @example
8
+ * ```
9
+ * import * as Sentry from '@sentry/browser';
10
+ * import {launchDarklyIntegration, buildLaunchDarklyFlagUsedInspector} from '@sentry/browser';
11
+ * import * as LaunchDarkly from 'launchdarkly-js-client-sdk';
12
+ *
13
+ * Sentry.init(..., integrations: [launchDarklyIntegration()])
14
+ * const ldClient = LaunchDarkly.initialize(..., {inspectors: [buildLaunchDarklyFlagUsedHandler()]});
15
+ * ```
16
+ */
17
+ export declare const launchDarklyIntegration: () => import("@sentry/types").Integration;
18
+ /**
19
+ * LaunchDarkly hook that listens for flag evaluations and updates the `flags`
20
+ * context in our Sentry scope. This needs to be registered as an
21
+ * 'inspector' in LaunchDarkly initialize() options, separately from
22
+ * `launchDarklyIntegration`. Both are needed to collect feature flags on error.
23
+ */
24
+ export declare function buildLaunchDarklyFlagUsedHandler(): LDInspectionFlagUsedHandler;
25
+ //# sourceMappingURL=integration.d.ts.map
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Inline definitions of LaunchDarkly types so we don't have to include their
3
+ * SDK in devDependencies. These are only for type-checking and can be extended
4
+ * as needed - for exact definitions, reference `launchdarkly-js-client-sdk`.
5
+ */
6
+ /**
7
+ * Currently, the Sentry integration does not read from values of this type.
8
+ */
9
+ export type LDContext = object;
10
+ /**
11
+ * An object that combines the result of a feature flag evaluation with information about
12
+ * how it was calculated.
13
+ */
14
+ export interface LDEvaluationDetail {
15
+ value: unknown;
16
+ }
17
+ /**
18
+ * Callback interface for collecting information about the SDK at runtime.
19
+ *
20
+ * This interface is used to collect information about flag usage.
21
+ *
22
+ * This interface should not be used by the application to access flags for the purpose of controlling application
23
+ * flow. It is intended for monitoring, analytics, or debugging purposes.
24
+ */
25
+ export interface LDInspectionFlagUsedHandler {
26
+ type: 'flag-used';
27
+ /**
28
+ * Name of the inspector. Will be used for logging issues with the inspector.
29
+ */
30
+ name: string;
31
+ /**
32
+ * If `true`, then the inspector will be ran synchronously with evaluation.
33
+ * Synchronous inspectors execute inline with evaluation and care should be taken to ensure
34
+ * they have minimal performance overhead.
35
+ */
36
+ synchronous?: boolean;
37
+ /**
38
+ * This method is called when a flag is accessed via a variation method, or it can be called based on actions in
39
+ * wrapper SDKs which have different methods of tracking when a flag was accessed. It is not called when a call is made
40
+ * to allFlags.
41
+ */
42
+ method: (flagKey: string, flagDetail: LDEvaluationDetail, context: LDContext) => void;
43
+ }
44
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,26 @@
1
+ import { FeatureFlag } from '@sentry/types';
2
+ /**
3
+ * Ordered LRU cache for storing feature flags in the scope context. The name
4
+ * of each flag in the buffer is unique, and the output of getAll() is ordered
5
+ * from oldest to newest.
6
+ */
7
+ /**
8
+ * Max size of the LRU flag buffer stored in Sentry scope and event contexts.
9
+ */
10
+ export declare const FLAG_BUFFER_SIZE = 100;
11
+ /**
12
+ * Insert into a FeatureFlag array while maintaining ordered LRU properties. Not
13
+ * thread-safe. After inserting:
14
+ * - `flags` is sorted in order of recency, with the newest flag at the end.
15
+ * - No other flags with the same name exist in `flags`.
16
+ * - The length of `flags` does not exceed `maxSize`. The oldest flag is evicted
17
+ * as needed.
18
+ *
19
+ * @param flags The array to insert into.
20
+ * @param name Name of the feature flag to insert.
21
+ * @param value Value of the feature flag.
22
+ * @param maxSize Max number of flags the buffer should store. It's recommended
23
+ * to keep this consistent across insertions. Default is DEFAULT_MAX_SIZE
24
+ */
25
+ export declare function insertToFlagBuffer(flags: FeatureFlag[], name: string, value: boolean, maxSize?: number): void;
26
+ //# sourceMappingURL=featureFlags.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/browser",
3
- "version": "8.38.0",
3
+ "version": "8.39.0-beta.0",
4
4
  "description": "Official Sentry SDK for browsers",
5
5
  "repository": "git://github.com/getsentry/sentry-javascript.git",
6
6
  "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/browser",
@@ -39,16 +39,16 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@sentry-internal/browser-utils": "8.38.0",
43
- "@sentry-internal/feedback": "8.38.0",
44
- "@sentry-internal/replay": "8.38.0",
45
- "@sentry-internal/replay-canvas": "8.38.0",
46
- "@sentry/core": "8.38.0",
47
- "@sentry/types": "8.38.0",
48
- "@sentry/utils": "8.38.0"
42
+ "@sentry-internal/browser-utils": "8.39.0-beta.0",
43
+ "@sentry-internal/feedback": "8.39.0-beta.0",
44
+ "@sentry-internal/replay": "8.39.0-beta.0",
45
+ "@sentry-internal/replay-canvas": "8.39.0-beta.0",
46
+ "@sentry/core": "8.39.0-beta.0",
47
+ "@sentry/types": "8.39.0-beta.0",
48
+ "@sentry/utils": "8.39.0-beta.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@sentry-internal/integration-shims": "8.38.0",
51
+ "@sentry-internal/integration-shims": "8.39.0-beta.0",
52
52
  "fake-indexeddb": "^4.0.1"
53
53
  },
54
54
  "scripts": {