feat(metrics): run events carry which engine served them

Without this we cannot tell whether the in-browser path is actually
displacing guest boots — the whole point of the dual engine is a number
(% of runs that never touched the backend), so the event has to say.
This commit is contained in:
David Montero Crespo 2026-07-29 04:41:52 +02:00
parent 84e32ef1f2
commit b622cad80a
2 changed files with 10 additions and 2 deletions

View File

@ -2,6 +2,7 @@ import { useState, useCallback, useRef, useEffect } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useEditorStore, chipFileGroupId } from '../../store/useEditorStore'; import { useEditorStore, chipFileGroupId } from '../../store/useEditorStore';
import { useSimulatorStore, piRerunScript } from '../../store/useSimulatorStore'; import { useSimulatorStore, piRerunScript } from '../../store/useSimulatorStore';
import { decideEngine } from '../../lib/instantEngine';
import { useElectricalStore } from '../../store/useElectricalStore'; import { useElectricalStore } from '../../store/useElectricalStore';
import { type VerificationResult } from '../../simulation/verify/circuitVerifier'; import { type VerificationResult } from '../../simulation/verify/circuitVerifier';
import { verifyCircuitFromStore } from '../../simulation/verify/verifyFromStore'; import { verifyCircuitFromStore } from '../../simulation/verify/verifyFromStore';
@ -227,11 +228,12 @@ export const EditorToolbar = ({
// Helper: report a Run event to the backend for analytics. Resolves the // Helper: report a Run event to the backend for analytics. Resolves the
// FQBN from the board kind so the backend can group by family/fqbn. // FQBN from the board kind so the backend can group by family/fqbn.
const reportRun = useCallback( const reportRun = useCallback(
(boardKind: BoardKind | undefined) => { (boardKind: BoardKind | undefined, engine?: 'instant' | 'linux') => {
const fqbn = boardKind ? BOARD_KIND_FQBN[boardKind] : null; const fqbn = boardKind ? BOARD_KIND_FQBN[boardKind] : null;
void reportRunEvent({ void reportRunEvent({
project_id: currentProject?.id ?? null, project_id: currentProject?.id ?? null,
board_fqbn: fqbn ?? null, board_fqbn: fqbn ?? null,
engine: engine ?? null,
}); });
}, },
[currentProject], [currentProject],
@ -824,7 +826,10 @@ export const EditorToolbar = ({
// generic stop-then-boot restart below. // generic stop-then-boot restart below.
if (isPiBoardKind(board?.boardKind ?? '')) { if (isPiBoardKind(board?.boardKind ?? '')) {
trackRunSimulation(board?.boardKind); trackRunSimulation(board?.boardKind);
reportRun(board?.boardKind); reportRun(
board?.boardKind,
decideEngine(activeBoardId, board?.enginePinned).engine,
);
if (board?.running) { if (board?.running) {
// Zombie/edge case (Run is normally disabled while running): // Zombie/edge case (Run is normally disabled while running):
// power-cycle for a clean boot. // power-cycle for a clean boot.

View File

@ -12,6 +12,9 @@ api.interceptors.request.use((config) => {
export interface RunEventPayload { export interface RunEventPayload {
project_id?: string | null; project_id?: string | null;
board_fqbn?: string | null; board_fqbn?: string | null;
/** Which engine took this run 'instant' (browser) or 'linux' (guest).
* Absent for boards where the question doesn't apply. */
engine?: 'instant' | 'linux' | null;
} }
export async function reportRunEvent(payload: RunEventPayload): Promise<void> { export async function reportRunEvent(payload: RunEventPayload): Promise<void> {