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

Enhancement - Synchroize OSS UI telemetry tracking with CLI #1037

Merged
merged 8 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 11 additions & 21 deletions agenta-web/src/components/AppSelector/AppSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {useState, useEffect, useMemo} from "react"
import {useRouter} from "next/router"
import {usePostHog} from "posthog-js/react"
import {PlusOutlined} from "@ant-design/icons"
import {Input, Modal, ConfigProvider, theme, Spin, Card, Button, notification, Divider} from "antd"
import AppCard from "./AppCard"
Expand All @@ -12,7 +11,6 @@ import Welcome from "./Welcome"
import {getApikeys, isAppNameInputValid, isDemo} from "@/lib/helpers/utils"
import {
createAndStartTemplate,
getProfile,
getTemplates,
removeApp,
waitForAppToStart,
Expand All @@ -25,6 +23,7 @@ import {createUseStyles} from "react-jss"
import {useAppsData} from "@/contexts/app.context"
import {useProfileData} from "@/contexts/profile.context"
import CreateAppStatusModal from "./modals/CreateAppStatusModal"
import {usePostHogAg} from "@/hooks/usePostHogAg"

type StyleProps = {
themeMode: "dark" | "light"
Expand Down Expand Up @@ -97,15 +96,15 @@ const timeout = isDemo() ? 60000 : 30000

const AppSelector: React.FC = () => {
const router = useRouter()
const posthog = usePostHog()
const posthog = usePostHogAg()
const {appTheme} = useAppTheme()
const classes = useStyles({themeMode: appTheme} as StyleProps)
const [isCreateAppModalOpen, setIsCreateAppModalOpen] = useState(false)
const [isCreateAppFromTemplateModalOpen, setIsCreateAppFromTemplateModalOpen] = useState(false)
const [isWriteAppModalOpen, setIsWriteAppModalOpen] = useState(false)
const [isMaxAppModalOpen, setIsMaxAppModalOpen] = useState(false)
const [templates, setTemplates] = useState<Template[]>([])

const {user} = useProfileData()
const [templateMessage, setTemplateMessage] = useState("")
const [templateId, setTemplateId] = useState<string | undefined>(undefined)
const [isInputTemplateModalOpen, setIsInputTemplateModalOpen] = useState<boolean>(false)
Expand All @@ -120,7 +119,6 @@ const AppSelector: React.FC = () => {
appId: undefined,
})

const trackingEnabled = process.env.NEXT_PUBLIC_TELEMETRY_TRACKING_ENABLED === "true"
const showCreateAppModal = async () => {
setIsCreateAppModalOpen(true)
}
Expand Down Expand Up @@ -204,27 +202,19 @@ const AppSelector: React.FC = () => {
orgId: selectedOrg?.id!,
providerKey: isDemo() ? "" : (providerKeys as string),
timeout,
onStatusChange: (status, details, appId) => {
onStatusChange: async (status, details, appId) => {
setStatusData((prev) => ({status, details, appId: appId || prev.appId}))
if (["error", "bad_request", "timeout", "success"].includes(status))
setFetchingTemplate(false)
if (status === "success") {
mutate()

if (trackingEnabled) {
// Get user profile
getProfile().then((res) => {
// Update distinct_id and track successfully app variant deployment
posthog?.identify(res?.data?.id)
posthog?.capture("app_deployment", {
properties: {
app_id: appId,
environment: "UI",
deployed_by: res?.data?.id,
},
})
})
}
posthog.capture("app_deployment", {
properties: {
app_id: appId,
environment: "UI",
deployed_by: user?.id,
},
})
}
},
})
Expand Down
3 changes: 3 additions & 0 deletions agenta-web/src/components/Playground/Views/ParametersView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {ModelParameters, ObjectParameters, StringParameters} from "./ParametersC
import PublishVariantModal from "./PublishVariantModal"
import {removeVariant} from "@/lib/services/api"
import {CloudUploadOutlined, DeleteOutlined, SaveOutlined} from "@ant-design/icons"
import {usePostHogAg} from "@/hooks/usePostHogAg"

interface Props {
variant: Variant
Expand Down Expand Up @@ -70,6 +71,7 @@ const ParametersView: React.FC<Props> = ({
tabID,
}) => {
const classes = useStyles()
const posthog = usePostHogAg()
const [messageApi, contextHolder] = message.useMessage()
const [isPublishModalOpen, setPublishModalOpen] = useState(false)
const isVariantExisting = !!variant.variantId
Expand Down Expand Up @@ -106,6 +108,7 @@ const ParametersView: React.FC<Props> = ({
onStateChange(false)
res(true)
})
posthog.capture("variant_saved", {variant_id: variant.variantId})
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {usePostHogAg} from "@/hooks/usePostHogAg"
import {Environment, Variant} from "@/lib/Types"
import {fetchEnvironments, publishVariant} from "@/lib/services/api"
import {Button, Checkbox, Modal, Space, Typography, message} from "antd"
Expand Down Expand Up @@ -35,6 +36,7 @@ const PublishVariantModal: React.FC<Props> = ({
setSelectedEnvs([])
}
const router = useRouter()
const posthog = usePostHogAg()
const appId = router.query.app_id as string

const [selectedEnvs, setSelectedEnvs] = useState<string[]>([])
Expand All @@ -55,6 +57,7 @@ const PublishVariantModal: React.FC<Props> = ({
closeModal()
await loadEnvironments()
message.success(`Published ${variant.variantName} to ${envName}`)
posthog.capture("app_deployed", {app_id: appId, environment: envName})
})
}

Expand Down
3 changes: 3 additions & 0 deletions agenta-web/src/contexts/profile.context.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {usePostHogAg} from "@/hooks/usePostHogAg"
import {useSession} from "@/hooks/useSession"
import useStateCallback from "@/hooks/useStateCallback"
import {isDemo} from "@/lib/helpers/utils"
Expand Down Expand Up @@ -54,6 +55,7 @@ const profileContextValues = {...initialValues}
export const getProfileValues = () => profileContextValues

const ProfileContextProvider: React.FC<PropsWithChildren> = ({children}) => {
const posthog = usePostHogAg()
const router = useRouter()
const [user, setUser] = useState<User | null>(null)
const [orgs, setOrgs] = useState<Org[]>([])
Expand All @@ -65,6 +67,7 @@ const ProfileContextProvider: React.FC<PropsWithChildren> = ({children}) => {
setLoading(true)
Promise.all([getProfile(), getOrgsList()])
.then(([profile, orgs]) => {
posthog.identify()
setUser(profile.data)
setOrgs(orgs.data)
setSelectedOrg(
Expand Down
34 changes: 34 additions & 0 deletions agenta-web/src/hooks/usePostHogAg.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {useProfileData} from "@/contexts/profile.context"
import {isDemo} from "@/lib/helpers/utils"
import {usePostHog} from "posthog-js/react"
import {useLayoutEffect} from "react"

export const usePostHogAg = () => {
const trackingEnabled = process.env.NEXT_PUBLIC_TELEMETRY_TRACKING_ENABLED === "true"
const {user} = useProfileData()
const posthog = usePostHog()

const _id = isDemo() ? user?.email : user?.id

const capture: typeof posthog.capture = (...args) => {
if (trackingEnabled && user?.id) {
posthog.capture(...args)
}
}

const identify: typeof posthog.identify = (id, ...args) => {
if (trackingEnabled && user?.id) {
posthog.identify(_id || id, ...args)
}
}

useLayoutEffect(() => {
if (!trackingEnabled) posthog.opt_out_capturing()
}, [trackingEnabled])

useLayoutEffect(() => {
if (posthog.get_distinct_id() !== _id) identify()
}, [user?.id])

return {...posthog, identify, capture}
}
2 changes: 2 additions & 0 deletions agenta-web/src/hooks/useSession.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {useProfileData} from "@/contexts/profile.context"
import {isDemo} from "@/lib/helpers/utils"
import {useRouter} from "next/router"
import posthog from "posthog-js"
import {useSessionContext} from "supertokens-auth-react/recipe/session"
import {signOut} from "supertokens-auth-react/recipe/thirdpartypasswordless"

Expand All @@ -17,6 +18,7 @@ export const useSession: () => {loading: boolean; doesSessionExist: boolean; log
logout: () => {
signOut()
.then(() => {
posthog.reset()
reset()
router.push("/auth")
})
Expand Down
20 changes: 18 additions & 2 deletions agenta-web/src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import "@/styles/globals.css"
import posthog from "posthog-js"
import {useEffect} from "react"
import type {AppProps} from "next/app"
import {useRouter} from "next/router"

import posthog from "posthog-js"
import {PostHogProvider} from "posthog-js/react"

import "@/styles/globals.css"
import Layout from "@/components/Layout/Layout"
import ThemeContextProvider from "@/components/Layout/ThemeContextProvider"
import AppContextProvider from "@/contexts/app.context"
Expand All @@ -16,10 +20,22 @@ if (typeof window !== "undefined") {
if (process.env.NODE_ENV === "development") posthog.debug()
},
capture_pageview: false,
persistence: "localStorage+cookie",
})
}

export default function App({Component, pageProps}: AppProps) {
const router = useRouter()

useEffect(() => {
const handleRouteChange = () =>
posthog.capture("$pageview", {$current_url: window.location.href})
router.events.on("routeChangeComplete", handleRouteChange)

return () => {
router.events.off("routeChangeComplete", handleRouteChange)
}
}, [])
return (
<PostHogProvider client={posthog}>
<ThemeContextProvider>
Expand Down
Loading