Compare commits

...

1 Commits

Author SHA1 Message Date
Shibo Zhou
803043c582 feat: track is_app and workflow_id on workflow open/import
Add is_app + workflow_id to the app:workflow_opened/imported events. is_app is derived from the serialized linearMode via the shared linearModeToAppMode (now exported); workflow_id comes from the loaded graph's id, matching execution_success's workflow_id.

Unlocks two App Mode metrics: '% of opened workflows that are Apps' (open_source + is_app) and the Quality denominator apps_opened (distinct app workflow_ids opened), countable in the same unit as apps_with_successful_runs.
2026-05-29 13:40:15 -07:00
4 changed files with 26 additions and 4 deletions

View File

@@ -151,6 +151,8 @@ export interface WorkflowImportMetadata {
| 'template'
| 'shared_url'
| 'unknown'
is_app?: boolean
workflow_id?: string
}
export interface EnterLinearMetadata {

View File

@@ -11,7 +11,10 @@ import { useSettingStore } from '@/platform/settings/settingStore'
import { useToastStore } from '@/platform/updates/common/toastStore'
import type { ComfyWorkflow } from '@/platform/workflow/management/stores/workflowStore'
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
import { useWorkflowService } from '@/platform/workflow/core/services/workflowService'
import {
linearModeToAppMode,
useWorkflowService
} from '@/platform/workflow/core/services/workflowService'
import { useMissingNodesErrorStore } from '@/platform/nodeReplacement/missingNodesErrorStore'
import { useExecutionErrorStore } from '@/stores/executionErrorStore'
import { useMissingModelStore } from '@/platform/missingModel/missingModelStore'
@@ -1333,3 +1336,15 @@ describe('useWorkflowService', () => {
})
})
})
describe('linearModeToAppMode', () => {
it('maps the serialized linearMode boolean to an app mode', () => {
expect(linearModeToAppMode(true)).toBe('app')
expect(linearModeToAppMode(false)).toBe('graph')
})
it('returns null when linearMode is absent or not a boolean', () => {
expect(linearModeToAppMode(undefined)).toBeNull()
expect(linearModeToAppMode('app')).toBeNull()
})
})

View File

@@ -38,7 +38,7 @@ import {
generateUUID
} from '@/utils/formatUtil'
function linearModeToAppMode(linearMode: unknown): AppMode | null {
export function linearModeToAppMode(linearMode: unknown): AppMode | null {
if (typeof linearMode !== 'boolean') return null
return linearMode ? 'app' : 'graph'
}

View File

@@ -28,7 +28,10 @@ import { useTelemetry } from '@/platform/telemetry'
import type { WorkflowOpenSource } from '@/platform/telemetry/types'
import { useToastStore } from '@/platform/updates/common/toastStore'
import { updatePendingWarnings } from '@/platform/workflow/core/utils/pendingWarnings'
import { useWorkflowService } from '@/platform/workflow/core/services/workflowService'
import {
linearModeToAppMode,
useWorkflowService
} from '@/platform/workflow/core/services/workflowService'
import { ComfyWorkflow } from '@/platform/workflow/management/stores/workflowStore'
import { useWorkflowValidation } from '@/platform/workflow/validation/composables/useWorkflowValidation'
import type {
@@ -1425,7 +1428,9 @@ export class ComfyApp {
missing_node_types: missingNodeTypes.map((node) =>
typeof node === 'string' ? node : node.type
),
open_source: openSource ?? 'unknown'
open_source: openSource ?? 'unknown',
is_app: linearModeToAppMode(graphData?.extra?.linearMode) === 'app',
workflow_id: graphData?.id
}
useTelemetry()?.trackWorkflowOpened(telemetryPayload)
useTelemetry()?.trackWorkflowImported(telemetryPayload)