Backport: chief-pig -> rh-test (commits: f2952e9ef2 5d7321e23a 75857b35b5 bf03253709 df68b56483 )

This commit is contained in:
Benjamin Lu
2025-10-31 23:59:03 -07:00
parent 2383a38aa0
commit 7b8e73a0dd
4 changed files with 115 additions and 0 deletions

View File

@@ -4,9 +4,11 @@ import { compare, valid } from 'semver'
import { ref } from 'vue'
import type { SettingParams } from '@/platform/settings/types'
import { useTelemetry } from '@/platform/telemetry'
import type { Settings } from '@/schemas/apiSchema'
import { api } from '@/scripts/api'
import { app } from '@/scripts/app'
import { useDialogStore } from '@/stores/dialogStore'
import type { TreeNode } from '@/types/treeExplorerTypes'
export const getSettingInfo = (setting: SettingParams) => {
@@ -73,6 +75,39 @@ export const useSettingStore = defineStore('setting', () => {
onChange(settingsById.value[key], newValue, oldValue)
settingValues.value[key] = newValue
await api.storeSetting(key, newValue)
try {
const dialogStore = useDialogStore()
if (dialogStore.isDialogOpen('global-settings')) {
const telemetry = useTelemetry()
const settingParameter = settingsById.value[key]
const { category, subCategory } = getSettingInfo(
settingParameter ??
({
id: String(key)
} as unknown as SettingParams)
)
const inputType = (() => {
const settingType = settingParameter?.type
if (!settingType) return undefined
return typeof settingType === 'function'
? 'custom'
: String(settingType)
})()
telemetry?.trackSettingChanged({
setting_id: String(key),
input_type: inputType,
category,
sub_category: subCategory,
previous_value: oldValue,
new_value: newValue
})
}
} catch (err) {
console.error('Failed to track setting change', err)
}
}
/**

View File

@@ -9,6 +9,7 @@ import type {
NodeSearchResultMetadata,
PageVisibilityMetadata,
RunButtonProperties,
SettingChangedMetadata,
SurveyResponses,
TabCountMetadata,
TelemetryEventName,
@@ -413,6 +414,10 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
this.trackEvent(TelemetryEvents.EXECUTION_SUCCESS, metadata)
}
trackSettingChanged(metadata: SettingChangedMetadata): void {
this.trackEvent(TelemetryEvents.SETTING_CHANGED, metadata)
}
getExecutionContext(): ExecutionContext {
// Try to initialize composables if not ready and not in onboarding mode
if (!this._composablesReady && !this.isOnboardingMode) {

View File

@@ -126,6 +126,18 @@ export interface TabCountMetadata {
tab_count: number
}
/**
* Settings change metadata
*/
export interface SettingChangedMetadata {
setting_id: string
input_type?: string
category?: string
sub_category?: string
previous_value?: unknown
new_value?: unknown
}
/**
* Node search metadata
*/
@@ -200,6 +212,9 @@ export interface TelemetryProvider {
trackExecutionError(metadata: ExecutionErrorMetadata): void
trackExecutionSuccess(metadata: ExecutionSuccessMetadata): void
// Settings events
trackSettingChanged(metadata: SettingChangedMetadata): void
// App lifecycle management
markAppReady?(): void
identifyUser?(userId: string): void
@@ -247,6 +262,9 @@ export const TelemetryEvents = {
// Template Filter Analytics
TEMPLATE_FILTER_CHANGED: 'app:template_filter_changed',
// Settings
SETTING_CHANGED: 'app:setting_changed',
// Execution Lifecycle
EXECUTION_START: 'execution_start',
EXECUTION_ERROR: 'execution_error',
@@ -275,3 +293,4 @@ export type TelemetryEventProperties =
| NodeSearchMetadata
| NodeSearchResultMetadata
| TemplateFilterMetadata
| SettingChangedMetadata

View File

@@ -8,6 +8,7 @@ import {
import type { SettingParams } from '@/platform/settings/types'
import { api } from '@/scripts/api'
import { app } from '@/scripts/app'
import { useDialogStore } from '@/stores/dialogStore'
// Mock the api
vi.mock('@/scripts/api', () => ({
@@ -17,6 +18,14 @@ vi.mock('@/scripts/api', () => ({
}
}))
// Mock telemetry provider
const trackSettingChanged = vi.fn()
vi.mock('@/platform/telemetry', () => ({
useTelemetry: vi.fn(() => ({
trackSettingChanged
}))
}))
// Mock the app
vi.mock('@/scripts/app', () => ({
app: {
@@ -399,6 +408,53 @@ describe('useSettingStore', () => {
)
})
it('should send telemetry when global settings dialog is visible', async () => {
const setting: SettingParams = {
id: 'main.sub.setting.name',
name: 'Telemetry Visible',
type: 'text',
defaultValue: 'default'
}
store.addSetting(setting)
const dialogStore = useDialogStore()
dialogStore.showDialog({
key: 'global-settings',
title: 'Settings',
component: {}
})
await store.set('main.sub.setting.name', 'newvalue')
expect(trackSettingChanged).toHaveBeenCalledTimes(1)
expect(trackSettingChanged).toHaveBeenCalledWith(
expect.objectContaining({
setting_id: 'main.sub.setting.name',
input_type: 'text',
category: 'main',
sub_category: 'sub',
previous_value: 'default',
new_value: 'newvalue'
})
)
})
it('should not send telemetry when global settings dialog is not visible', async () => {
const setting: SettingParams = {
id: 'main.sub.setting.name',
name: 'Telemetry Invisible',
type: 'text',
defaultValue: 'default'
}
store.addSetting(setting)
await store.set('main.sub.setting.name', 'newvalue')
expect(trackSettingChanged).not.toHaveBeenCalled()
})
describe('object mutation prevention', () => {
beforeEach(() => {
const setting: SettingParams = {