@grafana/scenes 6.40.1 → 6.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/esm/behaviors/SceneInteractionTracker.js.map +1 -1
- package/dist/esm/behaviors/SceneQueryController.js.map +1 -1
- package/dist/esm/components/SceneRefreshPicker.js +1 -1
- package/dist/esm/components/SceneRefreshPicker.js.map +1 -1
- package/dist/esm/components/VizPanel/VizPanel.js +26 -0
- package/dist/esm/components/VizPanel/VizPanel.js.map +1 -1
- package/dist/esm/components/VizPanel/VizPanelRenderer.js +18 -1
- package/dist/esm/components/VizPanel/VizPanelRenderer.js.map +1 -1
- package/dist/esm/core/SceneTimeRange.js +1 -1
- package/dist/esm/core/SceneTimeRange.js.map +1 -1
- package/dist/esm/index.js +5 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/locales/cs-CZ/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/cs-CZ/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/de-DE/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/de-DE/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/es-ES/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/es-ES/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/fr-FR/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/fr-FR/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/hu-HU/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/hu-HU/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/id-ID/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/id-ID/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/it-IT/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/it-IT/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/ja-JP/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/ja-JP/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/ko-KR/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/ko-KR/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/nl-NL/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/nl-NL/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/pl-PL/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/pl-PL/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/pt-BR/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/pt-BR/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/pt-PT/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/pt-PT/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/ru-RU/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/ru-RU/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/sv-SE/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/sv-SE/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/tr-TR/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/tr-TR/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/zh-Hans/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/zh-Hans/grafana-scenes.json.js.map +1 -1
- package/dist/esm/locales/zh-Hant/grafana-scenes.json.js +5 -0
- package/dist/esm/locales/zh-Hant/grafana-scenes.json.js.map +1 -1
- package/dist/esm/{behaviors → performance}/LongFrameDetector.js +11 -11
- package/dist/esm/performance/LongFrameDetector.js.map +1 -0
- package/dist/esm/performance/PanelProfilingManager.js +65 -0
- package/dist/esm/performance/PanelProfilingManager.js.map +1 -0
- package/dist/esm/performance/ScenePerformanceTracker.js +82 -0
- package/dist/esm/performance/ScenePerformanceTracker.js.map +1 -0
- package/dist/esm/{behaviors → performance}/SceneRenderProfiler.js +87 -132
- package/dist/esm/performance/SceneRenderProfiler.js.map +1 -0
- package/dist/esm/performance/VizPanelRenderProfiler.js +316 -0
- package/dist/esm/performance/VizPanelRenderProfiler.js.map +1 -0
- package/dist/esm/performance/index.js +3 -0
- package/dist/esm/performance/index.js.map +1 -0
- package/dist/esm/performance/interactionConstants.js +13 -0
- package/dist/esm/performance/interactionConstants.js.map +1 -0
- package/dist/esm/querying/SceneDataTransformer.js +57 -0
- package/dist/esm/querying/SceneDataTransformer.js.map +1 -1
- package/dist/esm/querying/SceneQueryRunner.js +11 -6
- package/dist/esm/querying/SceneQueryRunner.js.map +1 -1
- package/dist/esm/querying/registerQueryWithController.js +39 -2
- package/dist/esm/querying/registerQueryWithController.js.map +1 -1
- package/dist/esm/utils/findPanelProfiler.js +18 -0
- package/dist/esm/utils/findPanelProfiler.js.map +1 -0
- package/dist/esm/utils/writePerformanceLog.js +12 -0
- package/dist/esm/utils/writePerformanceLog.js.map +1 -0
- package/dist/esm/utils/writeSceneLog.js +1 -10
- package/dist/esm/utils/writeSceneLog.js.map +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js.map +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersVariable.js +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersVariable.js.map +1 -1
- package/dist/esm/variables/components/VariableValueSelect.js +1 -1
- package/dist/esm/variables/components/VariableValueSelect.js.map +1 -1
- package/dist/esm/variables/groupby/GroupByVariable.js +1 -1
- package/dist/esm/variables/groupby/GroupByVariable.js.map +1 -1
- package/dist/esm/variables/variants/MultiValueVariable.js +1 -1
- package/dist/esm/variables/variants/MultiValueVariable.js.map +1 -1
- package/dist/esm/variables/variants/ScopesVariable.js +1 -1
- package/dist/esm/variables/variants/ScopesVariable.js.map +1 -1
- package/dist/{grafana-scenes-CRkk3i3Y.js → grafana-scenes-2zS6WwcG.js} +6 -1
- package/dist/{grafana-scenes-BH2OEiLz.js.map → grafana-scenes-2zS6WwcG.js.map} +1 -1
- package/dist/{grafana-scenes-BH2OEiLz.js → grafana-scenes-5D_kgp5S.js} +6 -1
- package/dist/{grafana-scenes-BLJV6eE3.js.map → grafana-scenes-5D_kgp5S.js.map} +1 -1
- package/dist/{grafana-scenes-DTn3nyOX.js → grafana-scenes-8z5eBgO0.js} +6 -1
- package/dist/{grafana-scenes-BrExMMR1.js.map → grafana-scenes-8z5eBgO0.js.map} +1 -1
- package/dist/{grafana-scenes-DNMnQEFs.js → grafana-scenes-BAJo7mZu.js} +6 -1
- package/dist/{grafana-scenes-BrpU2VxI.js.map → grafana-scenes-BAJo7mZu.js.map} +1 -1
- package/dist/{grafana-scenes-DaO9TTTj.js → grafana-scenes-BAvDcHPV.js} +6 -1
- package/dist/grafana-scenes-BAvDcHPV.js.map +1 -0
- package/dist/{grafana-scenes-Kqjin1Vr.js → grafana-scenes-C4rsdf2J.js} +6 -1
- package/dist/grafana-scenes-C4rsdf2J.js.map +1 -0
- package/dist/{grafana-scenes-DpvJWDGo.js → grafana-scenes-DQDUiFgy.js} +6 -1
- package/dist/grafana-scenes-DQDUiFgy.js.map +1 -0
- package/dist/{grafana-scenes-OEGPBO01.js → grafana-scenes-DW_EK7z5.js} +6 -1
- package/dist/grafana-scenes-DW_EK7z5.js.map +1 -0
- package/dist/{grafana-scenes-D-DPZiBx.js → grafana-scenes-D_7C5tUl.js} +6 -1
- package/dist/grafana-scenes-D_7C5tUl.js.map +1 -0
- package/dist/{grafana-scenes-D1jd3aZp.js → grafana-scenes-DarGXy_b.js} +6 -1
- package/dist/grafana-scenes-DarGXy_b.js.map +1 -0
- package/dist/{grafana-scenes-Cl-piLdF.js → grafana-scenes-Di0mD-iN.js} +6 -1
- package/dist/grafana-scenes-Di0mD-iN.js.map +1 -0
- package/dist/{grafana-scenes-DPbgWPLH.js → grafana-scenes-DkNywY1s.js} +6 -1
- package/dist/grafana-scenes-DkNywY1s.js.map +1 -0
- package/dist/{grafana-scenes-BrpU2VxI.js → grafana-scenes-Dmwf_eJ5.js} +6 -1
- package/dist/grafana-scenes-Dmwf_eJ5.js.map +1 -0
- package/dist/{grafana-scenes-BLJV6eE3.js → grafana-scenes-L3DvBvA_.js} +6 -1
- package/dist/grafana-scenes-L3DvBvA_.js.map +1 -0
- package/dist/{grafana-scenes-qNHDZUAZ.js → grafana-scenes-fPery0i8.js} +6 -1
- package/dist/grafana-scenes-fPery0i8.js.map +1 -0
- package/dist/{grafana-scenes-CfuUpx6R.js → grafana-scenes-r_1S-tPI.js} +6 -1
- package/dist/grafana-scenes-r_1S-tPI.js.map +1 -0
- package/dist/{grafana-scenes-BrExMMR1.js → grafana-scenes-tZ650dxC.js} +6 -1
- package/dist/grafana-scenes-tZ650dxC.js.map +1 -0
- package/dist/{grafana-scenes-DoKV4lED.js → grafana-scenes-v_pWTyzx.js} +6 -1
- package/dist/grafana-scenes-v_pWTyzx.js.map +1 -0
- package/dist/index.d.ts +326 -95
- package/dist/index.js +6622 -6053
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/esm/behaviors/LongFrameDetector.js.map +0 -1
- package/dist/esm/behaviors/SceneRenderProfiler.js.map +0 -1
- package/dist/grafana-scenes-CRkk3i3Y.js.map +0 -1
- package/dist/grafana-scenes-CfuUpx6R.js.map +0 -1
- package/dist/grafana-scenes-Cl-piLdF.js.map +0 -1
- package/dist/grafana-scenes-D-DPZiBx.js.map +0 -1
- package/dist/grafana-scenes-D1jd3aZp.js.map +0 -1
- package/dist/grafana-scenes-DNMnQEFs.js.map +0 -1
- package/dist/grafana-scenes-DPbgWPLH.js.map +0 -1
- package/dist/grafana-scenes-DTn3nyOX.js.map +0 -1
- package/dist/grafana-scenes-DaO9TTTj.js.map +0 -1
- package/dist/grafana-scenes-DoKV4lED.js.map +0 -1
- package/dist/grafana-scenes-DpvJWDGo.js.map +0 -1
- package/dist/grafana-scenes-Kqjin1Vr.js.map +0 -1
- package/dist/grafana-scenes-OEGPBO01.js.map +0 -1
- package/dist/grafana-scenes-qNHDZUAZ.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LongFrameDetector.js","sources":["../../../src/performance/LongFrameDetector.ts"],"sourcesContent":["import { writePerformanceLog } from '../utils/writePerformanceLog';\n\nconst LONG_FRAME_THRESHOLD = 50; // Threshold for both LoAF and manual tracking (ms)\n\nexport interface LongFrameEvent {\n duration: number; // Frame duration in milliseconds\n timestamp: number; // When the frame occurred\n method: 'manual' | 'loaf'; // Which detection method was used\n}\n\nexport type LongFrameCallback = (event: LongFrameEvent) => void;\n\n/**\n * LongFrameDetector is a module for detecting long animation frames.\n *\n * It supports two detection methods with automatic fallback:\n * 1. LoAF API (default when available): Uses Long Animation Frame API with 50ms threshold\n * 2. Manual tracking (fallback): Uses requestAnimationFrame with configurable threshold (default: 50ms)\n *\n * The detector automatically uses LoAF when available for better attribution and performance,\n * falling back to manual tracking for broader browser support.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/Long_animation_frame_timing\n */\nexport class LongFrameDetector {\n #isTracking = false;\n #callback: LongFrameCallback | null = null;\n\n // Manual tracking state\n #frameTrackingId: number | null = null;\n #lastFrameTime = 0;\n\n // LoAF tracking state\n #loafObserver: PerformanceObserver | null = null;\n\n /**\n * Check if LoAF API is available in the browser\n */\n private isLoAFAvailable(): boolean {\n return (\n typeof PerformanceObserver !== 'undefined' &&\n PerformanceObserver.supportedEntryTypes &&\n PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')\n );\n }\n\n /**\n * Start detecting long frames and call the provided callback when they occur\n */\n public start(callback: LongFrameCallback): void {\n if (this.#isTracking) {\n writePerformanceLog('LFD', 'Already tracking frames, stopping previous session');\n this.stop();\n }\n\n this.#callback = callback;\n this.#isTracking = true;\n\n if (this.isLoAFAvailable()) {\n this.startLoAFTracking();\n } else {\n this.startManualFrameTracking();\n }\n\n writePerformanceLog(\n 'LFD',\n `Started tracking with ${\n this.isLoAFAvailable() ? 'LoAF API' : 'manual'\n } method, threshold: ${LONG_FRAME_THRESHOLD}ms`\n );\n }\n\n /**\n * Stop detecting long frames\n */\n public stop(): void {\n if (!this.#isTracking) {\n return;\n }\n\n this.#isTracking = false;\n this.#callback = null;\n\n // Stop both tracking methods to ensure cleanup\n this.stopLoAFTracking();\n this.stopManualFrameTracking();\n }\n\n /**\n * Check if currently tracking frames\n */\n public isTracking(): boolean {\n return this.#isTracking;\n }\n\n /**\n * Start tracking using the Long Animation Frame API\n * @see https://developer.mozilla.org/en-US/docs/Web/API/PerformanceLongAnimationFrameTiming\n */\n private startLoAFTracking(): void {\n if (!this.isLoAFAvailable()) {\n writePerformanceLog('LFD', 'LoAF API not available, falling back to manual tracking');\n this.startManualFrameTracking();\n return;\n }\n\n try {\n this.#loafObserver = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n // No duration check needed - LoAF API already filters for long frames (>50ms)\n const event: LongFrameEvent = {\n duration: entry.duration,\n timestamp: entry.startTime,\n method: 'loaf',\n };\n\n if (this.#callback) {\n this.#callback(event);\n }\n\n // Add performance marks and measurements for debugging in dev tools\n if (typeof performance !== 'undefined' && performance.mark && performance.measure) {\n const frameId = `long-frame-${entry.startTime.toFixed(0)}`;\n const startMarkName = `${frameId}-start`;\n const endMarkName = `${frameId}-end`;\n const measureName = `Long Frame (LoAF): ${entry.duration.toFixed(1)}ms`;\n\n try {\n // Create start and end marks\n performance.mark(startMarkName, { startTime: entry.startTime });\n performance.mark(endMarkName, { startTime: entry.startTime + entry.duration });\n\n // Create measurement span\n performance.measure(measureName, startMarkName, endMarkName);\n } catch {\n // Fallback for browsers that don't support startTime option\n performance.mark(measureName);\n }\n }\n\n writePerformanceLog('LFD', `Long frame detected (LoAF): ${entry.duration}ms at ${entry.startTime}ms`);\n }\n });\n\n this.#loafObserver.observe({ type: 'long-animation-frame', buffered: false });\n } catch (error) {\n writePerformanceLog('LFD', 'Failed to start LoAF tracking, falling back to manual:', error);\n this.startManualFrameTracking();\n }\n }\n\n /**\n * Stop LoAF tracking\n */\n private stopLoAFTracking(): void {\n if (this.#loafObserver) {\n this.#loafObserver.disconnect();\n this.#loafObserver = null;\n writePerformanceLog('LFD', 'Stopped LoAF tracking');\n }\n }\n\n /**\n * Start manual frame tracking using requestAnimationFrame\n */\n private startManualFrameTracking(): void {\n this.#lastFrameTime = performance.now();\n this.#frameTrackingId = requestAnimationFrame(() => this.measureFrames());\n }\n\n /**\n * Stop manual frame tracking\n */\n private stopManualFrameTracking(): void {\n if (this.#frameTrackingId) {\n cancelAnimationFrame(this.#frameTrackingId);\n this.#frameTrackingId = null;\n writePerformanceLog('LFD', 'Stopped manual frame tracking');\n }\n }\n\n /**\n * Measure frame durations using requestAnimationFrame\n */\n private measureFrames = (): void => {\n if (!this.#isTracking) {\n return;\n }\n\n const currentFrameTime = performance.now();\n const frameLength = currentFrameTime - this.#lastFrameTime;\n\n // Check if frame exceeds threshold\n if (frameLength > LONG_FRAME_THRESHOLD) {\n const event: LongFrameEvent = {\n duration: frameLength,\n timestamp: currentFrameTime,\n method: 'manual',\n };\n\n if (this.#callback) {\n this.#callback(event);\n }\n\n // Add performance marks and measurements for debugging in dev tools\n if (typeof performance !== 'undefined' && performance.mark && performance.measure) {\n const frameId = `long-frame-manual-${currentFrameTime.toFixed(0)}`;\n const startMarkName = `${frameId}-start`;\n const endMarkName = `${frameId}-end`;\n const measureName = `Long Frame (Manual): ${frameLength.toFixed(1)}ms`;\n\n try {\n // Create start and end marks\n performance.mark(startMarkName, { startTime: currentFrameTime - frameLength });\n performance.mark(endMarkName, { startTime: currentFrameTime });\n\n // Create measurement span\n performance.measure(measureName, startMarkName, endMarkName);\n } catch {\n // Fallback for browsers that don't support startTime option\n performance.mark(measureName);\n }\n }\n\n writePerformanceLog(\n 'LFD',\n `Long frame detected (manual): ${frameLength}ms (threshold: ${LONG_FRAME_THRESHOLD}ms)`\n );\n }\n\n this.#lastFrameTime = currentFrameTime;\n\n // Continue tracking\n if (this.#isTracking) {\n this.#frameTrackingId = requestAnimationFrame(this.measureFrames);\n }\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { VizPanel } from '../components/VizPanel/VizPanel.js';
|
|
2
|
+
import { VizPanelRenderProfiler } from './VizPanelRenderProfiler.js';
|
|
3
|
+
import { sceneGraph } from '../core/sceneGraph/index.js';
|
|
4
|
+
|
|
5
|
+
class PanelProfilingManager {
|
|
6
|
+
constructor(_config) {
|
|
7
|
+
this._config = _config;
|
|
8
|
+
this._subscriptions = [];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Attach panel profiling to a scene object
|
|
12
|
+
*/
|
|
13
|
+
attachToScene(sceneObject) {
|
|
14
|
+
this._sceneObject = sceneObject;
|
|
15
|
+
const subscription = sceneObject.subscribeToState((newState, prevState) => {
|
|
16
|
+
if (this._config.watchStateKey) {
|
|
17
|
+
if (newState[this._config.watchStateKey] !== prevState[this._config.watchStateKey]) {
|
|
18
|
+
this._attachProfilersToPanels();
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
this._attachProfilersToPanels();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
this._subscriptions.push(subscription);
|
|
25
|
+
this._attachProfilersToPanels();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Attach VizPanelRenderProfiler to a specific panel if it doesn't already have one
|
|
29
|
+
* @param panel - The VizPanel to attach profiling to
|
|
30
|
+
*/
|
|
31
|
+
attachProfilerToPanel(panel) {
|
|
32
|
+
var _a;
|
|
33
|
+
const existingProfiler = (_a = panel.state.$behaviors) == null ? void 0 : _a.find((b) => b instanceof VizPanelRenderProfiler);
|
|
34
|
+
if (existingProfiler) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const profiler = new VizPanelRenderProfiler();
|
|
38
|
+
panel.setState({
|
|
39
|
+
$behaviors: [...panel.state.$behaviors || [], profiler]
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Attach VizPanelRenderProfiler to all VizPanels that don't already have one
|
|
44
|
+
*/
|
|
45
|
+
_attachProfilersToPanels() {
|
|
46
|
+
if (!this._sceneObject) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const panels = sceneGraph.findAllObjects(this._sceneObject, (obj) => obj instanceof VizPanel);
|
|
50
|
+
panels.forEach((panel) => {
|
|
51
|
+
this.attachProfilerToPanel(panel);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Clean up subscriptions and references
|
|
56
|
+
*/
|
|
57
|
+
cleanup() {
|
|
58
|
+
this._subscriptions.forEach((sub) => sub.unsubscribe());
|
|
59
|
+
this._subscriptions = [];
|
|
60
|
+
this._sceneObject = void 0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { PanelProfilingManager };
|
|
65
|
+
//# sourceMappingURL=PanelProfilingManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PanelProfilingManager.js","sources":["../../../src/performance/PanelProfilingManager.ts"],"sourcesContent":["import { Unsubscribable } from 'rxjs';\nimport { VizPanel } from '../components/VizPanel/VizPanel';\nimport { VizPanelRenderProfiler } from './VizPanelRenderProfiler';\nimport { SceneObject } from '../core/types';\nimport { sceneGraph } from '../core/sceneGraph';\n\nexport interface PanelProfilingConfig {\n watchStateKey?: string; // State property to watch for structural changes (e.g., 'body', 'children')\n}\n\n/**\n * Manages VizPanelRenderProfiler instances for all panels in a scene object.\n * Extracted from DashboardPanelProfilingBehavior to allow composition with SceneRenderProfiler.\n */\nexport class PanelProfilingManager {\n private _sceneObject?: SceneObject;\n private _subscriptions: Unsubscribable[] = [];\n\n public constructor(private _config: PanelProfilingConfig) {}\n\n /**\n * Attach panel profiling to a scene object\n */\n public attachToScene(sceneObject: SceneObject) {\n this._sceneObject = sceneObject;\n\n // Subscribe to scene state changes to add profilers to new panels\n const subscription = sceneObject.subscribeToState((newState: any, prevState: any) => {\n // If watchStateKey is specified, only react to changes in that specific property\n if (this._config.watchStateKey) {\n if (newState[this._config.watchStateKey] !== prevState[this._config.watchStateKey]) {\n this._attachProfilersToPanels();\n }\n } else {\n // Fallback: react to any state change\n this._attachProfilersToPanels();\n }\n });\n\n this._subscriptions.push(subscription);\n\n // Attach profilers to existing panels\n this._attachProfilersToPanels();\n }\n\n /**\n * Attach VizPanelRenderProfiler to a specific panel if it doesn't already have one\n * @param panel - The VizPanel to attach profiling to\n */\n public attachProfilerToPanel(panel: VizPanel): void {\n // Check if profiler already exists\n const existingProfiler = panel.state.$behaviors?.find((b) => b instanceof VizPanelRenderProfiler);\n\n if (existingProfiler) {\n return; // Already has a profiler\n }\n\n // Add profiler behavior\n const profiler = new VizPanelRenderProfiler();\n\n panel.setState({\n $behaviors: [...(panel.state.$behaviors || []), profiler],\n });\n }\n\n /**\n * Attach VizPanelRenderProfiler to all VizPanels that don't already have one\n */\n private _attachProfilersToPanels() {\n if (!this._sceneObject) {\n return;\n }\n\n // Use scene graph to find all VizPanels in the scene\n const panels = sceneGraph.findAllObjects(this._sceneObject, (obj) => obj instanceof VizPanel) as VizPanel[];\n\n panels.forEach((panel) => {\n this.attachProfilerToPanel(panel);\n });\n }\n\n /**\n * Clean up subscriptions and references\n */\n public cleanup() {\n this._subscriptions.forEach((sub) => sub.unsubscribe());\n this._subscriptions = [];\n this._sceneObject = undefined;\n }\n}\n"],"names":[],"mappings":";;;;AAcO,MAAM,qBAAsB,CAAA;AAAA,EAI1B,YAAoB,OAA+B,EAAA;AAA/B,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAF3B,IAAA,IAAA,CAAQ,iBAAmC,EAAC;AAAA;AAEe;AAAA;AAAA;AAAA,EAKpD,cAAc,WAA0B,EAAA;AAC7C,IAAA,IAAA,CAAK,YAAe,GAAA,WAAA;AAGpB,IAAA,MAAM,YAAe,GAAA,WAAA,CAAY,gBAAiB,CAAA,CAAC,UAAe,SAAmB,KAAA;AAEnF,MAAI,IAAA,IAAA,CAAK,QAAQ,aAAe,EAAA;AAC9B,QAAI,IAAA,QAAA,CAAS,KAAK,OAAQ,CAAA,aAAa,MAAM,SAAU,CAAA,IAAA,CAAK,OAAQ,CAAA,aAAa,CAAG,EAAA;AAClF,UAAA,IAAA,CAAK,wBAAyB,EAAA;AAAA;AAChC,OACK,MAAA;AAEL,QAAA,IAAA,CAAK,wBAAyB,EAAA;AAAA;AAChC,KACD,CAAA;AAED,IAAK,IAAA,CAAA,cAAA,CAAe,KAAK,YAAY,CAAA;AAGrC,IAAA,IAAA,CAAK,wBAAyB,EAAA;AAAA;AAChC;AAAA;AAAA;AAAA;AAAA,EAMO,sBAAsB,KAAuB,EAAA;AAjDtD,IAAA,IAAA,EAAA;AAmDI,IAAM,MAAA,gBAAA,GAAA,CAAmB,WAAM,KAAM,CAAA,UAAA,KAAZ,mBAAwB,IAAK,CAAA,CAAC,MAAM,CAAa,YAAA,sBAAA,CAAA;AAE1E,IAAA,IAAI,gBAAkB,EAAA;AACpB,MAAA;AAAA;AAIF,IAAM,MAAA,QAAA,GAAW,IAAI,sBAAuB,EAAA;AAE5C,IAAA,KAAA,CAAM,QAAS,CAAA;AAAA,MACb,UAAA,EAAY,CAAC,GAAI,KAAA,CAAM,MAAM,UAAc,IAAA,IAAK,QAAQ;AAAA,KACzD,CAAA;AAAA;AACH;AAAA;AAAA;AAAA,EAKQ,wBAA2B,GAAA;AACjC,IAAI,IAAA,CAAC,KAAK,YAAc,EAAA;AACtB,MAAA;AAAA;AAIF,IAAM,MAAA,MAAA,GAAS,WAAW,cAAe,CAAA,IAAA,CAAK,cAAc,CAAC,GAAA,KAAQ,eAAe,QAAQ,CAAA;AAE5F,IAAO,MAAA,CAAA,OAAA,CAAQ,CAAC,KAAU,KAAA;AACxB,MAAA,IAAA,CAAK,sBAAsB,KAAK,CAAA;AAAA,KACjC,CAAA;AAAA;AACH;AAAA;AAAA;AAAA,EAKO,OAAU,GAAA;AACf,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,CAAC,GAAQ,KAAA,GAAA,CAAI,aAAa,CAAA;AACtD,IAAA,IAAA,CAAK,iBAAiB,EAAC;AACvB,IAAA,IAAA,CAAK,YAAe,GAAA,MAAA;AAAA;AAExB;;;;"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
function generateOperationId(prefix = "op") {
|
|
2
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
3
|
+
const uuid = crypto.randomUUID();
|
|
4
|
+
return `${prefix}-${uuid}`;
|
|
5
|
+
}
|
|
6
|
+
const randomPart = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
|
7
|
+
return `${prefix}-${randomPart}`;
|
|
8
|
+
}
|
|
9
|
+
const _ScenePerformanceTracker = class _ScenePerformanceTracker {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.observers = [];
|
|
12
|
+
}
|
|
13
|
+
static getInstance() {
|
|
14
|
+
if (!_ScenePerformanceTracker.instance) {
|
|
15
|
+
_ScenePerformanceTracker.instance = new _ScenePerformanceTracker();
|
|
16
|
+
}
|
|
17
|
+
return _ScenePerformanceTracker.instance;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register a performance observer
|
|
21
|
+
*/
|
|
22
|
+
addObserver(observer) {
|
|
23
|
+
this.observers.push(observer);
|
|
24
|
+
return () => {
|
|
25
|
+
const index = this.observers.indexOf(observer);
|
|
26
|
+
if (index > -1) {
|
|
27
|
+
this.observers.splice(index, 1);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Remove all observers (for testing)
|
|
33
|
+
*/
|
|
34
|
+
clearObservers() {
|
|
35
|
+
this.observers = [];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get current observer count (for debugging)
|
|
39
|
+
*/
|
|
40
|
+
getObserverCount() {
|
|
41
|
+
return this.observers.length;
|
|
42
|
+
}
|
|
43
|
+
notifyObservers(methodName, data, errorContext) {
|
|
44
|
+
this.observers.forEach((observer) => {
|
|
45
|
+
try {
|
|
46
|
+
const method = observer[methodName];
|
|
47
|
+
method == null ? void 0 : method(data);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.warn(`Error in ${errorContext} observer:`, error);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
notifyDashboardInteractionStart(data) {
|
|
54
|
+
this.notifyObservers("onDashboardInteractionStart", data, "dashboard interaction start");
|
|
55
|
+
}
|
|
56
|
+
notifyDashboardInteractionMilestone(data) {
|
|
57
|
+
this.notifyObservers("onDashboardInteractionMilestone", data, "dashboard interaction milestone");
|
|
58
|
+
}
|
|
59
|
+
notifyDashboardInteractionComplete(data) {
|
|
60
|
+
this.notifyObservers("onDashboardInteractionComplete", data, "dashboard interaction complete");
|
|
61
|
+
}
|
|
62
|
+
notifyPanelOperationStart(data) {
|
|
63
|
+
this.notifyObservers("onPanelOperationStart", data, "panel operation start");
|
|
64
|
+
}
|
|
65
|
+
notifyPanelOperationComplete(data) {
|
|
66
|
+
this.notifyObservers("onPanelOperationComplete", data, "panel operation complete");
|
|
67
|
+
}
|
|
68
|
+
notifyQueryStart(data) {
|
|
69
|
+
this.notifyObservers("onQueryStart", data, "query start");
|
|
70
|
+
}
|
|
71
|
+
notifyQueryComplete(data) {
|
|
72
|
+
this.notifyObservers("onQueryComplete", data, "query complete");
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
_ScenePerformanceTracker.instance = null;
|
|
76
|
+
let ScenePerformanceTracker = _ScenePerformanceTracker;
|
|
77
|
+
function getScenePerformanceTracker() {
|
|
78
|
+
return ScenePerformanceTracker.getInstance();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { ScenePerformanceTracker, generateOperationId, getScenePerformanceTracker };
|
|
82
|
+
//# sourceMappingURL=ScenePerformanceTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScenePerformanceTracker.js","sources":["../../../src/performance/ScenePerformanceTracker.ts"],"sourcesContent":["/**\n * Centralized performance tracking system using observer pattern.\n * External systems (like Grafana) implement ScenePerformanceObserver to receive performance events.\n */\n\n/** Generate unique operation IDs for correlating start/complete events */\nexport function generateOperationId(prefix = 'op'): string {\n // Use crypto.randomUUID() for true uniqueness without global state\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n const uuid = crypto.randomUUID();\n return `${prefix}-${uuid}`;\n }\n\n // Fallback for environments without crypto.randomUUID support\n const randomPart = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);\n return `${prefix}-${randomPart}`;\n}\n\n/** Base interface for all performance events */\nexport interface BasePerformanceEvent {\n operationId: string; // Unique identifier for correlating start/complete events\n timestamp: number;\n duration?: number;\n error?: string;\n}\n\nexport interface DashboardInteractionStartData extends BasePerformanceEvent {\n interactionType: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface DashboardInteractionMilestoneData extends BasePerformanceEvent {\n interactionType: string;\n milestone: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface DashboardInteractionCompleteData extends BasePerformanceEvent {\n interactionType: string;\n networkDuration?: number;\n longFramesCount: number;\n longFramesTotalTime: number;\n metadata?: Record<string, unknown>;\n}\n\n/** Metadata interface for transform operations */\nexport interface TransformMetadata {\n transformationId: string;\n transformationCount: number;\n seriesTransformationCount: number;\n annotationTransformationCount: number;\n success?: boolean;\n error?: string;\n}\n\n/** Metadata interface for query operations */\nexport interface QueryMetadata {\n queryId: string;\n queryType: string;\n}\n\n/** Metadata interface for render operations */\nexport interface RenderMetadata {\n // Empty for now - can be extended later if needed\n}\n\n/** Metadata interface for plugin load operations */\nexport interface PluginLoadMetadata {\n pluginId: string;\n fromCache?: boolean;\n pluginLoadTime?: number;\n}\n\n/** Metadata interface for field config operations */\nexport interface FieldConfigMetadata {}\n\n/** Base interface for panel performance events */\ninterface BasePanelPerformanceData extends BasePerformanceEvent {\n panelId: string;\n panelKey: string;\n pluginId: string;\n pluginVersion?: string;\n panelTitle?: string;\n}\n\n/** Transform operation performance data */\nexport interface PanelTransformPerformanceData extends BasePanelPerformanceData {\n operation: 'transform';\n metadata: TransformMetadata;\n}\n\n/** Query operation performance data */\nexport interface PanelQueryPerformanceData extends BasePanelPerformanceData {\n operation: 'query';\n metadata: QueryMetadata;\n}\n\n/** Render operation performance data */\nexport interface PanelRenderPerformanceData extends BasePanelPerformanceData {\n operation: 'render';\n metadata: RenderMetadata;\n}\n\n/** Plugin load operation performance data */\nexport interface PanelPluginLoadPerformanceData extends BasePanelPerformanceData {\n operation: 'plugin-load';\n metadata: PluginLoadMetadata;\n}\n\n/** Field config operation performance data */\nexport interface PanelFieldConfigPerformanceData extends BasePanelPerformanceData {\n operation: 'fieldConfig';\n metadata: FieldConfigMetadata;\n}\n\n/** Discriminated union of all panel performance data types */\nexport type PanelPerformanceData =\n | PanelTransformPerformanceData\n | PanelQueryPerformanceData\n | PanelRenderPerformanceData\n | PanelPluginLoadPerformanceData\n | PanelFieldConfigPerformanceData;\n\n/** Non-panel query performance data for dashboard queries (annotations, variables, etc.) */\nexport interface QueryPerformanceData extends BasePerformanceEvent {\n queryId: string;\n queryType: string;\n origin: string; // e.g., \"AnnotationsDataLayer\", \"QueryVariable\", \"VizPanel/loadPlugin\"\n}\n\n/**\n * Observer interface for performance monitoring\n * External systems implement this to receive performance notifications\n */\nexport interface ScenePerformanceObserver {\n // Dashboard-level events\n onDashboardInteractionStart?(data: DashboardInteractionStartData): void;\n onDashboardInteractionMilestone?(data: DashboardInteractionMilestoneData): void;\n onDashboardInteractionComplete?(data: DashboardInteractionCompleteData): void;\n\n // Panel-level events\n onPanelOperationStart?(data: PanelPerformanceData): void;\n onPanelOperationComplete?(data: PanelPerformanceData): void;\n\n // Query-level events\n onQueryStart?(data: QueryPerformanceData): void;\n onQueryComplete?(data: QueryPerformanceData): void;\n}\n\n/**\n * Centralized performance tracker\n * Manages observers and provides methods for scene objects to report performance events\n */\nexport class ScenePerformanceTracker {\n private static instance: ScenePerformanceTracker | null = null;\n private observers: ScenePerformanceObserver[] = [];\n\n public static getInstance(): ScenePerformanceTracker {\n if (!ScenePerformanceTracker.instance) {\n ScenePerformanceTracker.instance = new ScenePerformanceTracker();\n }\n return ScenePerformanceTracker.instance;\n }\n\n /**\n * Register a performance observer\n */\n public addObserver(observer: ScenePerformanceObserver): () => void {\n this.observers.push(observer);\n\n // Return unsubscribe function\n return () => {\n const index = this.observers.indexOf(observer);\n if (index > -1) {\n this.observers.splice(index, 1);\n }\n };\n }\n\n /**\n * Remove all observers (for testing)\n */\n public clearObservers(): void {\n this.observers = [];\n }\n\n /**\n * Get current observer count (for debugging)\n */\n public getObserverCount(): number {\n return this.observers.length;\n }\n\n private notifyObservers<T>(methodName: keyof ScenePerformanceObserver, data: T, errorContext: string): void {\n this.observers.forEach((observer) => {\n try {\n const method = observer[methodName] as ((data: T) => void) | undefined;\n method?.(data);\n } catch (error) {\n console.warn(`Error in ${errorContext} observer:`, error);\n }\n });\n }\n\n public notifyDashboardInteractionStart(data: DashboardInteractionStartData): void {\n this.notifyObservers('onDashboardInteractionStart', data, 'dashboard interaction start');\n }\n\n public notifyDashboardInteractionMilestone(data: DashboardInteractionMilestoneData): void {\n this.notifyObservers('onDashboardInteractionMilestone', data, 'dashboard interaction milestone');\n }\n\n public notifyDashboardInteractionComplete(data: DashboardInteractionCompleteData): void {\n this.notifyObservers('onDashboardInteractionComplete', data, 'dashboard interaction complete');\n }\n\n public notifyPanelOperationStart(data: PanelPerformanceData): void {\n this.notifyObservers('onPanelOperationStart', data, 'panel operation start');\n }\n\n public notifyPanelOperationComplete(data: PanelPerformanceData): void {\n this.notifyObservers('onPanelOperationComplete', data, 'panel operation complete');\n }\n\n public notifyQueryStart(data: QueryPerformanceData): void {\n this.notifyObservers('onQueryStart', data, 'query start');\n }\n\n public notifyQueryComplete(data: QueryPerformanceData): void {\n this.notifyObservers('onQueryComplete', data, 'query complete');\n }\n}\n\n/**\n * Get the global performance tracker instance\n */\nexport function getScenePerformanceTracker(): ScenePerformanceTracker {\n return ScenePerformanceTracker.getInstance();\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { writePerformanceLog } from '../utils/writePerformanceLog.js';
|
|
2
|
+
import { generateOperationId, getScenePerformanceTracker } from './ScenePerformanceTracker.js';
|
|
3
|
+
import { PanelProfilingManager } from './PanelProfilingManager.js';
|
|
2
4
|
import { LongFrameDetector } from './LongFrameDetector.js';
|
|
3
5
|
|
|
4
6
|
var __typeError = (msg) => {
|
|
@@ -16,17 +18,20 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
16
18
|
return __privateGet(obj, member, getter);
|
|
17
19
|
}
|
|
18
20
|
});
|
|
19
|
-
var _profileInProgress, _interactionInProgress, _profileStartTs, _trailAnimationFrameId, _recordedTrailingSpans, _longFrameDetector, _longFramesCount, _longFramesTotalTime, _visibilityChangeHandler, _onInteractionComplete;
|
|
21
|
+
var _profileInProgress, _interactionInProgress, _profileStartTs, _trailAnimationFrameId, _currentOperationId, _recordedTrailingSpans, _longFrameDetector, _longFramesCount, _longFramesTotalTime, _visibilityChangeHandler, _onInteractionComplete;
|
|
20
22
|
const POST_STORM_WINDOW = 2e3;
|
|
21
23
|
const DEFAULT_LONG_FRAME_THRESHOLD = 30;
|
|
22
24
|
class SceneRenderProfiler {
|
|
23
|
-
constructor(
|
|
24
|
-
this.queryController = queryController;
|
|
25
|
+
constructor(panelProfilingConfig) {
|
|
25
26
|
__privateAdd(this, _profileInProgress, null);
|
|
26
27
|
__privateAdd(this, _interactionInProgress, null);
|
|
27
28
|
__privateAdd(this, _profileStartTs, null);
|
|
28
29
|
__privateAdd(this, _trailAnimationFrameId, null);
|
|
29
|
-
//
|
|
30
|
+
// Generic metadata for observer notifications
|
|
31
|
+
this.metadata = {};
|
|
32
|
+
// Operation ID for correlating dashboard interaction events
|
|
33
|
+
__privateAdd(this, _currentOperationId);
|
|
34
|
+
// Trailing frame measurements
|
|
30
35
|
__privateAdd(this, _recordedTrailingSpans, []);
|
|
31
36
|
// Long frame tracking
|
|
32
37
|
__privateAdd(this, _longFrameDetector);
|
|
@@ -35,7 +40,6 @@ class SceneRenderProfiler {
|
|
|
35
40
|
__privateAdd(this, _visibilityChangeHandler, null);
|
|
36
41
|
__privateAdd(this, _onInteractionComplete, null);
|
|
37
42
|
this.measureTrailingFrames = (measurementStartTs, lastFrameTime, profileStartTs) => {
|
|
38
|
-
var _a, _b, _c, _d;
|
|
39
43
|
const currentFrameTime = performance.now();
|
|
40
44
|
const frameLength = currentFrameTime - lastFrameTime;
|
|
41
45
|
__privateGet(this, _recordedTrailingSpans).push(frameLength);
|
|
@@ -48,108 +52,73 @@ class SceneRenderProfiler {
|
|
|
48
52
|
} else {
|
|
49
53
|
const slowFrames = processRecordedSpans(__privateGet(this, _recordedTrailingSpans));
|
|
50
54
|
const slowFramesTime = slowFrames.reduce((acc, val) => acc + val, 0);
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
55
|
+
writePerformanceLog(
|
|
56
|
+
"SRP",
|
|
57
|
+
"Profile tail recorded, slow frames duration:",
|
|
58
|
+
slowFramesTime,
|
|
59
|
+
slowFrames,
|
|
60
|
+
__privateGet(this, _profileInProgress)
|
|
54
61
|
);
|
|
55
|
-
writeSceneLog("", ` \u251C\u2500 Origin: ${((_a = __privateGet(this, _profileInProgress)) == null ? void 0 : _a.origin) || "unknown"}`);
|
|
56
|
-
writeSceneLog("", ` \u2514\u2500 Crumbs:`, ((_b = __privateGet(this, _profileInProgress)) == null ? void 0 : _b.crumbs) || []);
|
|
57
62
|
__privateSet(this, _recordedTrailingSpans, []);
|
|
58
63
|
const profileDuration = measurementStartTs - profileStartTs;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
`Dashboard Profile: ${profileName} (${totalTime.toFixed(1)}ms)`,
|
|
67
|
-
startMarkName,
|
|
68
|
-
`Dashboard Profile End: ${profileName}`
|
|
69
|
-
);
|
|
70
|
-
} catch (e) {
|
|
71
|
-
performance.mark(`Dashboard Profile Complete: ${profileName} (${totalTime.toFixed(1)}ms)`);
|
|
72
|
-
}
|
|
73
|
-
if (slowFrames.length > 0) {
|
|
74
|
-
const slowFramesMarkName = `Slow Frames Summary: ${slowFrames.length} frames (${slowFramesTime.toFixed(
|
|
75
|
-
1
|
|
76
|
-
)}ms)`;
|
|
77
|
-
performance.mark(slowFramesMarkName);
|
|
78
|
-
slowFrames.forEach((frameTime, index) => {
|
|
79
|
-
if (frameTime > 16) {
|
|
80
|
-
try {
|
|
81
|
-
const frameStartTime = __privateGet(this, _profileStartTs) + profileDuration + (index > 0 ? slowFrames.slice(0, index).reduce((sum, t) => sum + t, 0) : 0);
|
|
82
|
-
const frameId = `slow-frame-${index}`;
|
|
83
|
-
const frameStartMark = `${frameId}-start`;
|
|
84
|
-
const frameEndMark = `${frameId}-end`;
|
|
85
|
-
performance.mark(frameStartMark, { startTime: frameStartTime });
|
|
86
|
-
performance.mark(frameEndMark, { startTime: frameStartTime + frameTime });
|
|
87
|
-
performance.measure(`Slow Frame ${index + 1}: ${frameTime.toFixed(1)}ms`, frameStartMark, frameEndMark);
|
|
88
|
-
} catch (e) {
|
|
89
|
-
performance.mark(`Slow Frame ${index + 1}: ${frameTime.toFixed(1)}ms`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
const completionTimestamp = performance.now();
|
|
96
|
-
writeSceneLog("SceneRenderProfiler", "Profile completed");
|
|
97
|
-
writeSceneLog("", ` \u251C\u2500 Timestamp: ${completionTimestamp.toFixed(1)}ms`);
|
|
98
|
-
writeSceneLog("", ` \u251C\u2500 Total time: ${(profileDuration + slowFramesTime).toFixed(1)}ms`);
|
|
99
|
-
writeSceneLog("", ` \u251C\u2500 Slow frames: ${slowFramesTime}ms (${slowFrames.length} frames)`);
|
|
100
|
-
writeSceneLog("", ` \u2514\u2500 Long frames: ${__privateGet(this, _longFramesTotalTime)}ms (${__privateGet(this, _longFramesCount)} frames)`);
|
|
101
|
-
__privateGet(this, _longFrameDetector).stop();
|
|
102
|
-
writeSceneLogStyled(
|
|
103
|
-
"SceneRenderProfiler",
|
|
104
|
-
`Stopped long frame detection - profile complete at ${completionTimestamp.toFixed(1)}ms`,
|
|
105
|
-
"color: #00CC00; font-weight: bold;"
|
|
64
|
+
const slowFrameSummary = slowFrames.length > 0 ? `${slowFramesTime.toFixed(1)}ms slow frames[tail recording] (${slowFrames.length}) \u26A0\uFE0F` : `${slowFramesTime.toFixed(1)}ms slow frames[tail recording] (${slowFrames.length})`;
|
|
65
|
+
const longFrameSummary = __privateGet(this, _longFramesCount) > 0 ? `${__privateGet(this, _longFramesTotalTime).toFixed(1)}ms long frames[LoAF] (${__privateGet(this, _longFramesCount)}) \u26A0\uFE0F` : `${__privateGet(this, _longFramesTotalTime).toFixed(1)}ms long frames[LoAF] (${__privateGet(this, _longFramesCount)})`;
|
|
66
|
+
writePerformanceLog(
|
|
67
|
+
"SRP",
|
|
68
|
+
`[PROFILER] Complete: ${(profileDuration + slowFramesTime).toFixed(
|
|
69
|
+
1
|
|
70
|
+
)}ms total | ${slowFrameSummary} | ${longFrameSummary}`
|
|
106
71
|
);
|
|
72
|
+
__privateGet(this, _longFrameDetector).stop();
|
|
107
73
|
__privateSet(this, _trailAnimationFrameId, null);
|
|
108
74
|
const profileEndTs = profileStartTs + profileDuration + slowFramesTime;
|
|
109
75
|
if (!__privateGet(this, _profileInProgress)) {
|
|
110
76
|
return;
|
|
111
77
|
}
|
|
112
|
-
performance.measure(`DashboardInteraction ${__privateGet(this, _profileInProgress).origin}`, {
|
|
113
|
-
start: profileStartTs,
|
|
114
|
-
end: profileEndTs
|
|
115
|
-
});
|
|
116
78
|
const networkDuration = captureNetwork(profileStartTs, profileEndTs);
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
79
|
+
if (__privateGet(this, _profileInProgress)) {
|
|
80
|
+
const dashboardData = {
|
|
81
|
+
operationId: __privateGet(this, _currentOperationId) || generateOperationId("dashboard-fallback"),
|
|
82
|
+
interactionType: __privateGet(this, _profileInProgress).origin,
|
|
83
|
+
timestamp: profileEndTs,
|
|
121
84
|
duration: profileDuration + slowFramesTime,
|
|
122
85
|
networkDuration,
|
|
123
|
-
startTs: profileStartTs,
|
|
124
|
-
endTs: profileEndTs,
|
|
125
86
|
longFramesCount: __privateGet(this, _longFramesCount),
|
|
126
87
|
longFramesTotalTime: __privateGet(this, _longFramesTotalTime),
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// @ts-ignore
|
|
132
|
-
totalJSHeapSize: performance.memory ? performance.memory.totalJSHeapSize : 0
|
|
133
|
-
});
|
|
88
|
+
metadata: this.metadata
|
|
89
|
+
};
|
|
90
|
+
const tracker = getScenePerformanceTracker();
|
|
91
|
+
tracker.notifyDashboardInteractionComplete(dashboardData);
|
|
134
92
|
__privateSet(this, _profileInProgress, null);
|
|
135
93
|
__privateSet(this, _trailAnimationFrameId, null);
|
|
136
94
|
}
|
|
137
|
-
if (window.__runs) {
|
|
138
|
-
window.__runs += `${Date.now()}, ${profileDuration + slowFramesTime}
|
|
139
|
-
`;
|
|
140
|
-
} else {
|
|
141
|
-
window.__runs = `${Date.now()}, ${profileDuration + slowFramesTime}
|
|
142
|
-
`;
|
|
143
|
-
}
|
|
144
95
|
}
|
|
145
96
|
};
|
|
146
97
|
__privateSet(this, _longFrameDetector, new LongFrameDetector());
|
|
147
98
|
this.setupVisibilityChangeHandler();
|
|
148
99
|
__privateSet(this, _interactionInProgress, null);
|
|
100
|
+
if (panelProfilingConfig) {
|
|
101
|
+
this._panelProfilingManager = new PanelProfilingManager(panelProfilingConfig);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Set generic metadata for observer notifications */
|
|
105
|
+
setMetadata(metadata) {
|
|
106
|
+
this.metadata = { ...metadata };
|
|
149
107
|
}
|
|
150
108
|
setQueryController(queryController) {
|
|
151
109
|
this.queryController = queryController;
|
|
152
110
|
}
|
|
111
|
+
/** Attach panel profiling to a scene object */
|
|
112
|
+
attachPanelProfiling(sceneObject) {
|
|
113
|
+
var _a;
|
|
114
|
+
(_a = this._panelProfilingManager) == null ? void 0 : _a.attachToScene(sceneObject);
|
|
115
|
+
}
|
|
116
|
+
/** Attach profiler to a specific panel */
|
|
117
|
+
attachProfilerToPanel(panel) {
|
|
118
|
+
var _a;
|
|
119
|
+
writePerformanceLog("SRP", "Attaching profiler to panel", panel.state.key);
|
|
120
|
+
(_a = this._panelProfilingManager) == null ? void 0 : _a.attachProfilerToPanel(panel);
|
|
121
|
+
}
|
|
153
122
|
setInteractionCompleteHandler(handler) {
|
|
154
123
|
__privateSet(this, _onInteractionComplete, handler != null ? handler : null);
|
|
155
124
|
}
|
|
@@ -159,7 +128,7 @@ class SceneRenderProfiler {
|
|
|
159
128
|
}
|
|
160
129
|
__privateSet(this, _visibilityChangeHandler, () => {
|
|
161
130
|
if (document.hidden && __privateGet(this, _profileInProgress)) {
|
|
162
|
-
|
|
131
|
+
writePerformanceLog("SRP", "Tab became inactive, cancelling profile");
|
|
163
132
|
this.cancelProfile();
|
|
164
133
|
}
|
|
165
134
|
});
|
|
@@ -168,16 +137,18 @@ class SceneRenderProfiler {
|
|
|
168
137
|
}
|
|
169
138
|
}
|
|
170
139
|
cleanup() {
|
|
140
|
+
var _a;
|
|
171
141
|
if (__privateGet(this, _visibilityChangeHandler) && typeof document !== "undefined") {
|
|
172
142
|
document.removeEventListener("visibilitychange", __privateGet(this, _visibilityChangeHandler));
|
|
173
143
|
__privateSet(this, _visibilityChangeHandler, null);
|
|
174
144
|
}
|
|
175
145
|
__privateGet(this, _longFrameDetector).stop();
|
|
176
146
|
this.cancelProfile();
|
|
147
|
+
(_a = this._panelProfilingManager) == null ? void 0 : _a.cleanup();
|
|
177
148
|
}
|
|
178
149
|
startProfile(name) {
|
|
179
150
|
if (document.hidden) {
|
|
180
|
-
|
|
151
|
+
writePerformanceLog("SRP", "Tab is inactive, skipping profile", name);
|
|
181
152
|
return;
|
|
182
153
|
}
|
|
183
154
|
if (__privateGet(this, _profileInProgress)) {
|
|
@@ -193,14 +164,14 @@ class SceneRenderProfiler {
|
|
|
193
164
|
}
|
|
194
165
|
startInteraction(interaction) {
|
|
195
166
|
if (__privateGet(this, _interactionInProgress)) {
|
|
196
|
-
|
|
167
|
+
writePerformanceLog("SRP", "Cancelled interaction:", __privateGet(this, _interactionInProgress));
|
|
197
168
|
__privateSet(this, _interactionInProgress, null);
|
|
198
169
|
}
|
|
199
170
|
__privateSet(this, _interactionInProgress, {
|
|
200
171
|
interaction,
|
|
201
172
|
startTs: performance.now()
|
|
202
173
|
});
|
|
203
|
-
|
|
174
|
+
writePerformanceLog("SRP", "Started interaction:", interaction);
|
|
204
175
|
}
|
|
205
176
|
stopInteraction() {
|
|
206
177
|
if (!__privateGet(this, _interactionInProgress)) {
|
|
@@ -209,11 +180,10 @@ class SceneRenderProfiler {
|
|
|
209
180
|
const endTs = performance.now();
|
|
210
181
|
const interactionDuration = endTs - __privateGet(this, _interactionInProgress).startTs;
|
|
211
182
|
const networkDuration = captureNetwork(__privateGet(this, _interactionInProgress).startTs, endTs);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
writeSceneLog("", ` \u2514\u2500 EndTs: ${endTs.toFixed(1)}ms`);
|
|
183
|
+
writePerformanceLog(
|
|
184
|
+
"SRP",
|
|
185
|
+
`[INTERACTION] Complete: ${interactionDuration.toFixed(1)}ms total | ${networkDuration.toFixed(1)}ms network`
|
|
186
|
+
);
|
|
217
187
|
if (__privateGet(this, _onInteractionComplete) && __privateGet(this, _profileInProgress)) {
|
|
218
188
|
__privateGet(this, _onInteractionComplete).call(this, {
|
|
219
189
|
origin: __privateGet(this, _interactionInProgress).interaction,
|
|
@@ -241,32 +211,24 @@ class SceneRenderProfiler {
|
|
|
241
211
|
return (_b = (_a = __privateGet(this, _interactionInProgress)) == null ? void 0 : _a.interaction) != null ? _b : null;
|
|
242
212
|
}
|
|
243
213
|
/**
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* @param
|
|
247
|
-
* @param force - Whether this is a "forced" profile (true) or "clean" profile (false)
|
|
248
|
-
* - "forced": Started by canceling an existing profile that was recording trailing frames
|
|
249
|
-
* This happens when a new user interaction occurs before the previous one
|
|
250
|
-
* finished measuring its performance impact
|
|
251
|
-
* - "clean": Started when no profile is currently active
|
|
214
|
+
* Start new performance profile
|
|
215
|
+
* @param name - Profile trigger (e.g., 'time_range_change')
|
|
216
|
+
* @param force - True if canceling existing profile, false if starting clean
|
|
252
217
|
*/
|
|
253
218
|
_startNewProfile(name, force = false) {
|
|
254
|
-
|
|
219
|
+
const profileType = force ? "forced" : "clean";
|
|
220
|
+
writePerformanceLog("SRP", `[PROFILER] ${name} started (${profileType})`);
|
|
255
221
|
__privateSet(this, _profileInProgress, { origin: name, crumbs: [] });
|
|
256
222
|
__privateSet(this, _profileStartTs, performance.now());
|
|
257
223
|
__privateSet(this, _longFramesCount, 0);
|
|
258
224
|
__privateSet(this, _longFramesTotalTime, 0);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
"color: #FFCC00; font-weight: bold;"
|
|
267
|
-
);
|
|
268
|
-
writeSceneLog("", ` \u251C\u2500 Origin: ${((_a = __privateGet(this, _profileInProgress)) == null ? void 0 : _a.origin) || "unknown"}`);
|
|
269
|
-
writeSceneLog("", ` \u2514\u2500 Timestamp: ${__privateGet(this, _profileStartTs).toFixed(1)}ms`);
|
|
225
|
+
__privateSet(this, _currentOperationId, generateOperationId("dashboard"));
|
|
226
|
+
getScenePerformanceTracker().notifyDashboardInteractionStart({
|
|
227
|
+
operationId: __privateGet(this, _currentOperationId),
|
|
228
|
+
interactionType: name,
|
|
229
|
+
timestamp: __privateGet(this, _profileStartTs),
|
|
230
|
+
metadata: this.metadata
|
|
231
|
+
});
|
|
270
232
|
__privateGet(this, _longFrameDetector).start((event) => {
|
|
271
233
|
if (!__privateGet(this, _profileInProgress) || !__privateGet(this, _profileStartTs)) {
|
|
272
234
|
return;
|
|
@@ -285,12 +247,9 @@ class SceneRenderProfiler {
|
|
|
285
247
|
}
|
|
286
248
|
tryCompletingProfile() {
|
|
287
249
|
var _a;
|
|
288
|
-
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
writeSceneLog("SceneRenderProfiler", "Trying to complete profile", __privateGet(this, _profileInProgress));
|
|
250
|
+
writePerformanceLog("SRP", "Trying to complete profile", __privateGet(this, _profileInProgress));
|
|
292
251
|
if (((_a = this.queryController) == null ? void 0 : _a.runningQueriesCount()) === 0 && __privateGet(this, _profileInProgress)) {
|
|
293
|
-
|
|
252
|
+
writePerformanceLog("SRP", "All queries completed, stopping profile");
|
|
294
253
|
this.recordProfileTail(performance.now(), __privateGet(this, _profileStartTs));
|
|
295
254
|
}
|
|
296
255
|
}
|
|
@@ -301,20 +260,19 @@ class SceneRenderProfiler {
|
|
|
301
260
|
if (__privateGet(this, _trailAnimationFrameId)) {
|
|
302
261
|
cancelAnimationFrame(__privateGet(this, _trailAnimationFrameId));
|
|
303
262
|
__privateSet(this, _trailAnimationFrameId, null);
|
|
304
|
-
|
|
263
|
+
writePerformanceLog("SRP", "Cancelled recording frames, new profile started");
|
|
305
264
|
}
|
|
306
265
|
}
|
|
307
|
-
// cancel profile
|
|
308
266
|
cancelProfile() {
|
|
309
267
|
if (__privateGet(this, _profileInProgress)) {
|
|
310
|
-
|
|
268
|
+
writePerformanceLog("SRP", "Cancelling profile", __privateGet(this, _profileInProgress));
|
|
311
269
|
__privateSet(this, _profileInProgress, null);
|
|
312
270
|
if (__privateGet(this, _trailAnimationFrameId)) {
|
|
313
271
|
cancelAnimationFrame(__privateGet(this, _trailAnimationFrameId));
|
|
314
272
|
__privateSet(this, _trailAnimationFrameId, null);
|
|
315
273
|
}
|
|
316
274
|
__privateGet(this, _longFrameDetector).stop();
|
|
317
|
-
|
|
275
|
+
writePerformanceLog("SRP", "Stopped long frame detection - profile cancelled");
|
|
318
276
|
__privateSet(this, _recordedTrailingSpans, []);
|
|
319
277
|
__privateSet(this, _longFramesCount, 0);
|
|
320
278
|
__privateSet(this, _longFramesTotalTime, 0);
|
|
@@ -322,7 +280,13 @@ class SceneRenderProfiler {
|
|
|
322
280
|
}
|
|
323
281
|
addCrumb(crumb) {
|
|
324
282
|
if (__privateGet(this, _profileInProgress)) {
|
|
325
|
-
|
|
283
|
+
getScenePerformanceTracker().notifyDashboardInteractionMilestone({
|
|
284
|
+
operationId: generateOperationId("dashboard-milestone"),
|
|
285
|
+
interactionType: __privateGet(this, _profileInProgress).origin,
|
|
286
|
+
timestamp: performance.now(),
|
|
287
|
+
milestone: crumb,
|
|
288
|
+
metadata: this.metadata
|
|
289
|
+
});
|
|
326
290
|
__privateGet(this, _profileInProgress).crumbs.push(crumb);
|
|
327
291
|
}
|
|
328
292
|
}
|
|
@@ -331,6 +295,7 @@ _profileInProgress = new WeakMap();
|
|
|
331
295
|
_interactionInProgress = new WeakMap();
|
|
332
296
|
_profileStartTs = new WeakMap();
|
|
333
297
|
_trailAnimationFrameId = new WeakMap();
|
|
298
|
+
_currentOperationId = new WeakMap();
|
|
334
299
|
_recordedTrailingSpans = new WeakMap();
|
|
335
300
|
_longFrameDetector = new WeakMap();
|
|
336
301
|
_longFramesCount = new WeakMap();
|
|
@@ -379,16 +344,6 @@ function calculateNetworkTime(requests) {
|
|
|
379
344
|
totalNetworkTime += currentEnd - currentStart;
|
|
380
345
|
return totalNetworkTime;
|
|
381
346
|
}
|
|
382
|
-
const REFRESH_INTERACTION = "refresh";
|
|
383
|
-
const TIME_RANGE_CHANGE_INTERACTION = "time_range_change";
|
|
384
|
-
const FILTER_REMOVED_INTERACTION = "filter_removed";
|
|
385
|
-
const FILTER_CHANGED_INTERACTION = "filter_changed";
|
|
386
|
-
const FILTER_RESTORED_INTERACTION = "filter_restored";
|
|
387
|
-
const VARIABLE_VALUE_CHANGED_INTERACTION = "variable_value_changed";
|
|
388
|
-
const SCOPES_CHANGED_INTERACTION = "scopes_changed";
|
|
389
|
-
const ADHOC_KEYS_DROPDOWN_INTERACTION = "adhoc_keys_dropdown";
|
|
390
|
-
const ADHOC_VALUES_DROPDOWN_INTERACTION = "adhoc_values_dropdown";
|
|
391
|
-
const GROUPBY_DIMENSIONS_INTERACTION = "groupby_dimensions";
|
|
392
347
|
|
|
393
|
-
export {
|
|
348
|
+
export { SceneRenderProfiler, calculateNetworkTime, captureNetwork, processRecordedSpans };
|
|
394
349
|
//# sourceMappingURL=SceneRenderProfiler.js.map
|