@grafana/scenes 6.29.2--canary.1202.16723575264.0 → 6.29.2--canary.1205.16747480830.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/dist/esm/behaviors/SceneRenderProfiler.js +48 -2
- package/dist/esm/behaviors/SceneRenderProfiler.js.map +1 -1
- package/dist/esm/variables/adhoc/getAdHocFiltersFromScopes.js +3 -20
- package/dist/esm/variables/adhoc/getAdHocFiltersFromScopes.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +50 -21
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -7,9 +7,10 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
|
|
|
7
7
|
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
8
8
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
9
9
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
10
|
-
var _profileInProgress, _profileStartTs, _trailAnimationFrameId, _recordedTrailingSpans;
|
|
10
|
+
var _profileInProgress, _profileStartTs, _trailAnimationFrameId, _recordedTrailingSpans, _visibilityChangeHandler;
|
|
11
11
|
const POST_STORM_WINDOW = 2e3;
|
|
12
12
|
const SPAN_THRESHOLD = 30;
|
|
13
|
+
const TAB_INACTIVE_THRESHOLD = 1e3;
|
|
13
14
|
class SceneRenderProfiler {
|
|
14
15
|
constructor(queryController) {
|
|
15
16
|
this.queryController = queryController;
|
|
@@ -19,10 +20,18 @@ class SceneRenderProfiler {
|
|
|
19
20
|
// Will keep measured lengths trailing frames
|
|
20
21
|
__privateAdd(this, _recordedTrailingSpans, []);
|
|
21
22
|
this.lastFrameTime = 0;
|
|
23
|
+
__privateAdd(this, _visibilityChangeHandler, null);
|
|
22
24
|
this.measureTrailingFrames = (measurementStartTs, lastFrameTime, profileStartTs) => {
|
|
23
25
|
var _a;
|
|
24
26
|
const currentFrameTime = performance.now();
|
|
25
27
|
const frameLength = currentFrameTime - lastFrameTime;
|
|
28
|
+
if (frameLength > TAB_INACTIVE_THRESHOLD) {
|
|
29
|
+
writeSceneLog("SceneRenderProfiler", "Tab was inactive, cancelling profile measurement");
|
|
30
|
+
__privateSet(this, _recordedTrailingSpans, []);
|
|
31
|
+
__privateSet(this, _profileInProgress, null);
|
|
32
|
+
__privateSet(this, _trailAnimationFrameId, null);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
26
35
|
__privateGet(this, _recordedTrailingSpans).push(frameLength);
|
|
27
36
|
if (currentFrameTime - measurementStartTs < POST_STORM_WINDOW) {
|
|
28
37
|
if (__privateGet(this, _profileInProgress)) {
|
|
@@ -49,12 +58,15 @@ class SceneRenderProfiler {
|
|
|
49
58
|
);
|
|
50
59
|
__privateSet(this, _trailAnimationFrameId, null);
|
|
51
60
|
const profileEndTs = profileStartTs + profileDuration + slowFramesTime;
|
|
61
|
+
if (!__privateGet(this, _profileInProgress)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
52
64
|
performance.measure(`DashboardInteraction ${__privateGet(this, _profileInProgress).origin}`, {
|
|
53
65
|
start: profileStartTs,
|
|
54
66
|
end: profileEndTs
|
|
55
67
|
});
|
|
56
68
|
const networkDuration = captureNetwork(profileStartTs, profileEndTs);
|
|
57
|
-
if ((_a = this.queryController) == null ? void 0 : _a.state.onProfileComplete) {
|
|
69
|
+
if (((_a = this.queryController) == null ? void 0 : _a.state.onProfileComplete) && __privateGet(this, _profileInProgress)) {
|
|
58
70
|
this.queryController.state.onProfileComplete({
|
|
59
71
|
origin: __privateGet(this, _profileInProgress).origin,
|
|
60
72
|
crumbs: __privateGet(this, _profileInProgress).crumbs,
|
|
@@ -81,10 +93,32 @@ class SceneRenderProfiler {
|
|
|
81
93
|
}
|
|
82
94
|
}
|
|
83
95
|
};
|
|
96
|
+
this.setupVisibilityChangeHandler();
|
|
84
97
|
}
|
|
85
98
|
setQueryController(queryController) {
|
|
86
99
|
this.queryController = queryController;
|
|
87
100
|
}
|
|
101
|
+
setupVisibilityChangeHandler() {
|
|
102
|
+
if (__privateGet(this, _visibilityChangeHandler)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
__privateSet(this, _visibilityChangeHandler, () => {
|
|
106
|
+
if (document.hidden && __privateGet(this, _profileInProgress)) {
|
|
107
|
+
writeSceneLog("SceneRenderProfiler", "Tab became inactive, cancelling profile");
|
|
108
|
+
this.cancelProfile();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
if (typeof document !== "undefined") {
|
|
112
|
+
document.addEventListener("visibilitychange", __privateGet(this, _visibilityChangeHandler));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
cleanup() {
|
|
116
|
+
if (__privateGet(this, _visibilityChangeHandler) && typeof document !== "undefined") {
|
|
117
|
+
document.removeEventListener("visibilitychange", __privateGet(this, _visibilityChangeHandler));
|
|
118
|
+
__privateSet(this, _visibilityChangeHandler, null);
|
|
119
|
+
}
|
|
120
|
+
this.cancelProfile();
|
|
121
|
+
}
|
|
88
122
|
startProfile(name) {
|
|
89
123
|
if (__privateGet(this, _profileInProgress)) {
|
|
90
124
|
this.addCrumb(name);
|
|
@@ -117,6 +151,17 @@ class SceneRenderProfiler {
|
|
|
117
151
|
writeSceneLog("SceneRenderProfiler", "Cancelled recording frames, new profile started");
|
|
118
152
|
}
|
|
119
153
|
}
|
|
154
|
+
// cancel profile
|
|
155
|
+
cancelProfile() {
|
|
156
|
+
if (__privateGet(this, _profileInProgress)) {
|
|
157
|
+
writeSceneLog("SceneRenderProfiler", "Cancelling profile", __privateGet(this, _profileInProgress));
|
|
158
|
+
__privateSet(this, _profileInProgress, null);
|
|
159
|
+
if (__privateGet(this, _trailAnimationFrameId)) {
|
|
160
|
+
cancelAnimationFrame(__privateGet(this, _trailAnimationFrameId));
|
|
161
|
+
__privateSet(this, _trailAnimationFrameId, null);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
120
165
|
addCrumb(crumb) {
|
|
121
166
|
if (__privateGet(this, _profileInProgress)) {
|
|
122
167
|
writeSceneLog("SceneRenderProfiler", "Adding crumb:", crumb);
|
|
@@ -128,6 +173,7 @@ _profileInProgress = new WeakMap();
|
|
|
128
173
|
_profileStartTs = new WeakMap();
|
|
129
174
|
_trailAnimationFrameId = new WeakMap();
|
|
130
175
|
_recordedTrailingSpans = new WeakMap();
|
|
176
|
+
_visibilityChangeHandler = new WeakMap();
|
|
131
177
|
function processRecordedSpans(spans) {
|
|
132
178
|
for (let i = spans.length - 1; i >= 0; i--) {
|
|
133
179
|
if (spans[i] > SPAN_THRESHOLD) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneRenderProfiler.js","sources":["../../../src/behaviors/SceneRenderProfiler.ts"],"sourcesContent":["import { writeSceneLog } from '../utils/writeSceneLog';\nimport { SceneQueryControllerLike } from './types';\n\nconst POST_STORM_WINDOW = 2000; // Time after last query to observe slow frames\nconst SPAN_THRESHOLD = 30; // Frames longer than this will be considered slow\n\nexport class SceneRenderProfiler {\n #profileInProgress: {\n // Profile origin, i.e. scene refresh picker\n origin: string;\n crumbs: string[];\n } | null = null;\n\n #profileStartTs: number | null = null;\n #trailAnimationFrameId: number | null = null;\n\n // Will keep measured lengths trailing frames\n #recordedTrailingSpans: number[] = [];\n\n lastFrameTime = 0;\n\n public constructor(private queryController?: SceneQueryControllerLike) {}\n\n public setQueryController(queryController: SceneQueryControllerLike) {\n this.queryController = queryController;\n }\n\n public startProfile(name: string) {\n if (this.#profileInProgress) {\n this.addCrumb(name);\n } else {\n this.#profileInProgress = { origin: name, crumbs: [] };\n this.#profileStartTs = performance.now();\n writeSceneLog('SceneRenderProfiler', 'Profile started:', this.#profileInProgress, this.#profileStartTs);\n }\n }\n\n private recordProfileTail(measurementStartTime: number, profileStartTs: number) {\n this.#trailAnimationFrameId = requestAnimationFrame(() =>\n this.measureTrailingFrames(measurementStartTime, measurementStartTime, profileStartTs)\n );\n }\n\n private measureTrailingFrames = (measurementStartTs: number, lastFrameTime: number, profileStartTs: number) => {\n const currentFrameTime = performance.now();\n const frameLength = currentFrameTime - lastFrameTime;\n this.#recordedTrailingSpans.push(frameLength);\n\n if (currentFrameTime - measurementStartTs! < POST_STORM_WINDOW) {\n if (this.#profileInProgress) {\n this.#trailAnimationFrameId = requestAnimationFrame(() =>\n this.measureTrailingFrames(measurementStartTs, currentFrameTime, profileStartTs)\n );\n }\n } else {\n const slowFrames = processRecordedSpans(this.#recordedTrailingSpans);\n const slowFramesTime = slowFrames.reduce((acc, val) => acc + val, 0);\n\n writeSceneLog(\n this.constructor.name,\n 'Profile tail recorded, slow frames duration:',\n slowFramesTime,\n slowFrames,\n this.#profileInProgress\n );\n\n this.#recordedTrailingSpans = [];\n\n const profileDuration = measurementStartTs - profileStartTs;\n\n writeSceneLog(\n this.constructor.name,\n 'Stoped recording, total measured time (network included):',\n profileDuration + slowFramesTime\n );\n this.#trailAnimationFrameId = null;\n\n const profileEndTs = profileStartTs + profileDuration + slowFramesTime;\n performance.measure(`DashboardInteraction ${this.#profileInProgress!.origin}`, {\n start: profileStartTs,\n end: profileEndTs,\n });\n\n const networkDuration = captureNetwork(profileStartTs, profileEndTs);\n\n if (this.queryController?.state.onProfileComplete) {\n this.queryController.state.onProfileComplete({\n origin: this.#profileInProgress!.origin,\n crumbs: this.#profileInProgress!.crumbs,\n duration: profileDuration + slowFramesTime,\n networkDuration,\n startTs: profileStartTs,\n endTs: profileEndTs,\n // @ts-ignore\n jsHeapSizeLimit: performance.memory ? performance.memory.jsHeapSizeLimit : 0,\n // @ts-ignore\n usedJSHeapSize: performance.memory ? performance.memory.usedJSHeapSize : 0,\n // @ts-ignore\n totalJSHeapSize: performance.memory ? performance.memory.totalJSHeapSize : 0,\n });\n\n this.#profileInProgress = null;\n this.#trailAnimationFrameId = null;\n }\n // @ts-ignore\n if (window.__runs) {\n // @ts-ignore\n window.__runs += `${Date.now()}, ${profileDuration + slowFramesTime}\\n`;\n } else {\n // @ts-ignore\n window.__runs = `${Date.now()}, ${profileDuration + slowFramesTime}\\n`;\n }\n }\n };\n\n public tryCompletingProfile() {\n writeSceneLog('SceneRenderProfiler', 'Trying to complete profile', this.#profileInProgress);\n if (this.queryController?.runningQueriesCount() === 0 && this.#profileInProgress) {\n writeSceneLog('SceneRenderProfiler', 'All queries completed, stopping profile');\n this.recordProfileTail(performance.now(), this.#profileStartTs!);\n }\n }\n\n public isTailRecording() {\n return Boolean(this.#trailAnimationFrameId);\n }\n public cancelTailRecording() {\n if (this.#trailAnimationFrameId) {\n cancelAnimationFrame(this.#trailAnimationFrameId);\n this.#trailAnimationFrameId = null;\n writeSceneLog('SceneRenderProfiler', 'Cancelled recording frames, new profile started');\n }\n }\n\n public addCrumb(crumb: string) {\n if (this.#profileInProgress) {\n writeSceneLog('SceneRenderProfiler', 'Adding crumb:', crumb);\n this.#profileInProgress.crumbs.push(crumb);\n }\n }\n}\n\nexport function processRecordedSpans(spans: number[]) {\n // identify last span in spans that's bigger than SPAN_THRESHOLD\n for (let i = spans.length - 1; i >= 0; i--) {\n if (spans[i] > SPAN_THRESHOLD) {\n return spans.slice(0, i + 1);\n }\n }\n return [spans[0]];\n}\n\nfunction captureNetwork(startTs: number, endTs: number) {\n const entries = performance.getEntriesByType('resource') as PerformanceResourceTiming[];\n performance.clearResourceTimings();\n const networkEntries = entries.filter((entry) => entry.startTime >= startTs && entry.startTime <= endTs);\n for (const entry of networkEntries) {\n performance.measure('Network entry ' + entry.name, {\n start: entry.startTime,\n end: entry.responseEnd,\n });\n }\n\n return calculateNetworkTime(networkEntries);\n}\n\n// Will calculate total time spent on Network\nexport function calculateNetworkTime(requests: PerformanceResourceTiming[]): number {\n if (requests.length === 0) {\n return 0;\n }\n\n // Step 1: Sort the requests by startTs\n requests.sort((a, b) => a.startTime - b.startTime);\n\n // Step 2: Initialize variables\n let totalNetworkTime = 0;\n let currentStart = requests[0].startTime;\n let currentEnd = requests[0].responseEnd;\n\n // Step 3: Iterate through the sorted list and merge overlapping intervals\n for (let i = 1; i < requests.length; i++) {\n if (requests[i].startTime <= currentEnd) {\n // Overlapping intervals, merge them\n currentEnd = Math.max(currentEnd, requests[i].responseEnd);\n } else {\n // Non-overlapping interval, add the duration to total time\n totalNetworkTime += currentEnd - currentStart;\n\n // Update current interval\n currentStart = requests[i].startTime;\n currentEnd = requests[i].responseEnd;\n }\n }\n\n // Step 4: Add the last interval\n totalNetworkTime += currentEnd - currentStart;\n\n return totalNetworkTime;\n}\n\nexport const REFRESH_INTERACTION = 'refresh';\nexport const TIME_RANGE_CHANGE_INTERACTION = 'time_range_change';\nexport const FILTER_ADDED_INTERACTION = 'filter_added';\nexport const FILTER_REMOVED_INTERACTION = 'filter_removed';\nexport const FILTER_CHANGED_INTERACTION = 'filter_changed';\nexport const FILTER_RESTORED_INTERACTION = 'filter_restored';\nexport const VARIABLE_VALUE_CHANGED_INTERACTION = 'variable_value_changed';\nexport const SCOPES_CHANGED_INTERACTION = 'scopes_changed';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SceneRenderProfiler.js","sources":["../../../src/behaviors/SceneRenderProfiler.ts"],"sourcesContent":["import { writeSceneLog } from '../utils/writeSceneLog';\nimport { SceneQueryControllerLike } from './types';\n\nconst POST_STORM_WINDOW = 2000; // Time after last query to observe slow frames\nconst SPAN_THRESHOLD = 30; // Frames longer than this will be considered slow\nconst TAB_INACTIVE_THRESHOLD = 1000; // Tab inactive threshold in ms\n\nexport class SceneRenderProfiler {\n #profileInProgress: {\n // Profile origin, i.e. scene refresh picker\n origin: string;\n crumbs: string[];\n } | null = null;\n\n #profileStartTs: number | null = null;\n #trailAnimationFrameId: number | null = null;\n\n // Will keep measured lengths trailing frames\n #recordedTrailingSpans: number[] = [];\n\n lastFrameTime = 0;\n #visibilityChangeHandler: (() => void) | null = null;\n\n public constructor(private queryController?: SceneQueryControllerLike) {\n this.setupVisibilityChangeHandler();\n }\n\n public setQueryController(queryController: SceneQueryControllerLike) {\n this.queryController = queryController;\n }\n\n private setupVisibilityChangeHandler() {\n // Ensure event listener is only added once\n if (this.#visibilityChangeHandler) {\n return;\n }\n\n // Handle tab switching with Page Visibility API\n this.#visibilityChangeHandler = () => {\n if (document.hidden && this.#profileInProgress) {\n writeSceneLog('SceneRenderProfiler', 'Tab became inactive, cancelling profile');\n this.cancelProfile();\n }\n };\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', this.#visibilityChangeHandler);\n }\n }\n\n public cleanup() {\n // Remove event listener to prevent memory leaks\n if (this.#visibilityChangeHandler && typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', this.#visibilityChangeHandler);\n this.#visibilityChangeHandler = null;\n }\n\n // Cancel any ongoing profiling\n this.cancelProfile();\n }\n\n public startProfile(name: string) {\n if (this.#profileInProgress) {\n this.addCrumb(name);\n } else {\n this.#profileInProgress = { origin: name, crumbs: [] };\n this.#profileStartTs = performance.now();\n writeSceneLog('SceneRenderProfiler', 'Profile started:', this.#profileInProgress, this.#profileStartTs);\n }\n }\n\n private recordProfileTail(measurementStartTime: number, profileStartTs: number) {\n this.#trailAnimationFrameId = requestAnimationFrame(() =>\n this.measureTrailingFrames(measurementStartTime, measurementStartTime, profileStartTs)\n );\n }\n\n private measureTrailingFrames = (measurementStartTs: number, lastFrameTime: number, profileStartTs: number) => {\n const currentFrameTime = performance.now();\n const frameLength = currentFrameTime - lastFrameTime;\n\n // Fallback: Detect if tab was inactive (frame longer than reasonable threshold)\n // This serves as backup to Page Visibility API in case the event wasn't triggered\n if (frameLength > TAB_INACTIVE_THRESHOLD) {\n writeSceneLog('SceneRenderProfiler', 'Tab was inactive, cancelling profile measurement');\n // Reset and cancel profiling due to tab inactivity\n this.#recordedTrailingSpans = [];\n this.#profileInProgress = null;\n this.#trailAnimationFrameId = null;\n return;\n }\n\n this.#recordedTrailingSpans.push(frameLength);\n\n if (currentFrameTime - measurementStartTs! < POST_STORM_WINDOW) {\n if (this.#profileInProgress) {\n this.#trailAnimationFrameId = requestAnimationFrame(() =>\n this.measureTrailingFrames(measurementStartTs, currentFrameTime, profileStartTs)\n );\n }\n } else {\n const slowFrames = processRecordedSpans(this.#recordedTrailingSpans);\n const slowFramesTime = slowFrames.reduce((acc, val) => acc + val, 0);\n\n writeSceneLog(\n this.constructor.name,\n 'Profile tail recorded, slow frames duration:',\n slowFramesTime,\n slowFrames,\n this.#profileInProgress\n );\n\n this.#recordedTrailingSpans = [];\n\n const profileDuration = measurementStartTs - profileStartTs;\n\n writeSceneLog(\n this.constructor.name,\n 'Stoped recording, total measured time (network included):',\n profileDuration + slowFramesTime\n );\n this.#trailAnimationFrameId = null;\n\n const profileEndTs = profileStartTs + profileDuration + slowFramesTime;\n\n // Guard against race condition where profile might be cancelled during execution\n if (!this.#profileInProgress) {\n return;\n }\n\n performance.measure(`DashboardInteraction ${this.#profileInProgress.origin}`, {\n start: profileStartTs,\n end: profileEndTs,\n });\n\n const networkDuration = captureNetwork(profileStartTs, profileEndTs);\n\n if (this.queryController?.state.onProfileComplete && this.#profileInProgress) {\n this.queryController.state.onProfileComplete({\n origin: this.#profileInProgress.origin,\n crumbs: this.#profileInProgress.crumbs,\n duration: profileDuration + slowFramesTime,\n networkDuration,\n startTs: profileStartTs,\n endTs: profileEndTs,\n // @ts-ignore\n jsHeapSizeLimit: performance.memory ? performance.memory.jsHeapSizeLimit : 0,\n // @ts-ignore\n usedJSHeapSize: performance.memory ? performance.memory.usedJSHeapSize : 0,\n // @ts-ignore\n totalJSHeapSize: performance.memory ? performance.memory.totalJSHeapSize : 0,\n });\n\n this.#profileInProgress = null;\n this.#trailAnimationFrameId = null;\n }\n // @ts-ignore\n if (window.__runs) {\n // @ts-ignore\n window.__runs += `${Date.now()}, ${profileDuration + slowFramesTime}\\n`;\n } else {\n // @ts-ignore\n window.__runs = `${Date.now()}, ${profileDuration + slowFramesTime}\\n`;\n }\n }\n };\n\n public tryCompletingProfile() {\n writeSceneLog('SceneRenderProfiler', 'Trying to complete profile', this.#profileInProgress);\n if (this.queryController?.runningQueriesCount() === 0 && this.#profileInProgress) {\n writeSceneLog('SceneRenderProfiler', 'All queries completed, stopping profile');\n this.recordProfileTail(performance.now(), this.#profileStartTs!);\n }\n }\n\n public isTailRecording() {\n return Boolean(this.#trailAnimationFrameId);\n }\n\n public cancelTailRecording() {\n if (this.#trailAnimationFrameId) {\n cancelAnimationFrame(this.#trailAnimationFrameId);\n this.#trailAnimationFrameId = null;\n writeSceneLog('SceneRenderProfiler', 'Cancelled recording frames, new profile started');\n }\n }\n\n // cancel profile\n public cancelProfile() {\n if (this.#profileInProgress) {\n writeSceneLog('SceneRenderProfiler', 'Cancelling profile', this.#profileInProgress);\n this.#profileInProgress = null;\n // Cancel any pending animation frame to prevent accessing null profileInProgress\n if (this.#trailAnimationFrameId) {\n cancelAnimationFrame(this.#trailAnimationFrameId);\n this.#trailAnimationFrameId = null;\n }\n }\n }\n\n public addCrumb(crumb: string) {\n if (this.#profileInProgress) {\n writeSceneLog('SceneRenderProfiler', 'Adding crumb:', crumb);\n this.#profileInProgress.crumbs.push(crumb);\n }\n }\n}\n\nexport function processRecordedSpans(spans: number[]) {\n // identify last span in spans that's bigger than SPAN_THRESHOLD\n for (let i = spans.length - 1; i >= 0; i--) {\n if (spans[i] > SPAN_THRESHOLD) {\n return spans.slice(0, i + 1);\n }\n }\n return [spans[0]];\n}\n\nfunction captureNetwork(startTs: number, endTs: number) {\n const entries = performance.getEntriesByType('resource') as PerformanceResourceTiming[];\n performance.clearResourceTimings();\n const networkEntries = entries.filter((entry) => entry.startTime >= startTs && entry.startTime <= endTs);\n for (const entry of networkEntries) {\n performance.measure('Network entry ' + entry.name, {\n start: entry.startTime,\n end: entry.responseEnd,\n });\n }\n\n return calculateNetworkTime(networkEntries);\n}\n\n// Will calculate total time spent on Network\nexport function calculateNetworkTime(requests: PerformanceResourceTiming[]): number {\n if (requests.length === 0) {\n return 0;\n }\n\n // Step 1: Sort the requests by startTs\n requests.sort((a, b) => a.startTime - b.startTime);\n\n // Step 2: Initialize variables\n let totalNetworkTime = 0;\n let currentStart = requests[0].startTime;\n let currentEnd = requests[0].responseEnd;\n\n // Step 3: Iterate through the sorted list and merge overlapping intervals\n for (let i = 1; i < requests.length; i++) {\n if (requests[i].startTime <= currentEnd) {\n // Overlapping intervals, merge them\n currentEnd = Math.max(currentEnd, requests[i].responseEnd);\n } else {\n // Non-overlapping interval, add the duration to total time\n totalNetworkTime += currentEnd - currentStart;\n\n // Update current interval\n currentStart = requests[i].startTime;\n currentEnd = requests[i].responseEnd;\n }\n }\n\n // Step 4: Add the last interval\n totalNetworkTime += currentEnd - currentStart;\n\n return totalNetworkTime;\n}\n\nexport const REFRESH_INTERACTION = 'refresh';\nexport const TIME_RANGE_CHANGE_INTERACTION = 'time_range_change';\nexport const FILTER_ADDED_INTERACTION = 'filter_added';\nexport const FILTER_REMOVED_INTERACTION = 'filter_removed';\nexport const FILTER_CHANGED_INTERACTION = 'filter_changed';\nexport const FILTER_RESTORED_INTERACTION = 'filter_restored';\nexport const VARIABLE_VALUE_CHANGED_INTERACTION = 'variable_value_changed';\nexport const SCOPES_CHANGED_INTERACTION = 'scopes_changed';\n"],"names":[],"mappings":"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"}
|
|
@@ -7,10 +7,6 @@ function isEqualityOrMultiOperator(value) {
|
|
|
7
7
|
const operators = /* @__PURE__ */ new Set(["equals", "not-equals", "one-of", "not-one-of"]);
|
|
8
8
|
return operators.has(value);
|
|
9
9
|
}
|
|
10
|
-
function isRegexOperator(value) {
|
|
11
|
-
const operators = /* @__PURE__ */ new Set(["regex-match", "regex-not-match"]);
|
|
12
|
-
return operators.has(value);
|
|
13
|
-
}
|
|
14
10
|
function getAdHocFiltersFromScopes(scopes) {
|
|
15
11
|
const formattedFilters = /* @__PURE__ */ new Map();
|
|
16
12
|
const duplicatedFilters = [];
|
|
@@ -26,11 +22,8 @@ function processFilter(formattedFilters, duplicatedFilters, filter) {
|
|
|
26
22
|
return;
|
|
27
23
|
}
|
|
28
24
|
const existingFilter = formattedFilters.get(filter.key);
|
|
29
|
-
if (existingFilter &&
|
|
25
|
+
if (existingFilter && canValueBeMerged(existingFilter.operator, filter.operator)) {
|
|
30
26
|
mergeFilterValues(existingFilter, filter);
|
|
31
|
-
} else if (existingFilter && isRegexValue(existingFilter.operator, filter.operator)) {
|
|
32
|
-
existingFilter.value += `|${filter.value}`;
|
|
33
|
-
existingFilter.values = [existingFilter.value];
|
|
34
27
|
} else if (!existingFilter) {
|
|
35
28
|
formattedFilters.set(filter.key, {
|
|
36
29
|
key: filter.key,
|
|
@@ -66,26 +59,16 @@ function mergeFilterValues(adHocFilter, filter) {
|
|
|
66
59
|
adHocFilter.operator = reverseScopeFilterOperatorMap["not-one-of"];
|
|
67
60
|
}
|
|
68
61
|
}
|
|
69
|
-
function
|
|
70
|
-
const scopeConvertedOperator = scopeFilterOperatorMap[adHocFilterOperator];
|
|
71
|
-
if (!isRegexOperator(scopeConvertedOperator) || !isRegexOperator(filterOperator)) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
return hasSameOperators(scopeConvertedOperator, filterOperator);
|
|
75
|
-
}
|
|
76
|
-
function isEqualityValue(adHocFilterOperator, filterOperator) {
|
|
62
|
+
function canValueBeMerged(adHocFilterOperator, filterOperator) {
|
|
77
63
|
const scopeConvertedOperator = scopeFilterOperatorMap[adHocFilterOperator];
|
|
78
64
|
if (!isEqualityOrMultiOperator(scopeConvertedOperator) || !isEqualityOrMultiOperator(filterOperator)) {
|
|
79
65
|
return false;
|
|
80
66
|
}
|
|
81
|
-
return hasSameOperators(scopeConvertedOperator, filterOperator);
|
|
82
|
-
}
|
|
83
|
-
function hasSameOperators(scopeConvertedOperator, filterOperator) {
|
|
84
67
|
if (scopeConvertedOperator.includes("not") && !filterOperator.includes("not") || !scopeConvertedOperator.includes("not") && filterOperator.includes("not")) {
|
|
85
68
|
return false;
|
|
86
69
|
}
|
|
87
70
|
return true;
|
|
88
71
|
}
|
|
89
72
|
|
|
90
|
-
export { getAdHocFiltersFromScopes, isEqualityOrMultiOperator,
|
|
73
|
+
export { getAdHocFiltersFromScopes, isEqualityOrMultiOperator, reverseScopeFilterOperatorMap };
|
|
91
74
|
//# sourceMappingURL=getAdHocFiltersFromScopes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getAdHocFiltersFromScopes.js","sources":["../../../../src/variables/adhoc/getAdHocFiltersFromScopes.ts"],"sourcesContent":["import { Scope, ScopeFilterOperator, ScopeSpecFilter, scopeFilterOperatorMap } from '@grafana/data';\nimport { AdHocFilterWithLabels } from './AdHocFiltersVariable';\n\nexport type EqualityOrMultiOperator = Extract<ScopeFilterOperator, 'equals' | 'not-equals' | 'one-of' | 'not-one-of'>;\
|
|
1
|
+
{"version":3,"file":"getAdHocFiltersFromScopes.js","sources":["../../../../src/variables/adhoc/getAdHocFiltersFromScopes.ts"],"sourcesContent":["import { Scope, ScopeFilterOperator, ScopeSpecFilter, scopeFilterOperatorMap } from '@grafana/data';\nimport { AdHocFilterWithLabels } from './AdHocFiltersVariable';\n\nexport type EqualityOrMultiOperator = Extract<ScopeFilterOperator, 'equals' | 'not-equals' | 'one-of' | 'not-one-of'>;\n\nexport const reverseScopeFilterOperatorMap: Record<ScopeFilterOperator, string> = Object.fromEntries(\n Object.entries(scopeFilterOperatorMap).map(([symbol, operator]) => [operator, symbol])\n) as Record<ScopeFilterOperator, string>;\n\nexport function isEqualityOrMultiOperator(value: string): value is EqualityOrMultiOperator {\n const operators = new Set(['equals', 'not-equals', 'one-of', 'not-one-of']);\n return operators.has(value);\n}\n\n// this function returns processed adhoc filters after parsing and processing\n// all scope filters from a scope list. The reason we need to process these filters is\n// because scopes can have multiple filter values with the same key. For example:\n// we have selected ScopeA which has a filter with a key1, operator one-of, a value1,\n// and a ScopeB which has a filter with key1, operator one-of, and value2. After processing,\n// the result will be just one adhoc filter with both values. This is held in formattedFilters.\n// DuplicatedFilters will containg unprocessable filters: if scopeA has instead of the one-of op\n// an equal op, then the result will be 2 adhoc filters with the same key, but diferent operator\n// and value. We return them this way and let the adhoc interface deal with this.\nexport function getAdHocFiltersFromScopes(scopes: Scope[]): AdHocFilterWithLabels[] {\n const formattedFilters: Map<string, AdHocFilterWithLabels> = new Map();\n // duplicated filters that could not be processed in any way are just appended to the list\n const duplicatedFilters: AdHocFilterWithLabels[] = [];\n const allFilters = scopes.flatMap((scope) => scope.spec.filters);\n\n for (const filter of allFilters) {\n processFilter(formattedFilters, duplicatedFilters, filter);\n }\n\n return [...formattedFilters.values(), ...duplicatedFilters];\n}\n\nfunction processFilter(\n formattedFilters: Map<string, AdHocFilterWithLabels>,\n duplicatedFilters: AdHocFilterWithLabels[],\n filter: ScopeSpecFilter\n) {\n if (!filter) {\n return;\n }\n\n const existingFilter = formattedFilters.get(filter.key);\n\n if (existingFilter && canValueBeMerged(existingFilter.operator, filter.operator)) {\n mergeFilterValues(existingFilter, filter);\n } else if (!existingFilter) {\n // Add filter to map either only if it is new.\n // Otherwise it is an existing filter that cannot be converted to multi-value\n // and thus will be moved to the duplicatedFilters list\n formattedFilters.set(filter.key, {\n key: filter.key,\n operator: reverseScopeFilterOperatorMap[filter.operator],\n value: filter.value,\n values: filter.values ?? [filter.value],\n origin: 'scope',\n });\n } else {\n duplicatedFilters.push({\n key: filter.key,\n operator: reverseScopeFilterOperatorMap[filter.operator],\n value: filter.value,\n values: filter.values ?? [filter.value],\n origin: 'scope',\n });\n }\n}\n\nfunction mergeFilterValues(adHocFilter: AdHocFilterWithLabels, filter: ScopeSpecFilter) {\n const values = filter.values ?? [filter.value];\n\n for (const value of values) {\n if (!adHocFilter.values?.includes(value)) {\n adHocFilter.values?.push(value);\n }\n }\n\n // If there's only one value, there's no need to update the\n // operator to its multi-value equivalent\n if (adHocFilter.values?.length === 1) {\n return;\n }\n\n // Otherwise update it to the equivalent multi-value operator\n if (filter.operator === 'equals' && adHocFilter.operator === reverseScopeFilterOperatorMap['equals']) {\n adHocFilter.operator = reverseScopeFilterOperatorMap['one-of'];\n } else if (filter.operator === 'not-equals' && adHocFilter.operator === reverseScopeFilterOperatorMap['not-equals']) {\n adHocFilter.operator = reverseScopeFilterOperatorMap['not-one-of'];\n }\n}\n\nfunction canValueBeMerged(adHocFilterOperator: string, filterOperator: string) {\n const scopeConvertedOperator = scopeFilterOperatorMap[adHocFilterOperator];\n\n if (!isEqualityOrMultiOperator(scopeConvertedOperator) || !isEqualityOrMultiOperator(filterOperator)) {\n return false;\n }\n\n if (\n (scopeConvertedOperator.includes('not') && !filterOperator.includes('not')) ||\n (!scopeConvertedOperator.includes('not') && filterOperator.includes('not'))\n ) {\n return false;\n }\n\n return true;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1505,12 +1505,15 @@ declare class SceneRenderProfiler {
|
|
|
1505
1505
|
lastFrameTime: number;
|
|
1506
1506
|
constructor(queryController?: SceneQueryControllerLike | undefined);
|
|
1507
1507
|
setQueryController(queryController: SceneQueryControllerLike): void;
|
|
1508
|
+
private setupVisibilityChangeHandler;
|
|
1509
|
+
cleanup(): void;
|
|
1508
1510
|
startProfile(name: string): void;
|
|
1509
1511
|
private recordProfileTail;
|
|
1510
1512
|
private measureTrailingFrames;
|
|
1511
1513
|
tryCompletingProfile(): void;
|
|
1512
1514
|
isTailRecording(): boolean;
|
|
1513
1515
|
cancelTailRecording(): void;
|
|
1516
|
+
cancelProfile(): void;
|
|
1514
1517
|
addCrumb(crumb: string): void;
|
|
1515
1518
|
}
|
|
1516
1519
|
|
package/dist/index.js
CHANGED
|
@@ -854,9 +854,10 @@ var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Ca
|
|
|
854
854
|
var __privateGet$2 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
855
855
|
var __privateAdd$2 = (obj, member, value) => member.has(obj) ? __typeError$2("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
856
856
|
var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$2(obj, member, "write to private field"), member.set(obj, value), value);
|
|
857
|
-
var _profileInProgress, _profileStartTs, _trailAnimationFrameId, _recordedTrailingSpans;
|
|
857
|
+
var _profileInProgress, _profileStartTs, _trailAnimationFrameId, _recordedTrailingSpans, _visibilityChangeHandler;
|
|
858
858
|
const POST_STORM_WINDOW = 2e3;
|
|
859
859
|
const SPAN_THRESHOLD = 30;
|
|
860
|
+
const TAB_INACTIVE_THRESHOLD = 1e3;
|
|
860
861
|
class SceneRenderProfiler {
|
|
861
862
|
constructor(queryController) {
|
|
862
863
|
this.queryController = queryController;
|
|
@@ -866,10 +867,18 @@ class SceneRenderProfiler {
|
|
|
866
867
|
// Will keep measured lengths trailing frames
|
|
867
868
|
__privateAdd$2(this, _recordedTrailingSpans, []);
|
|
868
869
|
this.lastFrameTime = 0;
|
|
870
|
+
__privateAdd$2(this, _visibilityChangeHandler, null);
|
|
869
871
|
this.measureTrailingFrames = (measurementStartTs, lastFrameTime, profileStartTs) => {
|
|
870
872
|
var _a;
|
|
871
873
|
const currentFrameTime = performance.now();
|
|
872
874
|
const frameLength = currentFrameTime - lastFrameTime;
|
|
875
|
+
if (frameLength > TAB_INACTIVE_THRESHOLD) {
|
|
876
|
+
writeSceneLog("SceneRenderProfiler", "Tab was inactive, cancelling profile measurement");
|
|
877
|
+
__privateSet$2(this, _recordedTrailingSpans, []);
|
|
878
|
+
__privateSet$2(this, _profileInProgress, null);
|
|
879
|
+
__privateSet$2(this, _trailAnimationFrameId, null);
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
873
882
|
__privateGet$2(this, _recordedTrailingSpans).push(frameLength);
|
|
874
883
|
if (currentFrameTime - measurementStartTs < POST_STORM_WINDOW) {
|
|
875
884
|
if (__privateGet$2(this, _profileInProgress)) {
|
|
@@ -896,12 +905,15 @@ class SceneRenderProfiler {
|
|
|
896
905
|
);
|
|
897
906
|
__privateSet$2(this, _trailAnimationFrameId, null);
|
|
898
907
|
const profileEndTs = profileStartTs + profileDuration + slowFramesTime;
|
|
908
|
+
if (!__privateGet$2(this, _profileInProgress)) {
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
899
911
|
performance.measure(`DashboardInteraction ${__privateGet$2(this, _profileInProgress).origin}`, {
|
|
900
912
|
start: profileStartTs,
|
|
901
913
|
end: profileEndTs
|
|
902
914
|
});
|
|
903
915
|
const networkDuration = captureNetwork(profileStartTs, profileEndTs);
|
|
904
|
-
if ((_a = this.queryController) == null ? void 0 : _a.state.onProfileComplete) {
|
|
916
|
+
if (((_a = this.queryController) == null ? void 0 : _a.state.onProfileComplete) && __privateGet$2(this, _profileInProgress)) {
|
|
905
917
|
this.queryController.state.onProfileComplete({
|
|
906
918
|
origin: __privateGet$2(this, _profileInProgress).origin,
|
|
907
919
|
crumbs: __privateGet$2(this, _profileInProgress).crumbs,
|
|
@@ -928,10 +940,32 @@ class SceneRenderProfiler {
|
|
|
928
940
|
}
|
|
929
941
|
}
|
|
930
942
|
};
|
|
943
|
+
this.setupVisibilityChangeHandler();
|
|
931
944
|
}
|
|
932
945
|
setQueryController(queryController) {
|
|
933
946
|
this.queryController = queryController;
|
|
934
947
|
}
|
|
948
|
+
setupVisibilityChangeHandler() {
|
|
949
|
+
if (__privateGet$2(this, _visibilityChangeHandler)) {
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
__privateSet$2(this, _visibilityChangeHandler, () => {
|
|
953
|
+
if (document.hidden && __privateGet$2(this, _profileInProgress)) {
|
|
954
|
+
writeSceneLog("SceneRenderProfiler", "Tab became inactive, cancelling profile");
|
|
955
|
+
this.cancelProfile();
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
if (typeof document !== "undefined") {
|
|
959
|
+
document.addEventListener("visibilitychange", __privateGet$2(this, _visibilityChangeHandler));
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
cleanup() {
|
|
963
|
+
if (__privateGet$2(this, _visibilityChangeHandler) && typeof document !== "undefined") {
|
|
964
|
+
document.removeEventListener("visibilitychange", __privateGet$2(this, _visibilityChangeHandler));
|
|
965
|
+
__privateSet$2(this, _visibilityChangeHandler, null);
|
|
966
|
+
}
|
|
967
|
+
this.cancelProfile();
|
|
968
|
+
}
|
|
935
969
|
startProfile(name) {
|
|
936
970
|
if (__privateGet$2(this, _profileInProgress)) {
|
|
937
971
|
this.addCrumb(name);
|
|
@@ -964,6 +998,17 @@ class SceneRenderProfiler {
|
|
|
964
998
|
writeSceneLog("SceneRenderProfiler", "Cancelled recording frames, new profile started");
|
|
965
999
|
}
|
|
966
1000
|
}
|
|
1001
|
+
// cancel profile
|
|
1002
|
+
cancelProfile() {
|
|
1003
|
+
if (__privateGet$2(this, _profileInProgress)) {
|
|
1004
|
+
writeSceneLog("SceneRenderProfiler", "Cancelling profile", __privateGet$2(this, _profileInProgress));
|
|
1005
|
+
__privateSet$2(this, _profileInProgress, null);
|
|
1006
|
+
if (__privateGet$2(this, _trailAnimationFrameId)) {
|
|
1007
|
+
cancelAnimationFrame(__privateGet$2(this, _trailAnimationFrameId));
|
|
1008
|
+
__privateSet$2(this, _trailAnimationFrameId, null);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
967
1012
|
addCrumb(crumb) {
|
|
968
1013
|
if (__privateGet$2(this, _profileInProgress)) {
|
|
969
1014
|
writeSceneLog("SceneRenderProfiler", "Adding crumb:", crumb);
|
|
@@ -975,6 +1020,7 @@ _profileInProgress = new WeakMap();
|
|
|
975
1020
|
_profileStartTs = new WeakMap();
|
|
976
1021
|
_trailAnimationFrameId = new WeakMap();
|
|
977
1022
|
_recordedTrailingSpans = new WeakMap();
|
|
1023
|
+
_visibilityChangeHandler = new WeakMap();
|
|
978
1024
|
function processRecordedSpans(spans) {
|
|
979
1025
|
for (let i = spans.length - 1; i >= 0; i--) {
|
|
980
1026
|
if (spans[i] > SPAN_THRESHOLD) {
|
|
@@ -5631,10 +5677,6 @@ function isEqualityOrMultiOperator(value) {
|
|
|
5631
5677
|
const operators = /* @__PURE__ */ new Set(["equals", "not-equals", "one-of", "not-one-of"]);
|
|
5632
5678
|
return operators.has(value);
|
|
5633
5679
|
}
|
|
5634
|
-
function isRegexOperator(value) {
|
|
5635
|
-
const operators = /* @__PURE__ */ new Set(["regex-match", "regex-not-match"]);
|
|
5636
|
-
return operators.has(value);
|
|
5637
|
-
}
|
|
5638
5680
|
function getAdHocFiltersFromScopes(scopes) {
|
|
5639
5681
|
const formattedFilters = /* @__PURE__ */ new Map();
|
|
5640
5682
|
const duplicatedFilters = [];
|
|
@@ -5650,11 +5692,8 @@ function processFilter(formattedFilters, duplicatedFilters, filter) {
|
|
|
5650
5692
|
return;
|
|
5651
5693
|
}
|
|
5652
5694
|
const existingFilter = formattedFilters.get(filter.key);
|
|
5653
|
-
if (existingFilter &&
|
|
5695
|
+
if (existingFilter && canValueBeMerged(existingFilter.operator, filter.operator)) {
|
|
5654
5696
|
mergeFilterValues(existingFilter, filter);
|
|
5655
|
-
} else if (existingFilter && isRegexValue(existingFilter.operator, filter.operator)) {
|
|
5656
|
-
existingFilter.value += `|${filter.value}`;
|
|
5657
|
-
existingFilter.values = [existingFilter.value];
|
|
5658
5697
|
} else if (!existingFilter) {
|
|
5659
5698
|
formattedFilters.set(filter.key, {
|
|
5660
5699
|
key: filter.key,
|
|
@@ -5690,21 +5729,11 @@ function mergeFilterValues(adHocFilter, filter) {
|
|
|
5690
5729
|
adHocFilter.operator = reverseScopeFilterOperatorMap["not-one-of"];
|
|
5691
5730
|
}
|
|
5692
5731
|
}
|
|
5693
|
-
function
|
|
5694
|
-
const scopeConvertedOperator = data.scopeFilterOperatorMap[adHocFilterOperator];
|
|
5695
|
-
if (!isRegexOperator(scopeConvertedOperator) || !isRegexOperator(filterOperator)) {
|
|
5696
|
-
return false;
|
|
5697
|
-
}
|
|
5698
|
-
return hasSameOperators(scopeConvertedOperator, filterOperator);
|
|
5699
|
-
}
|
|
5700
|
-
function isEqualityValue(adHocFilterOperator, filterOperator) {
|
|
5732
|
+
function canValueBeMerged(adHocFilterOperator, filterOperator) {
|
|
5701
5733
|
const scopeConvertedOperator = data.scopeFilterOperatorMap[adHocFilterOperator];
|
|
5702
5734
|
if (!isEqualityOrMultiOperator(scopeConvertedOperator) || !isEqualityOrMultiOperator(filterOperator)) {
|
|
5703
5735
|
return false;
|
|
5704
5736
|
}
|
|
5705
|
-
return hasSameOperators(scopeConvertedOperator, filterOperator);
|
|
5706
|
-
}
|
|
5707
|
-
function hasSameOperators(scopeConvertedOperator, filterOperator) {
|
|
5708
5737
|
if (scopeConvertedOperator.includes("not") && !filterOperator.includes("not") || !scopeConvertedOperator.includes("not") && filterOperator.includes("not")) {
|
|
5709
5738
|
return false;
|
|
5710
5739
|
}
|