-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2c87234
commit cca013a
Showing
9 changed files
with
364 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
import express from 'express' | ||
import { PostHog } from 'posthog-node' | ||
import { PostHog, PostHogSentryIntegration } from 'posthog-node' | ||
import undici from 'undici' | ||
|
||
import * as Sentry from '@sentry/node' | ||
|
||
const app = express() | ||
|
||
const { | ||
|
@@ -23,11 +25,25 @@ const posthog = new PostHog(PH_API_KEY, { | |
|
||
posthog.debug() | ||
|
||
Sentry.init({ | ||
dsn: 'https://[email protected]/0', | ||
integrations: [new PostHogSentryIntegration(posthog)], | ||
}) | ||
|
||
app.get('/', (req, res) => { | ||
posthog.capture({ distinctId: 'EXAMPLE_APP_GLOBAL', event: 'legacy capture' }) | ||
res.send({ hello: 'world' }) | ||
}) | ||
|
||
app.get('/error', (req, res) => { | ||
Sentry.captureException(new Error('example error'), { | ||
tags: { | ||
[PostHogSentryIntegration.POSTHOG_ID_TAG]: 'EXAMPLE_APP_GLOBAL', | ||
}, | ||
}) | ||
res.send({ status: 'error!!' }) | ||
}) | ||
|
||
app.get('/user/:userId/action', (req, res) => { | ||
posthog.capture({ distinctId: req.params.userId, event: 'user did action', properties: req.params }) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,6 +109,46 @@ | |
"@nodelib/fs.scandir" "2.1.5" | ||
fastq "^1.6.0" | ||
|
||
"@sentry-internal/[email protected]": | ||
version "7.91.0" | ||
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.91.0.tgz#fbb6e1e3383e1eeee08633384e004da73ac1c37d" | ||
integrity sha512-JH5y6gs6BS0its7WF2DhySu7nkhPDfZcdpAXldxzIlJpqFkuwQKLU5nkYJpiIyZz1NHYYtW5aum2bV2oCOdDRA== | ||
dependencies: | ||
"@sentry/core" "7.91.0" | ||
"@sentry/types" "7.91.0" | ||
"@sentry/utils" "7.91.0" | ||
|
||
"@sentry/[email protected]": | ||
version "7.91.0" | ||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.91.0.tgz#229334d7f03dd5d90a17495e61ce4215ab730b2a" | ||
integrity sha512-tu+gYq4JrTdrR+YSh5IVHF0fJi/Pi9y0HZ5H9HnYy+UMcXIotxf6hIEaC6ZKGeLWkGXffz2gKpQLe/g6vy/lPA== | ||
dependencies: | ||
"@sentry/types" "7.91.0" | ||
"@sentry/utils" "7.91.0" | ||
|
||
"@sentry/node@^7.91.0": | ||
version "7.91.0" | ||
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.91.0.tgz#26bf13c3daf988f9725afd1a3cc38ba2ff90d62a" | ||
integrity sha512-hTIfSQxD7L+AKIqyjoq8CWBRkEQrrMZmA3GSZgPI5JFWBHgO0HBo5TH/8TU81oEJh6kqqHAl2ObMhmcnaFqlzg== | ||
dependencies: | ||
"@sentry-internal/tracing" "7.91.0" | ||
"@sentry/core" "7.91.0" | ||
"@sentry/types" "7.91.0" | ||
"@sentry/utils" "7.91.0" | ||
https-proxy-agent "^5.0.0" | ||
|
||
"@sentry/[email protected]": | ||
version "7.91.0" | ||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.91.0.tgz#5b68954e08986fecb0d4bef168df58eef62c32c7" | ||
integrity sha512-bcQnb7J3P3equbCUc+sPuHog2Y47yGD2sCkzmnZBjvBT0Z1B4f36fI/5WjyZhTjLSiOdg3F2otwvikbMjmBDew== | ||
|
||
"@sentry/[email protected]": | ||
version "7.91.0" | ||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.91.0.tgz#3b1a94c053c885877908cd3e1365e3d23e21a73f" | ||
integrity sha512-fvxjrEbk6T6Otu++Ax9ntlQ0sGRiwSC179w68aC3u26Wr30FAIRKqHTCCdc2jyWk7Gd9uWRT/cq+g8NG/8BfSg== | ||
dependencies: | ||
"@sentry/types" "7.91.0" | ||
|
||
"@tsconfig/node10@^1.0.7": | ||
version "1.0.9" | ||
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" | ||
|
@@ -248,6 +288,13 @@ acorn@^8.4.1, acorn@^8.9.0: | |
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" | ||
integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== | ||
|
||
agent-base@6: | ||
version "6.0.2" | ||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" | ||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== | ||
dependencies: | ||
debug "4" | ||
|
||
ajv@^6.12.4: | ||
version "6.12.6" | ||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" | ||
|
@@ -290,10 +337,10 @@ asynckit@^0.4.0: | |
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" | ||
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== | ||
|
||
axios@^1.6.0: | ||
version "1.6.0" | ||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102" | ||
integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg== | ||
axios@^1.6.2: | ||
version "1.6.3" | ||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.3.tgz#7f50f23b3aa246eff43c54834272346c396613f4" | ||
integrity sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww== | ||
dependencies: | ||
follow-redirects "^1.15.0" | ||
form-data "^4.0.0" | ||
|
@@ -424,7 +471,7 @@ [email protected]: | |
dependencies: | ||
ms "2.0.0" | ||
|
||
debug@^4.1.1, debug@^4.3.2: | ||
debug@4, debug@^4.1.1, debug@^4.3.2: | ||
version "4.3.4" | ||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" | ||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== | ||
|
@@ -810,6 +857,14 @@ [email protected]: | |
statuses "2.0.1" | ||
toidentifier "1.0.1" | ||
|
||
https-proxy-agent@^5.0.0: | ||
version "5.0.1" | ||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" | ||
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== | ||
dependencies: | ||
agent-base "6" | ||
debug "4" | ||
|
||
[email protected]: | ||
version "0.4.24" | ||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" | ||
|
@@ -1071,9 +1126,9 @@ [email protected]: | |
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== | ||
|
||
"posthog-node@file:.yalc/posthog-node": | ||
version "3.1.2" | ||
version "3.2.1" | ||
dependencies: | ||
axios "^1.6.0" | ||
axios "^1.6.2" | ||
rusha "^0.8.14" | ||
|
||
prelude-ls@^1.2.1: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './src/posthog-node' | ||
export * from './src/extensions/sentry-integration' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/** | ||
* @file Adapted from [posthog-js](https://github.com/PostHog/posthog-js/blob/8157df935a4d0e71d2fefef7127aa85ee51c82d1/src/extensions/sentry-integration.ts) with modifications for the Node SDK. | ||
*/ | ||
import { type PostHog } from '../posthog-node' | ||
|
||
// NOTE - we can't import from @sentry/types because it changes frequently and causes clashes | ||
// We only use a small subset of the types, so we can just define the integration overall and use any for the rest | ||
|
||
// import { | ||
// Event as _SentryEvent, | ||
// EventProcessor as _SentryEventProcessor, | ||
// Exception as _SentryException, | ||
// Hub as _SentryHub, | ||
// Integration as _SentryIntegration, | ||
// Primitive as _SentryPrimitive, | ||
// } from '@sentry/types' | ||
|
||
// Uncomment the above and comment the below to get type checking for development | ||
|
||
type _SentryEvent = any | ||
type _SentryEventProcessor = any | ||
type _SentryHub = any | ||
type _SentryException = any | ||
type _SentryPrimitive = any | ||
|
||
interface _SentryIntegration { | ||
name: string | ||
setupOnce(addGlobalEventProcessor: (callback: _SentryEventProcessor) => void, getCurrentHub: () => _SentryHub): void | ||
} | ||
|
||
interface PostHogSentryExceptionProperties { | ||
$sentry_event_id?: string | ||
$sentry_exception?: { values?: _SentryException[] } | ||
$sentry_exception_message?: string | ||
$sentry_exception_type?: string | ||
$sentry_tags: { [key: string]: _SentryPrimitive } | ||
$sentry_url?: string | ||
$exception_type?: string | ||
$exception_message?: string | ||
$exception_personURL?: string | ||
} | ||
|
||
/** | ||
* Integrate Sentry with PostHog. This will add a direct link to the person in Sentry, and an $exception event in PostHog. | ||
* | ||
* ### Usage | ||
* | ||
* Sentry.init({ | ||
* dsn: 'https://example', | ||
* integrations: [ | ||
* new PostHogSentryIntegration(posthog) | ||
* ] | ||
* }) | ||
* | ||
* Sentry.setTag(PostHogSentryIntegration.POSTHOG_ID_TAG, 'some distinct id'); | ||
* | ||
* @param {Object} [posthog] The posthog object | ||
* @param {string} [organization] Optional: The Sentry organization, used to send a direct link from PostHog to Sentry | ||
* @param {Number} [projectId] Optional: The Sentry project id, used to send a direct link from PostHog to Sentry | ||
* @param {string} [prefix] Optional: Url of a self-hosted sentry instance (default: https://sentry.io/organizations/) | ||
*/ | ||
export class PostHogSentryIntegration implements _SentryIntegration { | ||
public readonly name = 'posthog-node' | ||
|
||
public static readonly POSTHOG_ID_TAG = 'posthog_distinct_id' | ||
|
||
public constructor( | ||
private readonly posthog: PostHog, | ||
private readonly posthogHost?: string, | ||
private readonly organization?: string, | ||
private readonly prefix?: string | ||
) { | ||
this.posthogHost = posthog.options.host ?? 'https://app.posthog.com' | ||
} | ||
|
||
public setupOnce( | ||
addGlobalEventProcessor: (callback: _SentryEventProcessor) => void, | ||
getCurrentHub: () => _SentryHub | ||
): void { | ||
addGlobalEventProcessor((event: _SentryEvent): _SentryEvent => { | ||
if (event.exception?.values === undefined || event.exception.values.length === 0) { | ||
return event | ||
} | ||
|
||
if (!event.tags) { | ||
event.tags = {} | ||
} | ||
|
||
const sentry = getCurrentHub() | ||
|
||
// Get the PostHog user ID from a specific tag, which users can set on their Sentry scope as they need. | ||
const userId = event.tags[PostHogSentryIntegration.POSTHOG_ID_TAG] | ||
if (userId === undefined) { | ||
// 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. | ||
return event | ||
} | ||
|
||
event.tags['PostHog Person URL'] = new URL(`/person/${userId}`, this.posthogHost).toString() | ||
|
||
const properties: PostHogSentryExceptionProperties = { | ||
// PostHog Exception Properties | ||
$exception_message: event.exception.values[0]?.value, | ||
$exception_type: event.exception.values[0]?.type, | ||
$exception_personURL: event.tags['PostHog Person URL'], | ||
// Sentry Exception Properties | ||
$sentry_event_id: event.event_id, | ||
$sentry_exception: event.exception, | ||
$sentry_exception_message: event.exception.values[0]?.value, | ||
$sentry_exception_type: event.exception.values[0]?.type, | ||
$sentry_tags: event.tags, | ||
} | ||
|
||
const projectId = sentry.getClient()?.getDsn()?.projectId | ||
if (this.organization !== undefined && projectId !== undefined && event.event_id !== undefined) { | ||
properties.$sentry_url = `${this.prefix ?? 'https://sentry.io/organizations'}/${ | ||
this.organization | ||
}/issues/?project=${projectId}&query=${event.event_id}` | ||
} | ||
|
||
this.posthog.capture({ event: '$exception', distinctId: userId, properties }) | ||
|
||
return event | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.