posthog-node 5.8.2 → 5.8.4

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.
@@ -27,13 +27,15 @@ var core = require('@posthog/core');
27
27
  * @param {Number} [projectId] Optional: The Sentry project id, used to send a direct link from PostHog to Sentry
28
28
  * @param {string} [prefix] Optional: Url of a self-hosted sentry instance (default: https://sentry.io/organizations/)
29
29
  * @param {SeverityLevel[] | '*'} [severityAllowList] Optional: send events matching the provided levels. Use '*' to send all events (default: ['error'])
30
+ * @param {boolean} [sendExceptionsToPostHog] Optional: capture exceptions as events in PostHog (default: true)
30
31
  */
31
32
  const NAME = 'posthog-node';
32
33
  function createEventProcessor(_posthog, {
33
34
  organization,
34
35
  projectId,
35
36
  prefix,
36
- severityAllowList = ['error']
37
+ severityAllowList = ['error'],
38
+ sendExceptionsToPostHog = true
37
39
  } = {}) {
38
40
  return event => {
39
41
  const shouldProcessLevel = severityAllowList === '*' || severityAllowList.includes(event.level);
@@ -83,11 +85,13 @@ function createEventProcessor(_posthog, {
83
85
  if (organization && projectId) {
84
86
  properties['$sentry_url'] = (prefix || 'https://sentry.io/organizations/') + organization + '/issues/?project=' + projectId + '&query=' + event.event_id;
85
87
  }
86
- _posthog.capture({
87
- event: '$exception',
88
- distinctId: userId,
89
- properties
90
- });
88
+ if (sendExceptionsToPostHog) {
89
+ _posthog.capture({
90
+ event: '$exception',
91
+ distinctId: userId,
92
+ properties
93
+ });
94
+ }
91
95
  return event;
92
96
  };
93
97
  }
@@ -103,7 +107,7 @@ function sentryIntegration(_posthog, options) {
103
107
  }
104
108
  // V7 integration - class based
105
109
  class PostHogSentryIntegration {
106
- constructor(_posthog, organization, prefix, severityAllowList) {
110
+ constructor(_posthog, organization, prefix, severityAllowList, sendExceptionsToPostHog) {
107
111
  this.name = NAME;
108
112
  // setupOnce gets called by Sentry when it intializes the plugin
109
113
  this.name = NAME;
@@ -113,7 +117,8 @@ class PostHogSentryIntegration {
113
117
  organization,
114
118
  projectId,
115
119
  prefix,
116
- severityAllowList
120
+ severityAllowList,
121
+ sendExceptionsToPostHog: sendExceptionsToPostHog ?? true
117
122
  }));
118
123
  };
119
124
  }
@@ -1186,7 +1191,7 @@ function snipLine(line, colno) {
1186
1191
  return newLine;
1187
1192
  }
1188
1193
 
1189
- var version = "5.8.2";
1194
+ var version = "5.8.4";
1190
1195
 
1191
1196
  /**
1192
1197
  * A lazy value that is only computed when needed. Inspired by C#'s Lazy<T> class.
@@ -1373,12 +1378,14 @@ class FeatureFlagsPoller {
1373
1378
  const payloads = {};
1374
1379
  let fallbackToFlags = this.featureFlags.length == 0;
1375
1380
  const flagsToEvaluate = flagKeysToExplicitlyEvaluate ? flagKeysToExplicitlyEvaluate.map(key => this.featureFlagsByKey[key]).filter(Boolean) : this.featureFlags;
1381
+ // Create a shared evaluation cache to prevent memory leaks when processing many flags
1382
+ const sharedEvaluationCache = {};
1376
1383
  await Promise.all(flagsToEvaluate.map(async flag => {
1377
1384
  try {
1378
1385
  const {
1379
1386
  value: matchValue,
1380
1387
  payload: matchPayload
1381
- } = await this.computeFlagAndPayloadLocally(flag, distinctId, groups, personProperties, groupProperties);
1388
+ } = await this.computeFlagAndPayloadLocally(flag, distinctId, groups, personProperties, groupProperties, undefined /* matchValue */, sharedEvaluationCache);
1382
1389
  response[flag.key] = matchValue;
1383
1390
  if (matchPayload) {
1384
1391
  payloads[flag.key] = matchPayload;
@@ -1398,9 +1405,11 @@ class FeatureFlagsPoller {
1398
1405
  fallbackToFlags
1399
1406
  };
1400
1407
  }
1401
- async computeFlagAndPayloadLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}, matchValue) {
1402
- // Always ensure flags are loaded for payload computation
1403
- await this.loadFeatureFlags();
1408
+ async computeFlagAndPayloadLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}, matchValue, evaluationCache, skipLoadCheck = false) {
1409
+ // Only load flags if not already loaded and not skipping the check
1410
+ if (!skipLoadCheck) {
1411
+ await this.loadFeatureFlags();
1412
+ }
1404
1413
  if (!this.loadedSuccessfullyOnce) {
1405
1414
  return {
1406
1415
  value: false,
@@ -1412,7 +1421,7 @@ class FeatureFlagsPoller {
1412
1421
  if (matchValue !== undefined) {
1413
1422
  flagValue = matchValue;
1414
1423
  } else {
1415
- flagValue = await this.computeFlagValueLocally(flag, distinctId, groups, personProperties, groupProperties);
1424
+ flagValue = await this.computeFlagValueLocally(flag, distinctId, groups, personProperties, groupProperties, evaluationCache);
1416
1425
  }
1417
1426
  // Always compute payload based on the final flagValue (whether provided or computed)
1418
1427
  const payload = this.getFeatureFlagPayload(flag.key, flagValue);
@@ -1421,7 +1430,7 @@ class FeatureFlagsPoller {
1421
1430
  payload
1422
1431
  };
1423
1432
  }
1424
- async computeFlagValueLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}) {
1433
+ async computeFlagValueLocally(flag, distinctId, groups = {}, personProperties = {}, groupProperties = {}, evaluationCache = {}) {
1425
1434
  if (flag.ensure_experience_continuity) {
1426
1435
  throw new InconclusiveMatchError('Flag has experience continuity enabled');
1427
1436
  }
@@ -1441,9 +1450,9 @@ class FeatureFlagsPoller {
1441
1450
  return false;
1442
1451
  }
1443
1452
  const focusedGroupProperties = groupProperties[groupName];
1444
- return await this.matchFeatureFlagProperties(flag, groups[groupName], focusedGroupProperties);
1453
+ return await this.matchFeatureFlagProperties(flag, groups[groupName], focusedGroupProperties, evaluationCache);
1445
1454
  } else {
1446
- return await this.matchFeatureFlagProperties(flag, distinctId, personProperties);
1455
+ return await this.matchFeatureFlagProperties(flag, distinctId, personProperties, evaluationCache);
1447
1456
  }
1448
1457
  }
1449
1458
  getFeatureFlagPayload(key, flagValue) {