posthog-node 3.2.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/index.ts +1 -0
- package/lib/index.cjs.js +116 -17
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +42 -2
- package/lib/index.esm.js +116 -18
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-node/index.d.ts +1 -0
- package/lib/posthog-node/src/extensions/sentry-integration.d.ts +40 -0
- package/lib/posthog-node/src/feature-flags.d.ts +2 -0
- package/lib/posthog-node/src/posthog-node.d.ts +1 -1
- package/package.json +6 -2
- package/src/extensions/sentry-integration.ts +125 -0
- package/src/feature-flags.ts +5 -2
- package/src/posthog-node.ts +4 -1
- package/test/extensions/sentry-integration.spec.ts +150 -0
package/lib/index.d.ts
CHANGED
|
@@ -316,7 +316,7 @@ declare class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
|
|
|
316
316
|
private _memoryStorage;
|
|
317
317
|
private featureFlagsPoller?;
|
|
318
318
|
private maxCacheSize;
|
|
319
|
-
|
|
319
|
+
readonly options: PostHogOptions;
|
|
320
320
|
distinctIdHasSentFlagCalls: Record<string, string[]>;
|
|
321
321
|
constructor(apiKey: string, options?: PostHogOptions);
|
|
322
322
|
getPersistedProperty(key: PostHogPersistedProperty): any | undefined;
|
|
@@ -379,4 +379,44 @@ declare class PostHog extends PostHogCoreStateless implements PostHogNodeV1 {
|
|
|
379
379
|
shutdownAsync(): Promise<void>;
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
-
|
|
382
|
+
/**
|
|
383
|
+
* @file Adapted from [posthog-js](https://github.com/PostHog/posthog-js/blob/8157df935a4d0e71d2fefef7127aa85ee51c82d1/src/extensions/sentry-integration.ts) with modifications for the Node SDK.
|
|
384
|
+
*/
|
|
385
|
+
|
|
386
|
+
declare type _SentryEventProcessor = any;
|
|
387
|
+
declare type _SentryHub = any;
|
|
388
|
+
interface _SentryIntegration {
|
|
389
|
+
name: string;
|
|
390
|
+
setupOnce(addGlobalEventProcessor: (callback: _SentryEventProcessor) => void, getCurrentHub: () => _SentryHub): void;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Integrate Sentry with PostHog. This will add a direct link to the person in Sentry, and an $exception event in PostHog.
|
|
394
|
+
*
|
|
395
|
+
* ### Usage
|
|
396
|
+
*
|
|
397
|
+
* Sentry.init({
|
|
398
|
+
* dsn: 'https://example',
|
|
399
|
+
* integrations: [
|
|
400
|
+
* new PostHogSentryIntegration(posthog)
|
|
401
|
+
* ]
|
|
402
|
+
* })
|
|
403
|
+
*
|
|
404
|
+
* Sentry.setTag(PostHogSentryIntegration.POSTHOG_ID_TAG, 'some distinct id');
|
|
405
|
+
*
|
|
406
|
+
* @param {Object} [posthog] The posthog object
|
|
407
|
+
* @param {string} [organization] Optional: The Sentry organization, used to send a direct link from PostHog to Sentry
|
|
408
|
+
* @param {Number} [projectId] Optional: The Sentry project id, used to send a direct link from PostHog to Sentry
|
|
409
|
+
* @param {string} [prefix] Optional: Url of a self-hosted sentry instance (default: https://sentry.io/organizations/)
|
|
410
|
+
*/
|
|
411
|
+
declare class PostHogSentryIntegration implements _SentryIntegration {
|
|
412
|
+
private readonly posthog;
|
|
413
|
+
private readonly posthogHost?;
|
|
414
|
+
private readonly organization?;
|
|
415
|
+
private readonly prefix?;
|
|
416
|
+
readonly name = "posthog-node";
|
|
417
|
+
static readonly POSTHOG_ID_TAG = "posthog_distinct_id";
|
|
418
|
+
constructor(posthog: PostHog, posthogHost?: string | undefined, organization?: string | undefined, prefix?: string | undefined);
|
|
419
|
+
setupOnce(addGlobalEventProcessor: (callback: _SentryEventProcessor) => void, getCurrentHub: () => _SentryHub): void;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export { PostHog, PostHogOptions, PostHogSentryIntegration };
|
package/lib/index.esm.js
CHANGED
|
@@ -154,7 +154,7 @@ function __spreadArray(to, from, pack) {
|
|
|
154
154
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
var version = "3.
|
|
157
|
+
var version = "3.3.0";
|
|
158
158
|
|
|
159
159
|
var PostHogPersistedProperty;
|
|
160
160
|
(function (PostHogPersistedProperty) {
|
|
@@ -1000,7 +1000,7 @@ var PostHogCoreStateless = /** @class */ (function () {
|
|
|
1000
1000
|
var _this = this;
|
|
1001
1001
|
var _a;
|
|
1002
1002
|
if (this.optedOut) {
|
|
1003
|
-
this._events.emit(type, "Library is disabled. Not sending event. To re-enable, call posthog.
|
|
1003
|
+
this._events.emit(type, "Library is disabled. Not sending event. To re-enable, call posthog.optIn()");
|
|
1004
1004
|
return;
|
|
1005
1005
|
}
|
|
1006
1006
|
var message = __assign(__assign({}, _message), { type: type, library: this.getLibraryId(), library_version: this.getLibraryVersion(), timestamp: (options === null || options === void 0 ? void 0 : options.timestamp) ? options === null || options === void 0 ? void 0 : options.timestamp : currentISOTime() });
|
|
@@ -1743,6 +1743,7 @@ function () {
|
|
|
1743
1743
|
this.poller = undefined; // NOTE: as any is required here as the AbortSignal typing is slightly misaligned but works just fine
|
|
1744
1744
|
|
|
1745
1745
|
this.fetch = options.fetch || fetch$1;
|
|
1746
|
+
this.onError = options.onError;
|
|
1746
1747
|
void this.loadFeatureFlags();
|
|
1747
1748
|
}
|
|
1748
1749
|
|
|
@@ -1902,10 +1903,13 @@ function () {
|
|
|
1902
1903
|
this.featureFlags.map(function (flag) {
|
|
1903
1904
|
return __awaiter(_this, void 0, void 0, function () {
|
|
1904
1905
|
var matchValue, matchPayload, e_1;
|
|
1905
|
-
|
|
1906
|
-
|
|
1906
|
+
|
|
1907
|
+
var _a;
|
|
1908
|
+
|
|
1909
|
+
return __generator(this, function (_b) {
|
|
1910
|
+
switch (_b.label) {
|
|
1907
1911
|
case 0:
|
|
1908
|
-
|
|
1912
|
+
_b.trys.push([0, 2,, 3]);
|
|
1909
1913
|
|
|
1910
1914
|
matchValue = this.computeFlagLocally(flag, distinctId, groups, personProperties, groupProperties);
|
|
1911
1915
|
response[flag.key] = matchValue;
|
|
@@ -1914,7 +1918,7 @@ function () {
|
|
|
1914
1918
|
, this.computeFeatureFlagPayloadLocally(flag.key, matchValue)];
|
|
1915
1919
|
|
|
1916
1920
|
case 1:
|
|
1917
|
-
matchPayload =
|
|
1921
|
+
matchPayload = _b.sent();
|
|
1918
1922
|
|
|
1919
1923
|
if (matchPayload) {
|
|
1920
1924
|
payloads[flag.key] = matchPayload;
|
|
@@ -1925,10 +1929,10 @@ function () {
|
|
|
1925
1929
|
, 3];
|
|
1926
1930
|
|
|
1927
1931
|
case 2:
|
|
1928
|
-
e_1 =
|
|
1932
|
+
e_1 = _b.sent();
|
|
1929
1933
|
|
|
1930
1934
|
if (e_1 instanceof InconclusiveMatchError) ; else if (e_1 instanceof Error) {
|
|
1931
|
-
|
|
1935
|
+
(_a = this.onError) === null || _a === void 0 ? void 0 : _a.call(this, new Error("Error computing flag locally: ".concat(flag.key, ": ").concat(e_1)));
|
|
1932
1936
|
}
|
|
1933
1937
|
|
|
1934
1938
|
fallbackToDecide = true;
|
|
@@ -2166,13 +2170,15 @@ function () {
|
|
|
2166
2170
|
};
|
|
2167
2171
|
|
|
2168
2172
|
FeatureFlagsPoller.prototype._loadFeatureFlags = function () {
|
|
2173
|
+
var _a;
|
|
2174
|
+
|
|
2169
2175
|
return __awaiter(this, void 0, void 0, function () {
|
|
2170
2176
|
var res, responseJson, err_1;
|
|
2171
2177
|
|
|
2172
2178
|
var _this = this;
|
|
2173
2179
|
|
|
2174
|
-
return __generator(this, function (
|
|
2175
|
-
switch (
|
|
2180
|
+
return __generator(this, function (_b) {
|
|
2181
|
+
switch (_b.label) {
|
|
2176
2182
|
case 0:
|
|
2177
2183
|
if (this.poller) {
|
|
2178
2184
|
clearTimeout(this.poller);
|
|
@@ -2182,17 +2188,17 @@ function () {
|
|
|
2182
2188
|
this.poller = setTimeout(function () {
|
|
2183
2189
|
return _this._loadFeatureFlags();
|
|
2184
2190
|
}, this.pollingInterval);
|
|
2185
|
-
|
|
2191
|
+
_b.label = 1;
|
|
2186
2192
|
|
|
2187
2193
|
case 1:
|
|
2188
|
-
|
|
2194
|
+
_b.trys.push([1, 4,, 5]);
|
|
2189
2195
|
|
|
2190
2196
|
return [4
|
|
2191
2197
|
/*yield*/
|
|
2192
2198
|
, this._requestFeatureFlagDefinitions()];
|
|
2193
2199
|
|
|
2194
2200
|
case 2:
|
|
2195
|
-
res =
|
|
2201
|
+
res = _b.sent();
|
|
2196
2202
|
|
|
2197
2203
|
if (res && res.status === 401) {
|
|
2198
2204
|
throw new ClientError("Your personalApiKey is invalid. Are you sure you're not using your Project API key? More information: https://posthog.com/docs/api/overview");
|
|
@@ -2211,7 +2217,7 @@ function () {
|
|
|
2211
2217
|
, res.json()];
|
|
2212
2218
|
|
|
2213
2219
|
case 3:
|
|
2214
|
-
responseJson =
|
|
2220
|
+
responseJson = _b.sent();
|
|
2215
2221
|
|
|
2216
2222
|
if (!('flags' in responseJson)) {
|
|
2217
2223
|
console.error("Invalid response when getting feature flags: ".concat(JSON.stringify(responseJson)));
|
|
@@ -2229,11 +2235,11 @@ function () {
|
|
|
2229
2235
|
, 5];
|
|
2230
2236
|
|
|
2231
2237
|
case 4:
|
|
2232
|
-
err_1 =
|
|
2238
|
+
err_1 = _b.sent(); // if an error that is not an instance of ClientError is thrown
|
|
2233
2239
|
// we silently ignore the error when reloading feature flags
|
|
2234
2240
|
|
|
2235
2241
|
if (err_1 instanceof ClientError) {
|
|
2236
|
-
|
|
2242
|
+
(_a = this.onError) === null || _a === void 0 ? void 0 : _a.call(this, err_1);
|
|
2237
2243
|
}
|
|
2238
2244
|
|
|
2239
2245
|
return [3
|
|
@@ -2558,7 +2564,10 @@ function (_super) {
|
|
|
2558
2564
|
projectApiKey: apiKey,
|
|
2559
2565
|
timeout: (_a = options.requestTimeout) !== null && _a !== void 0 ? _a : 10000,
|
|
2560
2566
|
host: _this.host,
|
|
2561
|
-
fetch: options.fetch
|
|
2567
|
+
fetch: options.fetch,
|
|
2568
|
+
onError: function (err) {
|
|
2569
|
+
_this._events.emit('error', err);
|
|
2570
|
+
}
|
|
2562
2571
|
});
|
|
2563
2572
|
}
|
|
2564
2573
|
|
|
@@ -2996,5 +3005,94 @@ function (_super) {
|
|
|
2996
3005
|
return PostHog;
|
|
2997
3006
|
}(PostHogCoreStateless);
|
|
2998
3007
|
|
|
2999
|
-
|
|
3008
|
+
/**
|
|
3009
|
+
* Integrate Sentry with PostHog. This will add a direct link to the person in Sentry, and an $exception event in PostHog.
|
|
3010
|
+
*
|
|
3011
|
+
* ### Usage
|
|
3012
|
+
*
|
|
3013
|
+
* Sentry.init({
|
|
3014
|
+
* dsn: 'https://example',
|
|
3015
|
+
* integrations: [
|
|
3016
|
+
* new PostHogSentryIntegration(posthog)
|
|
3017
|
+
* ]
|
|
3018
|
+
* })
|
|
3019
|
+
*
|
|
3020
|
+
* Sentry.setTag(PostHogSentryIntegration.POSTHOG_ID_TAG, 'some distinct id');
|
|
3021
|
+
*
|
|
3022
|
+
* @param {Object} [posthog] The posthog object
|
|
3023
|
+
* @param {string} [organization] Optional: The Sentry organization, used to send a direct link from PostHog to Sentry
|
|
3024
|
+
* @param {Number} [projectId] Optional: The Sentry project id, used to send a direct link from PostHog to Sentry
|
|
3025
|
+
* @param {string} [prefix] Optional: Url of a self-hosted sentry instance (default: https://sentry.io/organizations/)
|
|
3026
|
+
*/
|
|
3027
|
+
var PostHogSentryIntegration =
|
|
3028
|
+
/** @class */
|
|
3029
|
+
function () {
|
|
3030
|
+
function PostHogSentryIntegration(posthog, posthogHost, organization, prefix) {
|
|
3031
|
+
var _a;
|
|
3032
|
+
|
|
3033
|
+
this.posthog = posthog;
|
|
3034
|
+
this.posthogHost = posthogHost;
|
|
3035
|
+
this.organization = organization;
|
|
3036
|
+
this.prefix = prefix;
|
|
3037
|
+
this.name = 'posthog-node';
|
|
3038
|
+
this.posthogHost = (_a = posthog.options.host) !== null && _a !== void 0 ? _a : 'https://app.posthog.com';
|
|
3039
|
+
}
|
|
3040
|
+
|
|
3041
|
+
PostHogSentryIntegration.prototype.setupOnce = function (addGlobalEventProcessor, getCurrentHub) {
|
|
3042
|
+
var _this = this;
|
|
3043
|
+
|
|
3044
|
+
addGlobalEventProcessor(function (event) {
|
|
3045
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
3046
|
+
|
|
3047
|
+
if (((_a = event.exception) === null || _a === void 0 ? void 0 : _a.values) === undefined || event.exception.values.length === 0) {
|
|
3048
|
+
return event;
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
if (!event.tags) {
|
|
3052
|
+
event.tags = {};
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
var sentry = getCurrentHub(); // Get the PostHog user ID from a specific tag, which users can set on their Sentry scope as they need.
|
|
3056
|
+
|
|
3057
|
+
var userId = event.tags[PostHogSentryIntegration.POSTHOG_ID_TAG];
|
|
3058
|
+
|
|
3059
|
+
if (userId === undefined) {
|
|
3060
|
+
// If we can't find a user ID, don't bother linking the event. We won't be able to send anything meaningful to PostHog without it.
|
|
3061
|
+
return event;
|
|
3062
|
+
}
|
|
3063
|
+
|
|
3064
|
+
event.tags['PostHog Person URL'] = new URL("/person/".concat(userId), _this.posthogHost).toString();
|
|
3065
|
+
var properties = {
|
|
3066
|
+
// PostHog Exception Properties
|
|
3067
|
+
$exception_message: (_b = event.exception.values[0]) === null || _b === void 0 ? void 0 : _b.value,
|
|
3068
|
+
$exception_type: (_c = event.exception.values[0]) === null || _c === void 0 ? void 0 : _c.type,
|
|
3069
|
+
$exception_personURL: event.tags['PostHog Person URL'],
|
|
3070
|
+
// Sentry Exception Properties
|
|
3071
|
+
$sentry_event_id: event.event_id,
|
|
3072
|
+
$sentry_exception: event.exception,
|
|
3073
|
+
$sentry_exception_message: (_d = event.exception.values[0]) === null || _d === void 0 ? void 0 : _d.value,
|
|
3074
|
+
$sentry_exception_type: (_e = event.exception.values[0]) === null || _e === void 0 ? void 0 : _e.type,
|
|
3075
|
+
$sentry_tags: event.tags
|
|
3076
|
+
};
|
|
3077
|
+
var projectId = (_g = (_f = sentry.getClient()) === null || _f === void 0 ? void 0 : _f.getDsn()) === null || _g === void 0 ? void 0 : _g.projectId;
|
|
3078
|
+
|
|
3079
|
+
if (_this.organization !== undefined && projectId !== undefined && event.event_id !== undefined) {
|
|
3080
|
+
properties.$sentry_url = "".concat((_h = _this.prefix) !== null && _h !== void 0 ? _h : 'https://sentry.io/organizations', "/").concat(_this.organization, "/issues/?project=").concat(projectId, "&query=").concat(event.event_id);
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
_this.posthog.capture({
|
|
3084
|
+
event: '$exception',
|
|
3085
|
+
distinctId: userId,
|
|
3086
|
+
properties: properties
|
|
3087
|
+
});
|
|
3088
|
+
|
|
3089
|
+
return event;
|
|
3090
|
+
});
|
|
3091
|
+
};
|
|
3092
|
+
|
|
3093
|
+
PostHogSentryIntegration.POSTHOG_ID_TAG = 'posthog_distinct_id';
|
|
3094
|
+
return PostHogSentryIntegration;
|
|
3095
|
+
}();
|
|
3096
|
+
|
|
3097
|
+
export { PostHog, PostHogSentryIntegration };
|
|
3000
3098
|
//# sourceMappingURL=index.esm.js.map
|