Skip to content

Commit

Permalink
Merge branch 'master' into feat/dead-clicks-server-side
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra committed Oct 30, 2024
2 parents 32ca67d + a9a77ac commit b8f63cc
Show file tree
Hide file tree
Showing 14 changed files with 303 additions and 332 deletions.
52 changes: 27 additions & 25 deletions frontend/src/loadPostHogJS.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,38 @@ export function loadPostHogJS(): void {
bootstrap: window.POSTHOG_USER_IDENTITY_WITH_FLAGS ? window.POSTHOG_USER_IDENTITY_WITH_FLAGS : {},
opt_in_site_apps: true,
api_transport: 'fetch',
loaded: (posthog) => {
if (posthog.sessionRecording) {
posthog.sessionRecording._forceAllowLocalhostNetworkCapture = true
loaded: (loadedInstance) => {
if (loadedInstance.sessionRecording) {
loadedInstance.sessionRecording._forceAllowLocalhostNetworkCapture = true
}

if (window.IMPERSONATED_SESSION) {
posthog.opt_out_capturing()
loadedInstance.sessionManager?.resetSessionId()
loadedInstance.opt_out_capturing()
} else {
posthog.opt_in_capturing()
loadedInstance.opt_in_capturing()
}

const Cypress = (window as any).Cypress

if (Cypress) {
Object.entries(Cypress.env()).forEach(([key, value]) => {
if (key.startsWith('POSTHOG_PROPERTY_')) {
loadedInstance.register_for_session({
[key.replace('POSTHOG_PROPERTY_', 'E2E_TESTING_').toLowerCase()]: value,
})
}
})
}

// This is a helpful flag to set to automatically reset the recording session on load for testing multiple recordings
const shouldResetSessionOnLoad = loadedInstance.getFeatureFlag(FEATURE_FLAGS.SESSION_RESET_ON_LOAD)
if (shouldResetSessionOnLoad) {
loadedInstance.sessionManager?.resetSessionId()
}

// Make sure we have access to the object in window for debugging
window.posthog = loadedInstance
},
scroll_root_selector: ['main', 'html'],
autocapture: {
Expand All @@ -52,26 +74,6 @@ export function loadPostHogJS(): void {
: undefined,
})
)

const Cypress = (window as any).Cypress

if (Cypress) {
Object.entries(Cypress.env()).forEach(([key, value]) => {
if (key.startsWith('POSTHOG_PROPERTY_')) {
posthog.register_for_session({
[key.replace('POSTHOG_PROPERTY_', 'E2E_TESTING_').toLowerCase()]: value,
})
}
})
}

// This is a helpful flag to set to automatically reset the recording session on load for testing multiple recordings
const shouldResetSessionOnLoad = posthog.getFeatureFlag(FEATURE_FLAGS.SESSION_RESET_ON_LOAD)
if (shouldResetSessionOnLoad) {
posthog.sessionManager?.resetSessionId()
}
// Make sure we have access to the object in window for debugging
window.posthog = posthog
} else {
posthog.init('fake token', {
autocapture: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ export function HogFunctionFilters(): JSX.Element {
value: '{person.id}',
label: 'Run once per person per interval',
},
{
value: '{concat(person.id, event.event)}',
label: 'Run once per person per event name per interval',
},
]}
value={value?.hash ?? null}
onChange={(val) =>
Expand Down
12 changes: 10 additions & 2 deletions plugin-server/tests/cdp/examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -708,8 +708,16 @@ export const HOG_MASK_EXAMPLES: Record<string, Pick<HogFunctionType, 'masking'>>
person: {
masking: {
ttl: 30,
hash: '{person.uuid}',
bytecode: ['_h', 32, 'uuid', 32, 'person', 1, 2],
hash: '{person.id}',
bytecode: ['_h', 32, 'id', 32, 'person', 1, 2],
threshold: null,
},
},
personAndEvent: {
masking: {
ttl: 30,
hash: '{concat(person.id, event.event)}',
bytecode: ['_H', 1, 32, 'id', 32, 'person', 1, 2, 32, 'event', 32, 'event', 1, 2, 2, 'concat', 2],
threshold: null,
},
},
Expand Down
37 changes: 29 additions & 8 deletions plugin-server/tests/cdp/hog-masker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ describe('HogMasker', () => {
describe('ttl', () => {
let hogFunctionPerson: HogFunctionType
let hogFunctionAll: HogFunctionType
let hogFunctionPersonAndEvent: HogFunctionType

beforeEach(() => {
hogFunctionPerson = createHogFunction({
Expand All @@ -127,6 +128,13 @@ describe('HogMasker', () => {
},
})

hogFunctionPersonAndEvent = createHogFunction({
masking: {
...HOG_MASK_EXAMPLES.personAndEvent.masking!,
ttl: 1,
},
})

hogFunctionAll = createHogFunction({
masking: {
...HOG_MASK_EXAMPLES.all.masking!,
Expand All @@ -145,20 +153,33 @@ describe('HogMasker', () => {
})

it('should mask with custom hog hash', async () => {
const globalsPerson1 = createHogExecutionGlobals({ person: { uuid: '1' } as any })
const globalsPerson2 = createHogExecutionGlobals({ person: { uuid: '2' } as any })
const globals1 = createHogExecutionGlobals({
person: { id: '1' } as any,
event: { event: '$pageview' } as any,
})
const globals2 = createHogExecutionGlobals({
person: { id: '2' } as any,
event: { event: '$autocapture' } as any,
})
const globals3 = createHogExecutionGlobals({
person: { id: '2' } as any,
event: { event: '$pageview' } as any,
})

const invocations = [
createInvocation(hogFunctionPerson, globalsPerson1),
createInvocation(hogFunctionAll, globalsPerson1),
createInvocation(hogFunctionPerson, globalsPerson2),
createInvocation(hogFunctionAll, globalsPerson2),
createInvocation(hogFunctionPerson, globals1),
createInvocation(hogFunctionAll, globals1),
createInvocation(hogFunctionPersonAndEvent, globals1),
createInvocation(hogFunctionPerson, globals2),
createInvocation(hogFunctionAll, globals2),
createInvocation(hogFunctionPersonAndEvent, globals2),
createInvocation(hogFunctionPersonAndEvent, globals3),
]
const res = await masker.filterByMasking(invocations)
expect(res.masked.length).toEqual(1)
expect(res.notMasked.length).toEqual(3)
expect(res.notMasked.length).toEqual(6)
const res2 = await masker.filterByMasking(invocations)
expect(res2.masked.length).toEqual(4)
expect(res2.masked.length).toEqual(7)
expect(res2.notMasked.length).toEqual(0)
})

Expand Down
Loading

0 comments on commit b8f63cc

Please sign in to comment.