Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(messaging): different types of hog functions #25788

Merged
merged 26 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
043c3e2
feat(messaging): different types of hog functions
mariusandra Oct 24, 2024
e3fb034
merge
mariusandra Oct 24, 2024
a66cce4
mailchimp type
mariusandra Oct 24, 2024
324df0a
fix
mariusandra Oct 24, 2024
dcb30a2
test
mariusandra Oct 24, 2024
ffbb89a
more fixes
mariusandra Oct 24, 2024
9b9696c
remove "shared"
mariusandra Oct 24, 2024
9b06f4d
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
d02b402
test that we can list
mariusandra Oct 24, 2024
70f4763
Merge branch 'messaging-part-1' of github.com:PostHog/posthog into me…
mariusandra Oct 24, 2024
5177554
fix
mariusandra Oct 24, 2024
108df5d
was not used
mariusandra Oct 24, 2024
0a64fb5
test for destinations
mariusandra Oct 24, 2024
955ca6d
Merge branch 'master' into messaging-part-1
mariusandra Oct 24, 2024
1bb9729
Update query snapshots
github-actions[bot] Oct 24, 2024
24b8894
Update query snapshots
github-actions[bot] Oct 24, 2024
3508529
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
129282c
Update query snapshots
github-actions[bot] Oct 24, 2024
22f230b
Merge branch 'master' into messaging-part-1
mariusandra Oct 24, 2024
fd78b10
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
a8c34f2
Merge branch 'master' into messaging-part-1
mariusandra Oct 24, 2024
0ff33b4
went down
mariusandra Oct 24, 2024
f9b46a7
make it reversable
mariusandra Oct 24, 2024
183f43e
Merge branch 'messaging-part-1' of github.com:PostHog/posthog into me…
mariusandra Oct 24, 2024
5e47b5f
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
581cbbd
Update UI snapshots for `chromium` (1)
github-actions[bot] Oct 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 10 additions & 4 deletions frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import {
HogFunctionStatus,
HogFunctionTemplateType,
HogFunctionType,
HogFunctionTypeType,
InsightModel,
IntegrationType,
ListOrganizationMembersParams,
Expand Down Expand Up @@ -1744,7 +1745,10 @@ const api = {
},
},
hogFunctions: {
async list(params?: { filters?: any }): Promise<PaginatedResponse<HogFunctionType>> {
async list(params?: {
filters?: any
type?: HogFunctionTypeType
}): Promise<PaginatedResponse<HogFunctionType>> {
return await new ApiRequest().hogFunctions().withQueryString(params).get()
},
async get(id: HogFunctionType['id']): Promise<HogFunctionType> {
Expand Down Expand Up @@ -1774,9 +1778,11 @@ const api = {
): Promise<AppMetricsTotalsV2Response> {
return await new ApiRequest().hogFunction(id).withAction('metrics/totals').withQueryString(params).get()
},

async listTemplates(): Promise<PaginatedResponse<HogFunctionTemplateType>> {
return await new ApiRequest().hogFunctionTemplates().get()
async listTemplates(type?: HogFunctionTypeType): Promise<PaginatedResponse<HogFunctionTemplateType>> {
return new ApiRequest()
.hogFunctionTemplates()
.withQueryString({ type: type ?? 'destination' })
.get()
},
async getTemplate(id: HogFunctionTemplateType['id']): Promise<HogFunctionTemplateType> {
return await new ApiRequest().hogFunctionTemplate(id).get()
Expand Down
1 change: 1 addition & 0 deletions frontend/src/scenes/actions/ActionHogFunctions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function ActionHogFunctions(): JSX.Element | null {
) : null}

<LinkedHogFunctions
type="destination"
filters={filters}
newDisabledReason={
hasCohortFilters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export function DefinitionView(props: DefinitionLogicProps = {}): JSX.Element {
<p>Get notified via Slack, webhooks or more whenever this event is captured.</p>

<LinkedHogFunctions
type="destination"
filters={{
events: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element {
<h3>Notifications</h3>
<p>Get notified when people opt in or out of your feature.</p>
<LinkedHogFunctions
type="destination"
filters={destinationFilters}
subTemplateId="early_access_feature_enrollment"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export const pipelineDestinationsLogic = kea<pipelineDestinationsLogicType>([
{
loadHogFunctions: async () => {
// TODO: Support pagination?
return (await api.hogFunctions.list()).results
return (await api.hogFunctions.list({ type: 'destination' })).results
},

deleteNodeHogFunction: async ({ destination }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ import { HogFunctionTest, HogFunctionTestPlaceholder } from './HogFunctionTest'

const EVENT_THRESHOLD_ALERT_LEVEL = 8000

export function HogFunctionConfiguration({ templateId, id }: { templateId?: string; id?: string }): JSX.Element {
export interface HogFunctionConfigurationProps {
templateId?: string | null
id?: string | null
}

export function HogFunctionConfiguration({ templateId, id }: HogFunctionConfigurationProps): JSX.Element {
const logicProps = { templateId, id }
const logic = hogFunctionConfigurationLogic(logicProps)
const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const HOG_TEMPLATE: HogFunctionTemplateType = {
],
status: 'beta',
id: 'template-webhook',
type: 'destination',
name: 'HTTP Webhook',
description: 'Sends a webhook templated by the incoming event data',
hog: "let res := fetch(inputs.url, {\n 'headers': inputs.headers,\n 'body': inputs.body,\n 'method': inputs.method\n});\n\nif (inputs.debug) {\n print('Response', res.status, res.body);\n}",
Expand Down Expand Up @@ -170,6 +171,7 @@ describe('hogFunctionConfigurationLogic', () => {
expect(logic.values.template).toEqual(HOG_TEMPLATE)
expect(logic.values.configuration).toEqual({
name: HOG_TEMPLATE.name,
type: HOG_TEMPLATE.type,
description: HOG_TEMPLATE.description,
inputs_schema: HOG_TEMPLATE.inputs_schema,
filters: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,17 @@ import { EmailTemplate } from './email-templater/emailTemplaterLogic'
import type { hogFunctionConfigurationLogicType } from './hogFunctionConfigurationLogicType'

export interface HogFunctionConfigurationLogicProps {
templateId?: string
subTemplateId?: string
id?: string
templateId?: string | null
subTemplateId?: string | null
id?: string | null
}

export const EVENT_VOLUME_DAILY_WARNING_THRESHOLD = 1000
const UNSAVED_CONFIGURATION_TTL = 1000 * 60 * 5

const NEW_FUNCTION_TEMPLATE: HogFunctionTemplateType = {
id: 'new',
type: 'destination',
name: '',
description: '',
inputs_schema: [],
Expand Down Expand Up @@ -118,6 +119,7 @@ const templateToConfiguration = (
})

return {
type: template.type ?? 'destination',
name: subTemplate?.name ?? template.name,
description: subTemplate?.name ?? template.description,
inputs_schema: template.inputs_schema,
Expand Down Expand Up @@ -403,6 +405,10 @@ export const hogFunctionConfigurationLogic = kea<hogFunctionConfigurationLogicTy
})),
selectors(() => ({
logicProps: [() => [(_, props) => props], (props): HogFunctionConfigurationLogicProps => props],
type: [
(s) => [s.configuration, s.hogFunction],
(configuration, hogFunction) => configuration?.type ?? hogFunction?.type ?? 'loading',
],
hasAddon: [
(s) => [s.hasAvailableFeature],
(hasAvailableFeature) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { LemonButton } from '@posthog/lemon-ui'
import { useState } from 'react'

import { HogFunctionFiltersType, HogFunctionSubTemplateIdType } from '~/types'
import { HogFunctionFiltersType, HogFunctionSubTemplateIdType, HogFunctionTypeType } from '~/types'

import { HogFunctionList } from './HogFunctionsList'
import { HogFunctionTemplateList } from './HogFunctionTemplateList'

export type LinkedHogFunctionsProps = {
type: HogFunctionTypeType
filters: HogFunctionFiltersType
subTemplateId?: HogFunctionSubTemplateIdType
newDisabledReason?: string
}

export function LinkedHogFunctions({
type,
filters,
subTemplateId,
newDisabledReason,
Expand All @@ -22,6 +24,7 @@ export function LinkedHogFunctions({
return showNewDestination ? (
<HogFunctionTemplateList
defaultFilters={{}}
type={type}
forceFilters={{ filters, subTemplateId }}
extraControls={
<>
Expand All @@ -34,6 +37,7 @@ export function LinkedHogFunctions({
) : (
<HogFunctionList
forceFilters={{ filters }}
type={type}
extraControls={
<>
<LemonButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { pipelineAccessLogic } from 'scenes/pipeline/pipelineAccessLogic'
import { teamLogic } from 'scenes/teamLogic'
import { userLogic } from 'scenes/userLogic'

import { HogFunctionType } from '~/types'
import { HogFunctionType, HogFunctionTypeType } from '~/types'

import type { hogFunctionListLogicType } from './hogFunctionListLogicType'

Expand All @@ -25,6 +25,7 @@ export type HogFunctionListFilters = {
}

export type HogFunctionListLogicProps = {
type: HogFunctionTypeType
defaultFilters?: HogFunctionListFilters
forceFilters?: HogFunctionListFilters
syncFiltersWithUrl?: boolean
Expand Down Expand Up @@ -68,14 +69,15 @@ export const hogFunctionListLogic = kea<hogFunctionListLogicType>([
},
],
})),
loaders(({ values, actions }) => ({
loaders(({ values, actions, props }) => ({
hogFunctions: [
[] as HogFunctionType[],
{
loadHogFunctions: async () => {
return (
await api.hogFunctions.list({
filters: values.filters?.filters,
type: props.type,
})
).results
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { objectsEqual } from 'lib/utils'
import { pipelineAccessLogic } from 'scenes/pipeline/pipelineAccessLogic'
import { urls } from 'scenes/urls'

import { HogFunctionTemplateType, PipelineStage } from '~/types'
import { HogFunctionTemplateType, HogFunctionTypeType, PipelineStage } from '~/types'

import type { hogFunctionTemplateListLogicType } from './hogFunctionTemplateListLogicType'

Expand All @@ -22,14 +22,15 @@ export type HogFunctionTemplateListFilters = {
}

export type HogFunctionTemplateListLogicProps = {
type: HogFunctionTypeType
defaultFilters?: HogFunctionTemplateListFilters
forceFilters?: HogFunctionTemplateListFilters
syncFiltersWithUrl?: boolean
}

export const hogFunctionTemplateListLogic = kea<hogFunctionTemplateListLogicType>([
props({} as HogFunctionTemplateListLogicProps),
key((props) => (props.syncFiltersWithUrl ? 'scene' : 'default')),
key((props) => `${props.syncFiltersWithUrl ? 'scene' : 'default'}/${props.type ?? 'destination'}`),
path((id) => ['scenes', 'pipeline', 'destinationsLogic', id]),
connect({
values: [pipelineAccessLogic, ['canEnableNewDestinations'], featureFlagLogic, ['featureFlags']],
Expand All @@ -53,12 +54,12 @@ export const hogFunctionTemplateListLogic = kea<hogFunctionTemplateListLogicType
},
],
})),
loaders(() => ({
loaders(({ props }) => ({
rawTemplates: [
[] as HogFunctionTemplateType[],
{
loadHogFunctionTemplates: async () => {
return (await api.hogFunctions.listTemplates()).results
return (await api.hogFunctions.listTemplates(props.type)).results
},
},
],
Expand Down
1 change: 1 addition & 0 deletions frontend/src/scenes/surveys/SurveyView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ export function SurveyView({ id }: { id: string }): JSX.Element {
<div>
<p>Get notified whenever a survey result is submitted</p>
<LinkedHogFunctions
type="destination"
subTemplateId="survey_response"
filters={{
events: [
Expand Down
1 change: 1 addition & 0 deletions frontend/src/scenes/surveys/Surveys.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export function Surveys(): JSX.Element {
<>
<p>Get notified whenever a survey result is submitted</p>
<LinkedHogFunctions
type="destination"
subTemplateId="survey_response"
filters={{
events: [
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4505,8 +4505,11 @@ export interface HogFunctionFiltersType {
bytecode_error?: string
}

export type HogFunctionTypeType = 'destination' | 'email' | 'sms' | 'push' | 'activity' | 'alert' | 'broadcast'

export type HogFunctionType = {
id: string
type: HogFunctionTypeType
icon_url?: string
name: string
description: string
Expand Down Expand Up @@ -4543,7 +4546,7 @@ export type HogFunctionSubTemplateType = Pick<HogFunctionType, 'filters' | 'inpu

export type HogFunctionTemplateType = Pick<
HogFunctionType,
'id' | 'name' | 'description' | 'hog' | 'inputs_schema' | 'filters' | 'icon_url' | 'masking'
'id' | 'type' | 'name' | 'description' | 'hog' | 'inputs_schema' | 'filters' | 'icon_url' | 'masking'
> & {
status: HogFunctionTemplateStatus
sub_templates?: HogFunctionSubTemplateType[]
Expand Down
2 changes: 1 addition & 1 deletion latest_migrations.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ contenttypes: 0002_remove_content_type_name
ee: 0016_rolemembership_organization_member
otp_static: 0002_throttling
otp_totp: 0002_auto_20190420_0723
posthog: 0498_errortrackingissuefingerprint_and_more
posthog: 0499_hog_function_type
sessions: 0001_initial
social_django: 0010_uid_db_index
two_factor: 0007_auto_20201201_1019
2 changes: 1 addition & 1 deletion plugin-server/src/cdp/cdp-consumers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ export class CdpProcessedEventsConsumer extends CdpConsumerBase {
try {
const clickHouseEvent = JSON.parse(message.value!.toString()) as RawClickHouseEvent

if (!this.hogFunctionManager.teamHasHogFunctions(clickHouseEvent.team_id)) {
if (!this.hogFunctionManager.teamHasHogDestinations(clickHouseEvent.team_id)) {
// No need to continue if the team doesn't have any functions
return
}
Expand Down
2 changes: 1 addition & 1 deletion plugin-server/src/cdp/hog-executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export class HogExecutor {
nonMatchingFunctions: HogFunctionType[]
erroredFunctions: HogFunctionType[]
} {
const allFunctionsForTeam = this.hogFunctionManager.getTeamHogFunctions(event.project.id)
const allFunctionsForTeam = this.hogFunctionManager.getTeamHogDestinations(event.project.id)
const filtersGlobals = convertToHogFunctionFilterGlobal(event)

const nonMatchingFunctions: HogFunctionType[] = []
Expand Down
15 changes: 11 additions & 4 deletions plugin-server/src/cdp/hog-function-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ const HOG_FUNCTION_FIELDS = [
'filters',
'bytecode',
'masking',
'type',
]

const RELOAD_HOG_FUNCTION_TYPES = ['destination', 'email']

export class HogFunctionManager {
private started: boolean
private ready: boolean
Expand Down Expand Up @@ -93,6 +96,10 @@ export class HogFunctionManager {
.filter((x) => !!x) as HogFunctionType[]
}

public getTeamHogDestinations(teamId: Team['id']): HogFunctionType[] {
return this.getTeamHogFunctions(teamId).filter((x) => x.type === 'destination' || !x.type)
}

public getHogFunction(id: HogFunctionType['id']): HogFunctionType | undefined {
if (!this.ready) {
throw new Error('HogFunctionManager is not ready! Run HogFunctionManager.start() before this')
Expand All @@ -112,8 +119,8 @@ export class HogFunctionManager {
}
}

public teamHasHogFunctions(teamId: Team['id']): boolean {
return !!Object.keys(this.getTeamHogFunctions(teamId)).length
public teamHasHogDestinations(teamId: Team['id']): boolean {
return !!Object.keys(this.getTeamHogDestinations(teamId)).length
}

public async reloadAllHogFunctions(): Promise<void> {
Expand All @@ -123,9 +130,9 @@ export class HogFunctionManager {
`
SELECT ${HOG_FUNCTION_FIELDS.join(', ')}
FROM posthog_hogfunction
WHERE deleted = FALSE AND enabled = TRUE
WHERE deleted = FALSE AND enabled = TRUE AND (type is NULL or type = ANY($1))
`,
[],
[RELOAD_HOG_FUNCTION_TYPES],
'fetchAllHogFunctions'
)
).rows
Expand Down
5 changes: 4 additions & 1 deletion plugin-server/src/cdp/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export type HogFunctionInvocationSerializedCompressed = {

// Mostly copied from frontend types
export type HogFunctionInputSchemaType = {
type: 'string' | 'boolean' | 'dictionary' | 'choice' | 'json' | 'integration' | 'integration_field'
type: 'string' | 'boolean' | 'dictionary' | 'choice' | 'json' | 'integration' | 'integration_field' | 'email'
key: string
label?: string
choices?: { value: string; label: string }[]
Expand All @@ -252,8 +252,11 @@ export type HogFunctionInputSchemaType = {
integration_field?: 'slack_channel'
}

export type HogFunctionTypeType = 'destination' | 'email' | 'sms' | 'push' | 'activity' | 'alert' | 'broadcast'

export type HogFunctionType = {
id: string
type: HogFunctionTypeType
team_id: number
name: string
enabled: boolean
Expand Down
1 change: 1 addition & 0 deletions plugin-server/tests/cdp/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { insertRow } from '../helpers/sql'
export const createHogFunction = (hogFunction: Partial<HogFunctionType>) => {
const item: HogFunctionType = {
id: randomUUID(),
type: 'destination',
name: 'Hog Function',
team_id: 1,
enabled: true,
Expand Down
Loading
Loading