From 7ee0a6ddc564dd8de08b9d6b70caf9326be8ef2e Mon Sep 17 00:00:00 2001 From: David Newell Date: Tue, 10 Dec 2024 15:35:15 +0000 Subject: [PATCH 01/11] chore: create event when issue created --- rust/cymbal/src/issue_resolution.rs | 44 +++++++++++++++++++++++++++++ rust/cymbal/src/lib.rs | 9 +++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/rust/cymbal/src/issue_resolution.rs b/rust/cymbal/src/issue_resolution.rs index b80c8d17d9b36..03a4c08359c22 100644 --- a/rust/cymbal/src/issue_resolution.rs +++ b/rust/cymbal/src/issue_resolution.rs @@ -1,8 +1,11 @@ +use common_types::ClickHouseEvent; +use rdkafka::producer::FutureProducer; use sqlx::postgres::any::AnyConnectionBackend; use uuid::Uuid; use crate::{ error::UnhandledError, + hack::kafka::{send_keyed_iter_to_kafka, KafkaContext}, types::{FingerprintedErrProps, OutputErrProps}, }; @@ -138,6 +141,8 @@ pub async fn resolve_issue<'c, A>( con: A, team_id: i32, fingerprinted: FingerprintedErrProps, + producer: &FutureProducer, + events_topic: &str, ) -> Result where A: sqlx::Acquire<'c, Database = sqlx::Postgres>, @@ -179,7 +184,46 @@ where conn.rollback().await?; } else { conn.commit().await?; + produce_issue_creation_event(team_id, producer, events_topic).await?; } Ok(fingerprinted.to_output(issue_override.issue_id)) } + +pub async fn produce_issue_creation_event( + team_id: i32, + producer: &FutureProducer, + topic: &str, +) -> Result<(), UnhandledError> { + let props = serde_json::json!({ + "uuid": Uuid::now_v7(), + "team_id": team_id, + "event": "$exception_issue_created" + }); + + let event: ClickHouseEvent = serde_json::from_value(props)?; + + send_keyed_iter_to_kafka(producer, topic, |ev| Some(ev.uuid.to_string()), &[event]) + .await + .expect("Failed to send event to Kafka"); + + Ok(()) + + // pub project_id: i64, + // pub distinct_id: String, + // #[serde(skip_serializing_if = "Option::is_none")] + // pub properties: Option, + // #[serde(skip_serializing_if = "Option::is_none")] + // pub person_id: Option, + // // TODO: verify timestamp format + // pub timestamp: String, + // // TODO: verify timestamp format + // pub created_at: String, + // pub elements_chain: String, + // // TODO: verify timestamp format + // #[serde(skip_serializing_if = "Option::is_none")] + // pub person_created_at: Option, + // #[serde(skip_serializing_if = "Option::is_none")] + // pub person_properties: Option, + // pub person_mode: PersonMode, +} diff --git a/rust/cymbal/src/lib.rs b/rust/cymbal/src/lib.rs index ed5720148fc9c..d8cf8a314d3d2 100644 --- a/rust/cymbal/src/lib.rs +++ b/rust/cymbal/src/lib.rs @@ -53,7 +53,14 @@ pub async fn handle_event( props.exception_list = results; let fingerprinted = props.to_fingerprinted(fingerprint.clone()); - let mut output = resolve_issue(&context.pool, event.team_id, fingerprinted).await?; + let mut output = resolve_issue( + &context.pool, + event.team_id, + fingerprinted, + &context.kafka_producer, + &context.config.events_topic, + ) + .await?; // TODO - I'm not sure we actually want to do this? Maybe junk drawer stuff should end up in clickhouse, and // be directly queryable by users? Stripping it for now, so it only ends up in postgres From 931c312fbbfd89f3d86c8e8915ab2a9bd04427b2 Mon Sep 17 00:00:00 2001 From: David Newell Date: Wed, 12 Feb 2025 16:02:56 +0000 Subject: [PATCH 02/11] configuration ui --- .../alerting/ErrorTrackingAlerting.tsx | 87 ++++-- .../hogfunctions/HogFunctionConfiguration.tsx | 261 ++++++++++-------- .../hogfunctions/HogFunctionInputs.tsx | 22 +- frontend/src/types.ts | 1 + .../cdp/templates/hog_function_template.py | 4 +- posthog/cdp/templates/slack/template_slack.py | 31 +++ 6 files changed, 248 insertions(+), 158 deletions(-) diff --git a/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx b/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx index 1f3329017edeb..58a52fba3cf81 100644 --- a/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx +++ b/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx @@ -1,32 +1,65 @@ -import { LemonButton } from '@posthog/lemon-ui' -import { PageHeader } from 'lib/components/PageHeader' -import { urls } from 'scenes/urls' +import { LemonCollapse, LemonSwitch } from '@posthog/lemon-ui' +import { useActions, useValues } from 'kea' +import { useEffect, useState } from 'react' +import { HogFunctionConfiguration } from 'scenes/pipeline/hogfunctions/HogFunctionConfiguration' +import { hogFunctionListLogic } from 'scenes/pipeline/hogfunctions/list/hogFunctionListLogic' export function ErrorTrackingAlerting(): JSX.Element { - return ( - <> - - Setup alert - - } - /> + const [activeKey, setActiveKey] = useState<'issue-created' | undefined>(undefined) + const logic = hogFunctionListLogic({ + type: 'internal_destination', + forceFilters: { filters: { type: ['error-tracking-issue-created'] } }, + }) + const { hogFunctions } = useValues(logic) + const { loadHogFunctions } = useActions(logic) + + const issueCreatedFunction = hogFunctions.find((f) => f.template?.id === 'template-error-tracking-alert') - {/* - */} - + useEffect(() => { + loadHogFunctions() + }, []) + + return ( + setActiveKey(k || undefined)} + panels={[ + { + key: 'issue-created', + header: ( +
+
+
Issue created
+
Notify me when a new issue occurs
+
+ { + setActiveKey('issue-created') + }} + /> +
+ ), + className: 'p-0 pb-2', + content: + activeKey === 'issue-created' || issueCreatedFunction ? ( + + ) : null, + }, + ]} + /> ) } diff --git a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx index 6f6a9962a1ed4..a6c82913bc813 100644 --- a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx +++ b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx @@ -42,6 +42,9 @@ export interface HogFunctionConfigurationProps { id?: string | null displayOptions?: { + embedded?: boolean + hidePageHeader?: boolean + hideOverview?: boolean showFilters?: boolean showExpectedVolume?: boolean showStatus?: boolean @@ -161,6 +164,9 @@ export function HogFunctionConfiguration({ return } + const embedded = displayOptions.embedded ?? false + const includeHeaderButtons = !(displayOptions.hidePageHeader ?? false) + const showOverview = !(displayOptions.hideOverview ?? false) const showFilters = displayOptions.showFilters ?? ['destination', 'internal_destination', 'site_destination', 'broadcast', 'transformation'].includes(type) @@ -180,17 +186,21 @@ export function HogFunctionConfiguration({ displayOptions.showTesting ?? ['destination', 'internal_destination', 'transformation', 'broadcast', 'email'].includes(type) + const showLeftPanel = showOverview || showExpectedVolume || showPersonsCount || showFilters + return (
- - {headerButtons} - {saveButtons} - - } - /> + {includeHeaderButtons && ( + + {headerButtons} + {saveButtons} + + } + /> + )} {type === 'destination' ? ( @@ -215,133 +225,144 @@ export function HogFunctionConfiguration({ className="space-y-3" >
-
-
-
- - {({ value, onChange }) => ( - onChange(val)} - /> - )} - + {showLeftPanel && ( +
+ {showOverview && ( +
+
+ + {({ value, onChange }) => ( + onChange(val)} + /> + )} + -
- {configuration.name} - {template && } -
+
+ {configuration.name} + {template && } +
- {showStatus && } - {showEnabled && ( - - {({ value, onChange }) => ( - onChange(!value)} - checked={value} - disabled={loading} - bordered - /> + {showStatus && } + {showEnabled && ( + + {({ value, onChange }) => ( + onChange(!value)} + checked={value} + disabled={loading} + bordered + /> + )} + )} +
+ + + + + - )} -
- - - - - - - {hogFunction?.template && !hogFunction.template.id.startsWith('template-blank-') ? ( - -

- This function was built from the template{' '} - {hogFunction.template.name}. If the template is updated, this - function is not affected unless you choose to update it. -

+ {hogFunction?.template && + !hogFunction.template.id.startsWith('template-blank-') ? ( + +

+ This function was built from the template{' '} + {hogFunction.template.name}. If the template is + updated, this function is not affected unless you choose to + update it. +

-
-
- Close -
+
+
+ Close +
- duplicateFromTemplate()} - > - New function from template - + duplicateFromTemplate()} + > + New function from template + - {templateHasChanged ? ( - resetToTemplate()}> - Update - - ) : null} + {templateHasChanged ? ( + resetToTemplate()} + > + Update + + ) : null} +
+
+ } + > +
+ + Built from template: + + {hogFunction?.template.name} + + + {templateHasChanged ? ( + Update available! + ) : null} +
-
- } - > -
- - Built from template: - {hogFunction?.template.name} - - {templateHasChanged ? ( - Update available! - ) : null} - -
- - ) : null} -
+ + ) : null} +
+ )} - {showFilters && } + {showFilters && } - {showPersonsCount && ( -
-
- Matching persons -
- {personsCount && !personsCountLoading ? ( - <> - Found{' '} - - - {personsCount ?? 0} {personsCount !== 1 ? 'people' : 'person'} - - {' '} - to send to. - - ) : personsCountLoading ? ( -
- + {showPersonsCount && ( +
+
+ Matching persons
- ) : ( -

The expected volume could not be calculated

- )} -
- )} + {personsCount && !personsCountLoading ? ( + <> + Found{' '} + + + {personsCount ?? 0} {personsCount !== 1 ? 'people' : 'person'} + + {' '} + to send to. + + ) : personsCountLoading ? ( +
+ +
+ ) : ( +

The expected volume could not be calculated

+ )} +
+ )} - {showExpectedVolume ? : null} -
+ {showExpectedVolume ? : null} +
+ )}
-
+
{usesGroups && !hasGroupsAddon ? ( diff --git a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionInputs.tsx b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionInputs.tsx index 8cbb21044fc1a..787562a6484cb 100644 --- a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionInputs.tsx +++ b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionInputs.tsx @@ -507,16 +507,18 @@ export function HogFunctionInputs({ }} > - {configuration.inputs_schema?.map((schema) => { - return ( - - ) - })} + {configuration.inputs_schema + ?.filter((i) => !i.hidden) + .map((schema) => { + return ( + + ) + })} diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 5f7747f05794c..465e0646934fa 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -4589,6 +4589,7 @@ export type HogFunctionInputSchemaType = { required?: boolean default?: any secret?: boolean + hidden?: boolean description?: string integration?: string integration_key?: string diff --git a/posthog/cdp/templates/hog_function_template.py b/posthog/cdp/templates/hog_function_template.py index f76deacc3d4e4..f6b7a9e9fdc8f 100644 --- a/posthog/cdp/templates/hog_function_template.py +++ b/posthog/cdp/templates/hog_function_template.py @@ -8,7 +8,9 @@ PluginConfig = None -SubTemplateId = Literal["early-access-feature-enrollment", "survey-response", "activity-log"] +SubTemplateId = Literal[ + "early-access-feature-enrollment", "survey-response", "activity-log", "error-tracking-issue-created" +] SUB_TEMPLATE_ID: tuple[SubTemplateId, ...] = get_args(SubTemplateId) diff --git a/posthog/cdp/templates/slack/template_slack.py b/posthog/cdp/templates/slack/template_slack.py index 3454c18381797..ef72f2993ba59 100644 --- a/posthog/cdp/templates/slack/template_slack.py +++ b/posthog/cdp/templates/slack/template_slack.py @@ -37,6 +37,7 @@ "label": "Slack workspace", "requiredScopes": "channels:read groups:read chat:write chat:write.customize", "secret": False, + "hidden": False, "required": True, }, { @@ -47,6 +48,7 @@ "label": "Channel to post to", "description": "Select the channel to post to (e.g. #general). The PostHog app must be installed in the workspace.", "secret": False, + "hidden": False, "required": True, }, { @@ -56,6 +58,7 @@ "default": ":hedgehog:", "required": False, "secret": False, + "hidden": False, }, { "key": "username", @@ -64,6 +67,7 @@ "default": "PostHog", "required": False, "secret": False, + "hidden": False, }, { "key": "blocks", @@ -96,6 +100,7 @@ ], "secret": False, "required": False, + "hidden": False, }, { "key": "text", @@ -105,6 +110,7 @@ "default": "*{person.name}* triggered event: '{event.event}'", "secret": False, "required": False, + "hidden": False, }, ], sub_templates=[ @@ -200,5 +206,30 @@ }, }, ), + HogFunctionSubTemplate( + id="error-tracking-issue-created", + name="Post to Slack on issue created", + description="", + filters={"events": [{"id": "$error_tracking_issue_created", "type": "events"}]}, + type="internal_destination", + input_schema_overrides={ + "blocks": { + "default": [ + { + "text": { + "text": "*{person.properties.email}* {event.properties.activity} {event.properties.scope} {event.properties.item_id} ", + "type": "mrkdwn", + }, + "type": "section", + } + ], + "hidden": True, + }, + "text": { + "default": "*{person.properties.email}* {event.properties.activity} {event.properties.scope} {event.properties.item_id}", + "hidden": True, + }, + }, + ), ], ) From e94e0547fc323f3eb9e07c2f0c608b9d17b1c538 Mon Sep 17 00:00:00 2001 From: David Newell Date: Wed, 12 Feb 2025 17:44:16 +0000 Subject: [PATCH 03/11] function management --- .../alerting/ErrorTrackingAlerting.tsx | 122 ++++++++++++------ 1 file changed, 79 insertions(+), 43 deletions(-) diff --git a/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx b/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx index 58a52fba3cf81..042647890f09b 100644 --- a/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx +++ b/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx @@ -1,19 +1,33 @@ -import { LemonCollapse, LemonSwitch } from '@posthog/lemon-ui' +import { LemonCollapse, LemonCollapsePanel, LemonSwitch } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { useEffect, useState } from 'react' import { HogFunctionConfiguration } from 'scenes/pipeline/hogfunctions/HogFunctionConfiguration' import { hogFunctionListLogic } from 'scenes/pipeline/hogfunctions/list/hogFunctionListLogic' +import { HogFunctionType } from '~/types' + +enum ErrorTrackingAlertTemplate { + IssueCreated = 'error-tracking-issue-created', +} + +type ErrorTrackingAlert = { type: ErrorTrackingAlertTemplate; title: string; description: string } + +const ALERTS: ErrorTrackingAlert[] = [ + { + type: ErrorTrackingAlertTemplate.IssueCreated, + title: 'Issue created', + description: 'Notify me when a new issue occurs', + }, +] + export function ErrorTrackingAlerting(): JSX.Element { - const [activeKey, setActiveKey] = useState<'issue-created' | undefined>(undefined) const logic = hogFunctionListLogic({ type: 'internal_destination', - forceFilters: { filters: { type: ['error-tracking-issue-created'] } }, + forceFilters: { filters: { type: [ErrorTrackingAlertTemplate.IssueCreated] } }, }) const { hogFunctions } = useValues(logic) - const { loadHogFunctions } = useActions(logic) - - const issueCreatedFunction = hogFunctions.find((f) => f.template?.id === 'template-error-tracking-alert') + const { loadHogFunctions, toggleEnabled } = useActions(logic) + const [activeKey, setActiveKey] = useState(undefined) useEffect(() => { loadHogFunctions() @@ -23,43 +37,65 @@ export function ErrorTrackingAlerting(): JSX.Element { setActiveKey(k || undefined)} - panels={[ - { - key: 'issue-created', - header: ( -
-
-
Issue created
-
Notify me when a new issue occurs
-
- { - setActiveKey('issue-created') - }} - /> -
- ), - className: 'p-0 pb-2', - content: - activeKey === 'issue-created' || issueCreatedFunction ? ( - - ) : null, - }, - ]} + panels={ALERTS.map(({ type }) => + panel({ + type, + hogFn: hogFunctions.find((f) => f.template?.id === `template-slack-${type}`), + active: activeKey === type, + toggleFunction: toggleEnabled, + setActiveKey, + }) + )} /> ) } + +const panel = ({ + type, + hogFn, + active, + toggleFunction, + setActiveKey, +}: { + type: ErrorTrackingAlert['type'] + hogFn?: HogFunctionType + active: boolean + toggleFunction: (hogFunction: HogFunctionType, enabled: boolean) => void + setActiveKey: (value: ErrorTrackingAlertTemplate | undefined) => void +}): LemonCollapsePanel => { + return { + key: type, + header: ( +
+
+
Issue created
+
Notify me when a new issue occurs
+
+ + hogFn ? toggleFunction(hogFn, value) : setActiveKey(value ? type : undefined) + } + /> +
+ ), + className: 'p-0 pb-2', + content: + active || hogFn ? ( + + ) : null, + } +} From cf431aaa52ed9d477a0bcb6377f067c55e976b56 Mon Sep 17 00:00:00 2001 From: David Newell Date: Thu, 13 Feb 2025 14:00:18 +0000 Subject: [PATCH 04/11] fix hog configuration --- .../hogfunctions/HogFunctionConfiguration.tsx | 255 ++++++++++-------- 1 file changed, 136 insertions(+), 119 deletions(-) diff --git a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx index a41e56c5fe033..2d7d32ba85010 100644 --- a/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx +++ b/frontend/src/scenes/pipeline/hogfunctions/HogFunctionConfiguration.tsx @@ -43,6 +43,9 @@ export interface HogFunctionConfigurationProps { id?: string | null displayOptions?: { + embedded?: boolean + hidePageHeader?: boolean + hideOverview?: boolean showFilters?: boolean showExpectedVolume?: boolean showStatus?: boolean @@ -167,6 +170,9 @@ export function HogFunctionConfiguration({ return } + const embedded = displayOptions.embedded ?? false + const includeHeaderButtons = !(displayOptions.hidePageHeader ?? false) + const showOverview = !(displayOptions.hideOverview ?? false) const showFilters = displayOptions.showFilters ?? ['destination', 'internal_destination', 'site_destination', 'broadcast'].includes(type) @@ -189,17 +195,21 @@ export function HogFunctionConfiguration({ displayOptions.showTesting ?? ['destination', 'internal_destination', 'transformation', 'broadcast', 'email'].includes(type) + const showLeftPanel = showOverview || showExpectedVolume || showPersonsCount || showFilters + return (
- - {headerButtons} - {saveButtons} - - } - /> + {includeHeaderButtons && ( + + {headerButtons} + {saveButtons} + + } + /> + )} {hogFunction?.filters?.bytecode_error ? (
@@ -216,134 +226,141 @@ export function HogFunctionConfiguration({ className="space-y-3" >
-
-
-
- - {({ value, onChange }) => ( - onChange(val)} - /> - )} - - -
- {configuration.name} - {template && } -
- - {showStatus && } - {showEnabled && ( - + {showLeftPanel && ( +
+
+
+ {({ value, onChange }) => ( - onChange(!value)} - checked={value} - disabled={loading} - bordered + onChange(val)} /> )} - )} -
- - - - - - - {isLegacyPlugin ? null : hogFunction?.template && - !hogFunction.template.id.startsWith('template-blank-') ? ( - -

- This function was built from the template{' '} - {hogFunction.template.name}. If the template is updated, this - function is not affected unless you choose to update it. -

+
+ {configuration.name} + {template && } +
-
-
- Close -
+ {showStatus && } + {showEnabled && ( + + {({ value, onChange }) => ( + onChange(!value)} + checked={value} + disabled={loading} + bordered + /> + )} + + )} +
+ + + + + + - duplicateFromTemplate()} - > - New function from template - + {isLegacyPlugin ? null : hogFunction?.template && + !hogFunction.template.id.startsWith('template-blank-') ? ( + +

+ This function was built from the template{' '} + {hogFunction.template.name}. If the template is updated, + this function is not affected unless you choose to update it. +

- {templateHasChanged ? ( - resetToTemplate()}> - Update +
+
+ Close +
+ + duplicateFromTemplate()} + > + New function from template - ) : null} + + {templateHasChanged ? ( + resetToTemplate()} + > + Update + + ) : null} +
+ } + > +
+ + Built from template: + {hogFunction?.template.name} + + {templateHasChanged ? ( + Update available! + ) : null} +
- } - > -
- - Built from template: - {hogFunction?.template.name} - - {templateHasChanged ? ( - Update available! - ) : null} - -
- - ) : null} -
+ + ) : null} +
- {showFilters && } + {showFilters && } - {showPersonsCount && ( -
-
- Matching persons -
- {personsCount && !personsCountLoading ? ( - <> - Found{' '} - - - {personsCount ?? 0} {personsCount !== 1 ? 'people' : 'person'} - - {' '} - to send to. - - ) : personsCountLoading ? ( -
- + {showPersonsCount && ( +
+
+ Matching persons
- ) : ( -

The expected volume could not be calculated

- )} -
- )} + {personsCount && !personsCountLoading ? ( + <> + Found{' '} + + + {personsCount ?? 0} {personsCount !== 1 ? 'people' : 'person'} + + {' '} + to send to. + + ) : personsCountLoading ? ( +
+ +
+ ) : ( +

The expected volume could not be calculated

+ )} +
+ )} - {showExpectedVolume ? : null} -
+ {showExpectedVolume ? : null} +
+ )}
-
+
{usesGroups && !hasGroupsAddon ? ( From babeb9ef6126d0a65198bf5d54c5dcad33e9e202 Mon Sep 17 00:00:00 2001 From: David Newell Date: Thu, 13 Feb 2025 14:02:36 +0000 Subject: [PATCH 05/11] revert files --- .../alerting/ErrorTrackingAlerting.tsx | 123 ++++-------------- rust/cymbal/src/issue_resolution.rs | 1 - 2 files changed, 27 insertions(+), 97 deletions(-) diff --git a/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx b/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx index 042647890f09b..1f3329017edeb 100644 --- a/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx +++ b/frontend/src/scenes/error-tracking/configuration/alerting/ErrorTrackingAlerting.tsx @@ -1,101 +1,32 @@ -import { LemonCollapse, LemonCollapsePanel, LemonSwitch } from '@posthog/lemon-ui' -import { useActions, useValues } from 'kea' -import { useEffect, useState } from 'react' -import { HogFunctionConfiguration } from 'scenes/pipeline/hogfunctions/HogFunctionConfiguration' -import { hogFunctionListLogic } from 'scenes/pipeline/hogfunctions/list/hogFunctionListLogic' - -import { HogFunctionType } from '~/types' - -enum ErrorTrackingAlertTemplate { - IssueCreated = 'error-tracking-issue-created', -} - -type ErrorTrackingAlert = { type: ErrorTrackingAlertTemplate; title: string; description: string } - -const ALERTS: ErrorTrackingAlert[] = [ - { - type: ErrorTrackingAlertTemplate.IssueCreated, - title: 'Issue created', - description: 'Notify me when a new issue occurs', - }, -] +import { LemonButton } from '@posthog/lemon-ui' +import { PageHeader } from 'lib/components/PageHeader' +import { urls } from 'scenes/urls' export function ErrorTrackingAlerting(): JSX.Element { - const logic = hogFunctionListLogic({ - type: 'internal_destination', - forceFilters: { filters: { type: [ErrorTrackingAlertTemplate.IssueCreated] } }, - }) - const { hogFunctions } = useValues(logic) - const { loadHogFunctions, toggleEnabled } = useActions(logic) - const [activeKey, setActiveKey] = useState(undefined) - - useEffect(() => { - loadHogFunctions() - }, []) - return ( - setActiveKey(k || undefined)} - panels={ALERTS.map(({ type }) => - panel({ - type, - hogFn: hogFunctions.find((f) => f.template?.id === `template-slack-${type}`), - active: activeKey === type, - toggleFunction: toggleEnabled, - setActiveKey, - }) - )} - /> + <> + + Setup alert + + } + /> + + {/* + */} + ) } - -const panel = ({ - type, - hogFn, - active, - toggleFunction, - setActiveKey, -}: { - type: ErrorTrackingAlert['type'] - hogFn?: HogFunctionType - active: boolean - toggleFunction: (hogFunction: HogFunctionType, enabled: boolean) => void - setActiveKey: (value: ErrorTrackingAlertTemplate | undefined) => void -}): LemonCollapsePanel => { - return { - key: type, - header: ( -
-
-
Issue created
-
Notify me when a new issue occurs
-
- - hogFn ? toggleFunction(hogFn, value) : setActiveKey(value ? type : undefined) - } - /> -
- ), - className: 'p-0 pb-2', - content: - active || hogFn ? ( - - ) : null, - } -} diff --git a/rust/cymbal/src/issue_resolution.rs b/rust/cymbal/src/issue_resolution.rs index 1d11e10602a93..73dbd34c27e73 100644 --- a/rust/cymbal/src/issue_resolution.rs +++ b/rust/cymbal/src/issue_resolution.rs @@ -247,7 +247,6 @@ where conn.rollback().await?; } else { conn.commit().await?; - produce_issue_creation_event(team_id, producer, events_topic).await?; } // This being None is /almost/ impossible, unless between the transaction above finishing and From 9d8f2092db51e2a3251c116defce2742b84f9d0b Mon Sep 17 00:00:00 2001 From: David Newell Date: Thu, 13 Feb 2025 15:11:59 +0000 Subject: [PATCH 06/11] add validation field --- posthog/cdp/validation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/posthog/cdp/validation.py b/posthog/cdp/validation.py index 96e048e934338..7f06cd689f75b 100644 --- a/posthog/cdp/validation.py +++ b/posthog/cdp/validation.py @@ -85,6 +85,7 @@ class InputsSchemaItemSerializer(serializers.Serializer): required = serializers.BooleanField(default=False) # type: ignore default = serializers.JSONField(required=False) secret = serializers.BooleanField(default=False) + hidden = serializers.BooleanField(default=False) description = serializers.CharField(required=False) integration = serializers.CharField(required=False) integration_key = serializers.CharField(required=False) From 244fc261ee22621274eb71b717faf8296b1525aa Mon Sep 17 00:00:00 2001 From: David Newell Date: Thu, 13 Feb 2025 15:30:41 +0000 Subject: [PATCH 07/11] fix tests --- posthog/cdp/test/test_validation.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/posthog/cdp/test/test_validation.py b/posthog/cdp/test/test_validation.py index c889081e0b1f8..c64dead526ba2 100644 --- a/posthog/cdp/test/test_validation.py +++ b/posthog/cdp/test/test_validation.py @@ -53,8 +53,22 @@ def test_validate_inputs_schema(self): inputs_schema = create_example_inputs_schema() assert validate_inputs_schema(inputs_schema) == snapshot( [ - {"type": "string", "key": "url", "label": "Webhook URL", "required": True, "secret": False}, - {"type": "json", "key": "payload", "label": "JSON Payload", "required": True, "secret": False}, + { + "type": "string", + "key": "url", + "label": "Webhook URL", + "required": True, + "secret": False, + "hidden": False, + }, + { + "type": "json", + "key": "payload", + "label": "JSON Payload", + "required": True, + "secret": False, + "hidden": False, + }, { "type": "choice", "key": "method", @@ -67,8 +81,16 @@ def test_validate_inputs_schema(self): ], "required": True, "secret": False, + "hidden": False, + }, + { + "type": "dictionary", + "key": "headers", + "label": "Headers", + "required": False, + "secret": False, + "hidden": False, }, - {"type": "dictionary", "key": "headers", "label": "Headers", "required": False, "secret": False}, ] ) From 6869953719f8d798eb193cb54f7b2a14c6a6c1b9 Mon Sep 17 00:00:00 2001 From: David Newell Date: Fri, 14 Feb 2025 11:39:10 +0000 Subject: [PATCH 08/11] fix tests --- posthog/cdp/templates/webhook/template_webhook.py | 5 +++++ posthog/cdp/templates/zapier/template_zapier.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/posthog/cdp/templates/webhook/template_webhook.py b/posthog/cdp/templates/webhook/template_webhook.py index 2dac56049c08d..e6163b9514092 100644 --- a/posthog/cdp/templates/webhook/template_webhook.py +++ b/posthog/cdp/templates/webhook/template_webhook.py @@ -34,6 +34,7 @@ "label": "Webhook URL", "secret": False, "required": True, + "hidden": False, }, { "key": "method", @@ -64,6 +65,7 @@ ], "default": "POST", "required": False, + "hidden": False, }, { "key": "body", @@ -72,6 +74,7 @@ "default": {"event": "{event}", "person": "{person}"}, "secret": False, "required": False, + "hidden": False, }, { "key": "headers", @@ -80,6 +83,7 @@ "secret": False, "required": False, "default": {"Content-Type": "application/json"}, + "hidden": False, }, { "key": "debug", @@ -89,6 +93,7 @@ "secret": False, "required": False, "default": False, + "hidden": False, }, ], sub_templates=[ diff --git a/posthog/cdp/templates/zapier/template_zapier.py b/posthog/cdp/templates/zapier/template_zapier.py index 129530a1bf5f3..8801d251fad15 100644 --- a/posthog/cdp/templates/zapier/template_zapier.py +++ b/posthog/cdp/templates/zapier/template_zapier.py @@ -29,6 +29,7 @@ "description": "The path of the Zapier webhook. You can create your own or use our native Zapier integration https://zapier.com/apps/posthog/integrations", "secret": False, "required": True, + "hidden": False, }, { "key": "body", @@ -53,6 +54,7 @@ }, "secret": False, "required": False, + "hidden": False, }, { "key": "debug", @@ -62,6 +64,7 @@ "secret": False, "required": False, "default": False, + "hidden": False, }, ], ) From 621e05567dce0a84105b5270e7a6736d8deb9455 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 14 Feb 2025 11:56:00 +0000 Subject: [PATCH 09/11] Update query snapshots --- posthog/test/__snapshots__/test_feature_flag.ambr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/posthog/test/__snapshots__/test_feature_flag.ambr b/posthog/test/__snapshots__/test_feature_flag.ambr index 6b548ad5e3da4..b3a37242ee880 100644 --- a/posthog/test/__snapshots__/test_feature_flag.ambr +++ b/posthog/test/__snapshots__/test_feature_flag.ambr @@ -2069,7 +2069,7 @@ FROM "posthog_cohort" INNER JOIN "posthog_team" ON ("posthog_cohort"."team_id" = "posthog_team"."id") WHERE (NOT "posthog_cohort"."deleted" - AND "posthog_team"."project_id" = 525) + AND "posthog_team"."project_id" = 528) ''' # --- # name: TestFeatureFlagMatcher.test_numeric_operator_with_cohorts_and_nested_cohorts.1 @@ -2115,7 +2115,7 @@ "posthog_grouptypemapping"."name_singular", "posthog_grouptypemapping"."name_plural" FROM "posthog_grouptypemapping" - WHERE "posthog_grouptypemapping"."project_id" = 525 + WHERE "posthog_grouptypemapping"."project_id" = 528 ''' # --- # name: TestFeatureFlagMatcher.test_numeric_operator_with_groups_and_person_flags.1 From eb8720ce84055013e7c1b7fcca55919f6fae00f5 Mon Sep 17 00:00:00 2001 From: David Newell Date: Fri, 14 Feb 2025 13:21:52 +0000 Subject: [PATCH 10/11] add type to plugin-server --- plugin-server/src/cdp/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin-server/src/cdp/types.ts b/plugin-server/src/cdp/types.ts index c0b4f4399169f..4a72f16269c57 100644 --- a/plugin-server/src/cdp/types.ts +++ b/plugin-server/src/cdp/types.ts @@ -265,6 +265,7 @@ export type HogFunctionInputSchemaType = { required?: boolean default?: any secret?: boolean + hidden?: boolean description?: string integration?: string integration_key?: string From 1bac1845e446b87acd9d666287f21effc494165b Mon Sep 17 00:00:00 2001 From: David Newell Date: Mon, 17 Feb 2025 10:59:49 +0000 Subject: [PATCH 11/11] reset snapshot --- posthog/test/__snapshots__/test_feature_flag.ambr | 8 -------- 1 file changed, 8 deletions(-) diff --git a/posthog/test/__snapshots__/test_feature_flag.ambr b/posthog/test/__snapshots__/test_feature_flag.ambr index 8c5675d3541d9..8035d369ba29d 100644 --- a/posthog/test/__snapshots__/test_feature_flag.ambr +++ b/posthog/test/__snapshots__/test_feature_flag.ambr @@ -2069,11 +2069,7 @@ FROM "posthog_cohort" INNER JOIN "posthog_team" ON ("posthog_cohort"."team_id" = "posthog_team"."id") WHERE (NOT "posthog_cohort"."deleted" -<<<<<<< HEAD - AND "posthog_team"."project_id" = 528) -======= AND "posthog_team"."project_id" = 523) ->>>>>>> master ''' # --- # name: TestFeatureFlagMatcher.test_numeric_operator_with_cohorts_and_nested_cohorts.1 @@ -2119,11 +2115,7 @@ "posthog_grouptypemapping"."name_singular", "posthog_grouptypemapping"."name_plural" FROM "posthog_grouptypemapping" -<<<<<<< HEAD - WHERE "posthog_grouptypemapping"."project_id" = 528 -======= WHERE "posthog_grouptypemapping"."project_id" = 523 ->>>>>>> master ''' # --- # name: TestFeatureFlagMatcher.test_numeric_operator_with_groups_and_person_flags.1