feat: track new functions behaviour (#34239)

This commit is contained in:
Pamela Chia authored and GitHub committed 2025-03-19 10:10:45 +01:00
1 parent 944adfa8f6
commit db1f2b4c4e
5 files changed
+203 -8

No files matched your search

@@ -2,6 +2,8 @@ import { useParams } from 'common'
import { ScaffoldSectionTitle } from 'components/layouts/Scaffold'
import { ResourceItem } from 'components/ui/Resource/ResourceItem'
import { ResourceList } from 'components/ui/Resource/ResourceList'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useFlag } from 'hooks/ui/useFlag'
import { Code, Terminal } from 'lucide-react'
import Link from 'next/link'
@@ -28,6 +30,9 @@ export const FunctionsEmptyState = () => {
const { setAiAssistantPanel } = useAppStateSnapshot()
const edgeFunctionCreate = useFlag('edgeFunctionCreate')
const { mutate: sendEvent } = useSendEventMutation()
const org = useSelectedOrganization()
return (
<>
<Card>
@@ -48,7 +53,17 @@ export const FunctionsEmptyState = () => {
<Dialog>
<DialogTrigger asChild>
<Button type="default">View CLI Instructions</Button>
<Button
type="default"
onClick={() =>
sendEvent({
action: 'edge_function_via_cli_button_clicked',
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}
>
View CLI Instructions
</Button>
</DialogTrigger>
<DialogContent size="large">
<DialogSection padding="small">
@@ -69,7 +84,7 @@ export const FunctionsEmptyState = () => {
</p>
<Button
type="default"
onClick={() =>
onClick={() => {
setAiAssistantPanel({
open: true,
initialInput: 'Create a new edge function that ...',
@@ -83,7 +98,12 @@ export const FunctionsEmptyState = () => {
],
},
})
}
sendEvent({
action: 'edge_function_ai_assistant_button_clicked',
properties: { origin: 'no_functions_block' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}}
>
Open Assistant
</Button>
@@ -99,7 +119,17 @@ export const FunctionsEmptyState = () => {
<p className="text-sm text-foreground-light mb-4 mt-1">
Create and edit functions directly in the browser. Download to local at any time.
</p>
<Button type="default" onClick={() => router.push(`/project/${ref}/functions/new`)}>
<Button
type="default"
onClick={() => {
router.push(`/project/${ref}/functions/new`)
sendEvent({
action: 'edge_function_via_editor_button_clicked',
properties: { origin: 'no_functions_block' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}}
>
Open Editor
</Button>
</div>
@@ -116,7 +146,13 @@ export const FunctionsEmptyState = () => {
<ResourceItem
key={template.name}
media={<Code strokeWidth={1.5} size={16} className="-translate-y-[9px]" />}
onClick={() => {}}
onClick={() => {
sendEvent({
action: 'edge_function_template_clicked',
properties: { templateName: template.name, origin: 'functions_page' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}}
>
<Link href={`/project/${ref}/functions/new?template=${template.value}`}>
<p>{template.name}</p>
@@ -2,12 +2,14 @@ import { DragEvent, ReactNode, useState } from 'react'
import { toast } from 'sonner'
import { useParams } from 'common'
import { useEdgeFunctionDeployMutation } from 'data/edge-functions/edge-functions-deploy-mutation'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { ReportBlockContainer } from 'components/interfaces/Reports/ReportBlock/ReportBlockContainer'
import { Button, CodeBlock, cn, CodeBlockLang } from 'ui'
import { Code } from 'lucide-react'
import Link from 'next/link'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { Admonition } from 'ui-patterns'
interface EdgeFunctionBlockProps {
@@ -43,6 +45,9 @@ export const EdgeFunctionBlock = ({
const { data: settings } = useProjectSettingsV2Query({ projectRef: ref })
const { data: existingFunction } = useEdgeFunctionQuery({ projectRef: ref, slug: functionName })
const { mutate: sendEvent } = useSendEventMutation()
const org = useSelectedOrganization()
const { mutateAsync: deployFunction, isLoading: isDeploying } = useEdgeFunctionDeployMutation({
onSuccess: () => {
setIsDeployed(true)
@@ -67,6 +72,11 @@ export const EdgeFunctionBlock = ({
},
files: [{ name: 'index.ts', content: code }],
})
sendEvent({
action: 'edge_function_deploy_button_clicked',
properties: { origin: 'functions_ai_assistant' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
} catch (error) {
toast.error(
`Failed to deploy function: ${error instanceof Error ? error.message : 'Unknown error'}`
@@ -15,6 +15,8 @@ import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { DocsButton } from 'components/ui/DocsButton'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useFlag } from 'hooks/ui/useFlag'
import { useAppStateSnapshot } from 'state/app-state'
import type { NextPageWithLayout } from 'types'
@@ -43,6 +45,8 @@ const EdgeFunctionsPage: NextPageWithLayout = () => {
isSuccess,
} = useEdgeFunctionsQuery({ projectRef: ref })
const edgeFunctionCreate = useFlag('edgeFunctionCreate')
const { mutate: sendEvent } = useSendEventMutation()
const org = useSelectedOrganization()
const hasFunctions = (functions ?? []).length > 0
@@ -74,7 +78,14 @@ const EdgeFunctionsPage: NextPageWithLayout = () => {
</Dialog>
{edgeFunctionCreate && (
<DropdownMenuItem
onSelect={() => router.push(`/project/${ref}/functions/new`)}
onSelect={() => {
router.push(`/project/${ref}/functions/new`)
sendEvent({
action: 'edge_function_via_editor_button_clicked',
properties: { origin: 'secondary_action' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}}
className="gap-4"
>
<Code className="shrink-0" size={16} strokeWidth={1.5} />
@@ -106,7 +117,7 @@ const EdgeFunctionsPage: NextPageWithLayout = () => {
type="default"
className="px-1 pointer-events-auto"
icon={<AiIconAnimation size={16} />}
onClick={() =>
onClick={() => {
setAiAssistantPanel({
open: true,
initialInput: `Create a new edge function that ...`,
@@ -120,7 +131,12 @@ const EdgeFunctionsPage: NextPageWithLayout = () => {
],
},
})
}
sendEvent({
action: 'edge_function_ai_assistant_button_clicked',
properties: { origin: 'secondary_action' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}}
tooltip={{
content: {
side: 'bottom',
@@ -13,7 +13,9 @@ import EdgeFunctionsLayout from 'components/layouts/EdgeFunctionsLayout/EdgeFunc
import { PageLayout } from 'components/layouts/PageLayout/PageLayout'
import FileExplorerAndEditor from 'components/ui/FileExplorerAndEditor/FileExplorerAndEditor'
import { useEdgeFunctionDeployMutation } from 'data/edge-functions/edge-functions-deploy-mutation'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useOrgOptedIntoAi } from 'hooks/misc/useOrgOptedIntoAi'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProject } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import { BASE_PATH, IS_PLATFORM } from 'lib/constants'
@@ -103,6 +105,8 @@ const NewFunctionPage = () => {
const includeSchemaMetadata = isOptedInToAI || !IS_PLATFORM
const { setAiAssistantPanel } = useAppStateSnapshot()
const edgeFunctionCreate = useFlag('edgeFunctionCreate')
const { mutate: sendEvent } = useSendEventMutation()
const org = useSelectedOrganization()
const [files, setFiles] = useState<
{ id: number; name: string; content: string; selected?: boolean }[]
@@ -148,6 +152,11 @@ const NewFunctionPage = () => {
},
files: files.map(({ name, content }) => ({ name, content })),
})
sendEvent({
action: 'edge_function_deploy_button_clicked',
properties: { origin: 'functions_editor' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}
const handleChat = () => {
@@ -167,6 +176,11 @@ const NewFunctionPage = () => {
],
},
})
sendEvent({
action: 'edge_function_ai_assistant_button_clicked',
properties: { origin: 'functions_editor_chat' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}
const onSelectTemplate = (templateValue: string) => {
@@ -176,6 +190,11 @@ const NewFunctionPage = () => {
prev.map((file) => (file.selected ? { ...file, content: template.content } : file))
)
setOpen(false)
sendEvent({
action: 'edge_function_template_clicked',
properties: { templateName: template.name, origin: 'editor_page' },
groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
})
}
}
+114
View File
@@ -1048,6 +1048,115 @@ export interface ReportsDatabaseGrafanaBannerClickedEvent {
}
}
/**
* User clicked the deploy button for an Edge Function.
*
* @group Events
* @source studio
* @page /dashboard/project/{ref}/functions/new
*/
export interface EdgeFunctionDeployButtonClickedEvent {
action: 'edge_function_deploy_button_clicked'
properties: {
/**
* Click on Deploy can either happen:
* 1. in the functions editor page
* 2. in the chat button in the functions editor
*/
origin: 'functions_editor' | 'functions_ai_assistant'
}
groups: {
project: string
organization: string
}
}
/**
* User clicked the AI Assistant button to create an Edge Function.
*
* @group Events
* @source studio
* @page /dashboard/project/{ref}/functions
*/
export interface EdgeFunctionAiAssistantButtonClickedEvent {
action: 'edge_function_ai_assistant_button_clicked'
properties: {
/**
* Click on AI Assistant can either happen:
* 1. on the main block when there are no functions
* 2. in the secondary action section of the page
* 3. on the chat button in the functions editor
*/
origin: 'no_functions_block' | 'secondary_action' | 'functions_editor_chat'
}
groups: {
project: string
organization: string
}
}
/**
* User clicked the button to go to the functions editor page to create an edge function.
*
* @group Events
* @source studio
* @page /dashboard/project/{ref}/functions
*/
export interface EdgeFunctionViaEditorButtonClickedEvent {
action: 'edge_function_via_editor_button_clicked'
properties: {
/**
* Click on Via Editor can either happen:
* 1. on the main block when there are no functions
* 2. in the secondary action section of the page
*/
origin: 'no_functions_block' | 'secondary_action'
}
groups: {
project: string
organization: string
}
}
/**
* User clicked on an Edge Function template.
*
* @group Events
* @source studio
* @page /dashboard/project/{ref}/functions
*/
export interface EdgeFunctionTemplateClickedEvent {
action: 'edge_function_template_clicked'
properties: {
templateName: string
/**
* Where the edge function template was clicked from:
* 1. functions page
* 2. editor page
*/
origin: 'functions_page' | 'editor_page'
}
groups: {
project: string
organization: string
}
}
/**
* User clicked the button to create an edge function via CLI.
*
* @group Events
* @source studio
* @page /dashboard/project/{ref}/functions
*/
export interface EdgeFunctionViaCliButtonClickedEvent {
action: 'edge_function_via_cli_button_clicked'
groups: {
project: string
organization: string
}
}
/**
* @hidden
*/
@@ -1113,3 +1222,8 @@ export type TelemetryEvent =
| StudioPricingPlanCtaClickedEvent
| StudioPricingSidePanelOpenedEvent
| ReportsDatabaseGrafanaBannerClickedEvent
| EdgeFunctionDeployButtonClickedEvent
| EdgeFunctionAiAssistantButtonClickedEvent
| EdgeFunctionViaEditorButtonClickedEvent
| EdgeFunctionTemplateClickedEvent
| EdgeFunctionViaCliButtonClickedEvent