diff --git a/src/plugin/piniaActionTrail.js b/src/plugin/piniaActionTrail.js index 9750d888..a605dc1e 100644 --- a/src/plugin/piniaActionTrail.js +++ b/src/plugin/piniaActionTrail.js @@ -2,10 +2,6 @@ import dayjs from 'dayjs'; const STORAGE_KEY = 'vrcx:sentry:piniaActions'; -function formatAction(actionName, count) { - return count > 1 ? `${actionName}×${count}` : actionName; -} - function getStorage() { try { return localStorage; @@ -45,18 +41,15 @@ export function clearPiniaActionTrail() { storage.removeItem(STORAGE_KEY); } -export function appendPiniaActionTrail(entry, maxEntries = 200) { +export function appendPiniaActionTrail(entry) { const storage = getStorage(); if (!storage) return; const existing = getPiniaActionTrail(); existing.push(entry); - let removed = 0; - - if (existing.length > maxEntries) { - removed = existing.length - maxEntries; - existing.splice(0, removed); + if (existing.length > 200) { + existing.splice(0, existing.length - 200); } try { @@ -64,92 +57,14 @@ export function appendPiniaActionTrail(entry, maxEntries = 200) { } catch { // ignore } - - return { - index: existing.length - 1, - removed - }; } -export function createPiniaActionTrailPlugin({ - maxEntries = 200, - dedupeWindowMs = 1000 -} = {}) { - const actionStateByName = new Map(); - +export function createPiniaActionTrailPlugin() { return ({ store }) => { store.$onAction(({ name }) => { - const storage = getStorage(); - if (!storage) return; - - const now = dayjs().valueOf(); - const prev = actionStateByName.get(name) ?? { - lastAt: 0, - count: 0, - lastIndex: null - }; - - const isWithinWindow = now - prev.lastAt < dedupeWindowMs; - - if (isWithinWindow && prev.lastIndex !== null) { - const trail = getPiniaActionTrail(); - const idx = prev.lastIndex; - - if (idx >= 0 && idx < trail.length) { - const existingEntry = trail[idx]; - if (existingEntry) { - const nextCount = (prev.count ?? 1) + 1; - trail[idx] = { - ...existingEntry, - ts: now, - action: formatAction(name, nextCount) - }; - - try { - storage.setItem( - STORAGE_KEY, - safeJsonStringify(trail) - ); - } catch { - // ignore - } - - actionStateByName.set(name, { - lastAt: now, - count: nextCount, - lastIndex: idx - }); - return; - } - } - } - - const appendResult = appendPiniaActionTrail( - { - ts: now, - action: name - }, - maxEntries - ); - - const removed = appendResult?.removed ?? 0; - if (removed > 0) { - for (const [actionName, actionState] of actionStateByName) { - if (!actionState || actionState.lastIndex === null) { - continue; - } - const shifted = actionState.lastIndex - removed; - actionStateByName.set(actionName, { - ...actionState, - lastIndex: shifted >= 0 ? shifted : null - }); - } - } - - actionStateByName.set(name, { - lastAt: now, - count: 1, - lastIndex: appendResult?.index ?? null + appendPiniaActionTrail({ + t: dayjs().format('HH:mm:ss'), + a: name }); }); }; @@ -187,25 +102,12 @@ export function startRendererMemoryThresholdReport( const ratio = m.usedJSHeapSize / m.jsHeapSizeLimit; if (!Number.isFinite(ratio) || ratio < thresholdRatio) return; - const now = dayjs().valueOf(); + const now = Date.now(); if (now - lastSent < cooldownMs) return; lastSent = now; const trail = getPiniaActionTrail(); - const trailText = trail - .map((entry) => { - const t = - typeof entry?.ts === 'number' - ? dayjs(entry.ts).format('HH:mm:ss') - : ''; - const a = entry?.action ?? ''; - if (!t && !a) return ''; - if (!t) return String(a); - if (!a) return t; - return `${t} ${a}`; - }) - .filter(Boolean) - .join(';'); + const trailText = JSON.stringify(trail); Sentry.withScope((scope) => { scope.setLevel('warning'); scope.setTag('reason', 'high-js-heap'); diff --git a/src/stores/vrcx.js b/src/stores/vrcx.js index 60d044e3..1e471db8 100644 --- a/src/stores/vrcx.js +++ b/src/stores/vrcx.js @@ -543,15 +543,7 @@ export const useVrcxStore = defineStore('Vrcx', () => { } return ts.isAfter(cutoff) || ts.isSame(cutoff); }); - const trailText = trail - .map((entry) => { - const t = dayjs(entry.ts).format('HH:mm:ss'); - const a = entry.action ?? ''; - if (!a) return t; - return `${t} ${a}`; - }) - .filter(Boolean) - .join(';'); + const trailText = JSON.stringify(trail); Sentry.withScope((scope) => { scope.setLevel('fatal'); scope.setTag('reason', 'crash-recovery');