mirror of https://github.com/grafana/grafana.git
Performance logging architecture improvements and service consolidation
- Rename ScenePerformanceService to ScenePerformanceLogger for clarity - Consolidate performance service initialization into dashboardPerformanceInitializer - Remove global singleton pattern in favor of per-dashboard lifecycle management - Add comprehensive collapsible analytics logging with detailed panel breakdowns - Remove duplicate completion logs between services - Implement proper cleanup for both ScenePerformanceLogger and DashboardAnalyticsAggregator - Update all imports and references to use new naming conventions
This commit is contained in:
parent
c13cf18cf0
commit
d6d071e7c0
|
|
@ -1,44 +1,55 @@
|
|||
import { getScenePerformanceTracker, writePerformanceLog } from '@grafana/scenes';
|
||||
|
||||
import { getDashboardAnalyticsAggregator } from '../../dashboard/services/DashboardAnalyticsAggregator';
|
||||
import { getScenePerformanceLogger } from '../../dashboard/services/ScenePerformanceLogger';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
|
||||
/**
|
||||
* Scene behavior function that manages the initialization and lifecycle of
|
||||
* DashboardAnalyticsAggregator for each dashboard session.
|
||||
* dashboard performance services for each dashboard session.
|
||||
*
|
||||
* Initializes the aggregator with dashboard metadata and registers it as a
|
||||
* performance observer. Returns a cleanup function for deactivation.
|
||||
* Initializes both the analytics aggregator and performance logger, registering
|
||||
* them as performance observers. Returns a cleanup function for deactivation.
|
||||
*/
|
||||
export function dashboardAnalyticsInitializer(dashboard: DashboardScene) {
|
||||
export function dashboardPerformanceInitializer(dashboard: DashboardScene) {
|
||||
const { uid, title } = dashboard.state;
|
||||
|
||||
if (!uid) {
|
||||
console.warn('dashboardAnalyticsInitializer: Dashboard UID is missing');
|
||||
console.warn('dashboardPerformanceInitializer: Dashboard UID is missing');
|
||||
return;
|
||||
}
|
||||
|
||||
// writePerformanceLog('DashboardAnalyticsInitializer', 'Initializing dashboard analytics behavior');
|
||||
writePerformanceLog('DAI', 'Initializing dashboard performance services');
|
||||
|
||||
// Initialize analytics aggregator
|
||||
const aggregator = getDashboardAnalyticsAggregator();
|
||||
aggregator.initialize(uid, title || 'Untitled Dashboard');
|
||||
|
||||
// Register as performance observer
|
||||
const tracker = getScenePerformanceTracker();
|
||||
const unsubscribe = tracker.addObserver(aggregator);
|
||||
// Initialize performance logger
|
||||
const logger = getScenePerformanceLogger();
|
||||
logger.initialize();
|
||||
|
||||
writePerformanceLog('DashboardAnalyticsInitializer', 'DashboardAnalyticsAggregator initialized:', { uid, title });
|
||||
// Register both as performance observers
|
||||
const tracker = getScenePerformanceTracker();
|
||||
const unsubscribeAggregator = tracker.addObserver(aggregator);
|
||||
const unsubscribeLogger = tracker.addObserver(logger);
|
||||
|
||||
writePerformanceLog('DAI', 'Dashboard performance services initialized:', { uid, title });
|
||||
|
||||
// Return cleanup function
|
||||
return () => {
|
||||
// Unsubscribe from performance tracker
|
||||
if (unsubscribe) {
|
||||
unsubscribe();
|
||||
if (unsubscribeAggregator) {
|
||||
unsubscribeAggregator();
|
||||
}
|
||||
if (unsubscribeLogger) {
|
||||
unsubscribeLogger();
|
||||
}
|
||||
|
||||
// Clean up aggregator state
|
||||
// Clean up service states
|
||||
aggregator.destroy();
|
||||
logger.destroy();
|
||||
|
||||
writePerformanceLog('DashboardAnalyticsInitializer', 'DashboardAnalyticsAggregator cleaned up');
|
||||
writePerformanceLog('DAI', 'Dashboard performance services cleaned up');
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ import {
|
|||
import { DashboardMeta } from 'app/types/dashboard';
|
||||
|
||||
import { addPanelsOnLoadBehavior } from '../addToDashboard/addPanelsOnLoadBehavior';
|
||||
import { dashboardAnalyticsInitializer } from '../behaviors/DashboardAnalyticsInitializerBehavior';
|
||||
import { dashboardPerformanceInitializer } from '../behaviors/DashboardAnalyticsInitializerBehavior';
|
||||
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
||||
import { DashboardControls } from '../scene/DashboardControls';
|
||||
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
|
||||
|
|
@ -228,7 +228,7 @@ export function transformSaveModelSchemaV2ToScene(dto: DashboardWithAccessInfo<D
|
|||
uid: dashboardId?.toString(),
|
||||
}),
|
||||
// Analytics aggregator lifecycle management (initialization, observer registration, cleanup)
|
||||
dashboardAnalyticsInitializer,
|
||||
dashboardPerformanceInitializer,
|
||||
// Panel profiling is now handled by composed SceneRenderProfiler
|
||||
],
|
||||
$data: new DashboardDataLayerSet({
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
|||
import { DashboardDTO, DashboardDataDTO } from 'app/types/dashboard';
|
||||
|
||||
import { addPanelsOnLoadBehavior } from '../addToDashboard/addPanelsOnLoadBehavior';
|
||||
import { dashboardAnalyticsInitializer } from '../behaviors/DashboardAnalyticsInitializerBehavior';
|
||||
import { dashboardPerformanceInitializer } from '../behaviors/DashboardAnalyticsInitializerBehavior';
|
||||
import { AlertStatesDataLayer } from '../scene/AlertStatesDataLayer';
|
||||
import { CustomTimeRangeCompare } from '../scene/CustomTimeRangeCompare';
|
||||
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
||||
|
|
@ -331,7 +331,7 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel,
|
|||
uid,
|
||||
}),
|
||||
// Analytics aggregator lifecycle management (initialization, observer registration, cleanup)
|
||||
dashboardAnalyticsInitializer,
|
||||
dashboardPerformanceInitializer,
|
||||
];
|
||||
|
||||
// Panel profiling is now handled by composed SceneRenderProfiler
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import {
|
|||
type DashboardInteractionCompleteData,
|
||||
type PanelPerformanceData,
|
||||
type QueryPerformanceData,
|
||||
writePerformanceLog,
|
||||
} from '@grafana/scenes';
|
||||
|
||||
/**
|
||||
|
|
@ -120,8 +119,7 @@ export class DashboardAnalyticsAggregator implements ScenePerformanceObserver {
|
|||
}
|
||||
|
||||
onPanelOperationComplete(data: PanelPerformanceData): void {
|
||||
writePerformanceLog('DashboardAnalyticsAggregator', '🔍 onPanelOperationComplete called with:', data);
|
||||
|
||||
// Aggregate panel metrics without verbose logging (handled by ScenePerformanceLogger)
|
||||
const panel = this.panelMetrics.get(data.panelKey);
|
||||
if (!panel) {
|
||||
console.warn('Panel not found for operation completion:', data.panelKey);
|
||||
|
|
@ -176,27 +174,14 @@ export class DashboardAnalyticsAggregator implements ScenePerformanceObserver {
|
|||
onQueryStart(data: QueryPerformanceData): void {
|
||||
// Non-panel queries (annotations, variables, plugins, datasources) don't need aggregation
|
||||
// These are infrastructure queries that don't belong to specific panels
|
||||
writePerformanceLog('DashboardAnalyticsAggregator', '📊 Non-Panel Query Started:', {
|
||||
queryId: data.queryId,
|
||||
queryType: data.queryType,
|
||||
querySource: data.querySource,
|
||||
origin: data.origin,
|
||||
});
|
||||
// Logging handled by ScenePerformanceLogger to avoid duplication
|
||||
}
|
||||
|
||||
onQueryComplete(data: QueryPerformanceData): void {
|
||||
// Non-panel queries (annotations, variables, plugins, datasources) don't need panel aggregation
|
||||
// These are infrastructure queries that don't belong to specific panels
|
||||
writePerformanceLog('DashboardAnalyticsAggregator', '📊 Non-Panel Query Complete:', {
|
||||
queryId: data.queryId,
|
||||
queryType: data.queryType,
|
||||
querySource: data.querySource,
|
||||
origin: data.origin,
|
||||
duration: data.duration,
|
||||
});
|
||||
|
||||
// Logging handled by ScenePerformanceLogger to avoid duplication
|
||||
// Could track infrastructure query metrics separately in the future if needed
|
||||
// For now, just log for observability
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -252,7 +237,7 @@ export class DashboardAnalyticsAggregator implements ScenePerformanceObserver {
|
|||
// S4.0/S5.0: Log complete analytics event including panel metrics
|
||||
this.logDashboardAnalyticsEvent(data, payload, panelMetrics);
|
||||
|
||||
writePerformanceLog('DashboardAnalyticsAggregator', 'Analytics payload:', payload);
|
||||
// Analytics payload logged separately if needed for debugging
|
||||
|
||||
// Send the same analytics as before
|
||||
reportInteraction('dashboard_render', {
|
||||
|
|
@ -276,67 +261,125 @@ export class DashboardAnalyticsAggregator implements ScenePerformanceObserver {
|
|||
payload: Record<string, unknown>,
|
||||
panelMetrics: PanelAnalyticsMetrics[] | null
|
||||
): void {
|
||||
// Calculate performance insights if panel metrics are available
|
||||
let performanceInsights = null;
|
||||
if (panelMetrics && panelMetrics.length > 0) {
|
||||
const totalPanelTime = panelMetrics.reduce((sum: number, panel) => {
|
||||
const panelTotal =
|
||||
panel.totalQueryTime +
|
||||
panel.totalFieldConfigTime +
|
||||
panel.totalTransformationTime +
|
||||
panel.totalRenderTime +
|
||||
panel.pluginLoadTime;
|
||||
return sum + panelTotal;
|
||||
}, 0);
|
||||
const panelCount = panelMetrics?.length || 0;
|
||||
const panelSummary = panelCount ? `${panelCount} panels analyzed` : 'No panel metrics';
|
||||
|
||||
const avgPanelTime = totalPanelTime / panelMetrics.length;
|
||||
// Main analytics summary
|
||||
const slowPanelCount =
|
||||
panelMetrics?.filter(
|
||||
(p) =>
|
||||
p.totalQueryTime + p.totalTransformationTime + p.totalRenderTime + p.totalFieldConfigTime + p.pluginLoadTime >
|
||||
100
|
||||
).length || 0;
|
||||
|
||||
const slowestPanel = panelMetrics.reduce((slowest, panel) => {
|
||||
const panelTotal =
|
||||
panel.totalQueryTime +
|
||||
panel.totalFieldConfigTime +
|
||||
panel.totalTransformationTime +
|
||||
panel.totalRenderTime +
|
||||
panel.pluginLoadTime;
|
||||
const slowestTotal =
|
||||
slowest.totalQueryTime +
|
||||
slowest.totalFieldConfigTime +
|
||||
slowest.totalTransformationTime +
|
||||
slowest.totalRenderTime +
|
||||
slowest.pluginLoadTime;
|
||||
// eslint-disable-next-line no-console
|
||||
console.groupCollapsed(
|
||||
`DAA: [ANALYTICS] ${data.interactionType} | ${panelSummary}${slowPanelCount > 0 ? ` | ${slowPanelCount} slow panels ⚠️` : ''}`
|
||||
);
|
||||
|
||||
return panelTotal > slowestTotal ? panel : slowest;
|
||||
// Dashboard overview
|
||||
console.log('📊 Dashboard:', {
|
||||
duration: `${(data.duration || 0).toFixed(1)}ms`,
|
||||
network: `${(data.networkDuration || 0).toFixed(1)}ms`,
|
||||
interactionType: data.interactionType,
|
||||
slowPanels: slowPanelCount,
|
||||
});
|
||||
|
||||
const slowestPanelTime =
|
||||
slowestPanel.totalQueryTime +
|
||||
slowestPanel.totalFieldConfigTime +
|
||||
slowestPanel.totalTransformationTime +
|
||||
slowestPanel.totalRenderTime +
|
||||
slowestPanel.pluginLoadTime;
|
||||
// Analytics payload
|
||||
console.log('📈 Analytics payload:', payload);
|
||||
|
||||
performanceInsights = {
|
||||
totalPanelTime: `${totalPanelTime.toFixed(2)}ms`,
|
||||
averagePanelTime: `${avgPanelTime.toFixed(2)}ms`,
|
||||
slowestPanel: {
|
||||
panelId: slowestPanel.panelId,
|
||||
pluginId: slowestPanel.pluginId,
|
||||
time: `${slowestPanelTime.toFixed(2)}ms`,
|
||||
// Individual collapsible panel logs with detailed breakdown
|
||||
if (panelMetrics && panelMetrics.length > 0) {
|
||||
panelMetrics.forEach((panel) => {
|
||||
const totalPanelTime =
|
||||
panel.totalQueryTime +
|
||||
panel.totalTransformationTime +
|
||||
panel.totalRenderTime +
|
||||
panel.totalFieldConfigTime +
|
||||
panel.pluginLoadTime;
|
||||
|
||||
const isSlowPanel = totalPanelTime > 100;
|
||||
const slowWarning = isSlowPanel ? ' ⚠️ SLOW' : '';
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.groupCollapsed(
|
||||
`🎨 Panel ${panel.pluginId}-${panel.panelId}: ${totalPanelTime.toFixed(1)}ms total${slowWarning}`
|
||||
);
|
||||
|
||||
console.log('🔧 Plugin:', {
|
||||
id: panel.pluginId,
|
||||
version: panel.pluginVersion || 'unknown',
|
||||
panelId: panel.panelId,
|
||||
panelKey: panel.panelKey,
|
||||
});
|
||||
|
||||
console.log('⚡ Performance:', {
|
||||
totalTime: `${totalPanelTime.toFixed(1)}ms`,
|
||||
isSlowPanel: isSlowPanel,
|
||||
breakdown: {
|
||||
query: `${panel.totalQueryTime.toFixed(1)}ms`,
|
||||
transform: `${panel.totalTransformationTime.toFixed(1)}ms`,
|
||||
render: `${panel.totalRenderTime.toFixed(1)}ms`,
|
||||
fieldConfig: `${panel.totalFieldConfigTime.toFixed(1)}ms`,
|
||||
pluginLoad: `${panel.pluginLoadTime.toFixed(1)}ms`,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
if (panel.queryOperations.length > 0) {
|
||||
console.log('📊 Queries:', {
|
||||
count: panel.queryOperations.length,
|
||||
details: panel.queryOperations.map((op, index) => ({
|
||||
operation: index + 1,
|
||||
duration: `${op.duration.toFixed(1)}ms`,
|
||||
timestamp: op.timestamp,
|
||||
queryType: op.queryType || 'unknown',
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
writePerformanceLog('DashboardAnalyticsAggregator', '🎯 Dashboard Analytics Event:', {
|
||||
uid: this.dashboardUID,
|
||||
title: this.dashboardTitle,
|
||||
interactionType: data.interactionType,
|
||||
dashboardMetrics: payload,
|
||||
panelMetricsMapSize: this.panelMetrics.size,
|
||||
panelMetricsArrayLength: panelMetrics?.length || 0,
|
||||
panelMetrics: (panelMetrics?.length ?? 0) > 0 ? panelMetrics : 'No panel metrics found',
|
||||
performanceInsights: performanceInsights || 'No performance insights available',
|
||||
if (panel.transformationOperations.length > 0) {
|
||||
console.log('🔄 Transformations:', {
|
||||
count: panel.transformationOperations.length,
|
||||
details: panel.transformationOperations.map((op, index) => ({
|
||||
operation: index + 1,
|
||||
duration: `${op.duration.toFixed(1)}ms`,
|
||||
timestamp: op.timestamp,
|
||||
transformationId: op.transformationId || 'unknown',
|
||||
success: op.success !== false,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
if (panel.renderOperations.length > 0) {
|
||||
console.log('🎨 Renders:', {
|
||||
count: panel.renderOperations.length,
|
||||
details: panel.renderOperations.map((op, index) => ({
|
||||
operation: index + 1,
|
||||
duration: `${op.duration.toFixed(1)}ms`,
|
||||
timestamp: op.timestamp,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
if (panel.fieldConfigOperations.length > 0) {
|
||||
console.log('⚙️ FieldConfigs:', {
|
||||
count: panel.fieldConfigOperations.length,
|
||||
details: panel.fieldConfigOperations.map((op, index) => ({
|
||||
operation: index + 1,
|
||||
duration: `${op.duration.toFixed(1)}ms`,
|
||||
timestamp: op.timestamp,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.groupEnd();
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.groupEnd();
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton instance
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { logMeasurement, reportInteraction, config } from '@grafana/runtime';
|
||||
import { SceneRenderProfiler, type SceneObject } from '@grafana/scenes';
|
||||
|
||||
import { initializeScenePerformanceService } from './ScenePerformanceService';
|
||||
import { initializeScenePerformanceLogger } from './ScenePerformanceLogger';
|
||||
|
||||
interface SceneInteractionProfileEvent {
|
||||
origin: string;
|
||||
|
|
@ -26,9 +26,6 @@ export function getDashboardSceneProfiler() {
|
|||
};
|
||||
|
||||
dashboardSceneProfiler = new SceneRenderProfiler(panelProfilingConfig);
|
||||
|
||||
// Initialize the Scene performance service to start listening to events
|
||||
initializeScenePerformanceService();
|
||||
}
|
||||
return dashboardSceneProfiler;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ import {
|
|||
} from './performanceConstants';
|
||||
|
||||
/**
|
||||
* Grafana service that subscribes to Scene performance events
|
||||
* and integrates them with Grafana's observability systems.
|
||||
* Also creates Chrome DevTools performance marks and measurements for debugging.
|
||||
* Grafana logger that subscribes to Scene performance events
|
||||
* and logs them to console with Chrome DevTools performance marks and measurements for debugging.
|
||||
*/
|
||||
export class ScenePerformanceService implements ScenePerformanceObserver {
|
||||
export class ScenePerformanceLogger implements ScenePerformanceObserver {
|
||||
private isInitialized = false;
|
||||
private unsubscribe: (() => void) | null = null;
|
||||
private panelGroupsOpen = new Set<string>(); // Track which panels we've seen
|
||||
|
||||
constructor() {
|
||||
// Bind all observer methods to preserve 'this' context when called by ScenePerformanceTracker
|
||||
|
|
@ -48,7 +48,7 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
// Note: Analytics aggregator will be initialized separately with dashboard context
|
||||
|
||||
this.isInitialized = true;
|
||||
writePerformanceLog('ScenePerformanceService', 'Initialized and subscribed to Scene performance events');
|
||||
writePerformanceLog('SPL', 'Initialized and subscribed to Scene performance events');
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
|
@ -63,7 +63,7 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
}
|
||||
|
||||
this.isInitialized = false;
|
||||
writePerformanceLog('ScenePerformanceService', 'Destroyed and unsubscribed from Scene performance events');
|
||||
writePerformanceLog('SPL', 'Destroyed and unsubscribed from Scene performance events');
|
||||
}
|
||||
|
||||
// Dashboard-level events
|
||||
|
|
@ -72,14 +72,10 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
const dashboardStartMark = PERFORMANCE_MARKS.DASHBOARD_INTERACTION_START(data.operationId);
|
||||
createPerformanceMark(dashboardStartMark, data.timestamp);
|
||||
|
||||
writePerformanceLog('ScenePerformanceService', '🎯 Dashboard Interaction Started:', {
|
||||
type: data.interactionType,
|
||||
uid: data.metadata?.dashboardUID,
|
||||
title: data.metadata?.dashboardTitle,
|
||||
panelCount: data.metadata?.panelCount,
|
||||
timestamp: data.timestamp,
|
||||
operationId: data.operationId,
|
||||
});
|
||||
const title = data.metadata?.dashboardTitle || 'Unknown Dashboard';
|
||||
const panelCount = data.metadata?.panelCount || 0;
|
||||
|
||||
writePerformanceLog('SPL', `[DASHBOARD] ${data.interactionType} started: ${title} (${panelCount} panels)`);
|
||||
}
|
||||
|
||||
onDashboardInteractionMilestone(data: DashboardInteractionMilestoneData): void {
|
||||
|
|
@ -88,13 +84,8 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
const dashboardMilestoneMark = PERFORMANCE_MARKS.DASHBOARD_MILESTONE(data.operationId, milestone);
|
||||
createPerformanceMark(dashboardMilestoneMark, data.timestamp);
|
||||
|
||||
writePerformanceLog('ScenePerformanceService', '🔄 Dashboard Milestone:', {
|
||||
type: data.interactionType,
|
||||
uid: data.metadata?.dashboardUID,
|
||||
milestone: data.milestone,
|
||||
timestamp: data.timestamp,
|
||||
operationId: data.operationId,
|
||||
});
|
||||
// Log milestones quietly - only when verbose debugging is needed
|
||||
// Most milestones are covered by the start/complete query logs
|
||||
}
|
||||
|
||||
onDashboardInteractionComplete(data: DashboardInteractionCompleteData): void {
|
||||
|
|
@ -106,15 +97,11 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
createPerformanceMark(dashboardEndMark, data.timestamp);
|
||||
createPerformanceMeasure(dashboardMeasureName, dashboardStartMark, dashboardEndMark);
|
||||
|
||||
writePerformanceLog('ScenePerformanceService', '✅ Dashboard Interaction Complete:', {
|
||||
type: data.interactionType,
|
||||
uid: data.metadata?.dashboardUID,
|
||||
title: data.metadata?.dashboardTitle,
|
||||
duration: data.duration,
|
||||
networkDuration: data.networkDuration,
|
||||
timestamp: data.timestamp,
|
||||
operationId: data.operationId,
|
||||
});
|
||||
// Clear tracking state
|
||||
this.panelGroupsOpen.clear();
|
||||
|
||||
// Dashboard completion logging is handled comprehensively by SceneRenderProfiler
|
||||
// This observer focuses on creating DevTools performance marks/measures
|
||||
}
|
||||
|
||||
// Panel-level events
|
||||
|
|
@ -122,16 +109,10 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
// Create standardized performance marks based on operation type
|
||||
this.createStandardizedPanelMark(data, 'start');
|
||||
|
||||
const operationIcon = this.getOperationIcon(data.operation);
|
||||
writePerformanceLog('ScenePerformanceService', `${operationIcon} Panel Operation Started [${data.operation}]:`, {
|
||||
panelId: data.panelId,
|
||||
panelKey: data.panelKey,
|
||||
pluginId: data.pluginId,
|
||||
operation: data.operation,
|
||||
timestamp: data.timestamp,
|
||||
metadata: data.metadata,
|
||||
operationId: data.operationId,
|
||||
});
|
||||
// Track panel for summary logging later
|
||||
this.panelGroupsOpen.add(data.panelKey);
|
||||
|
||||
// Don't log start events - they're noise. Only log completions with timing.
|
||||
}
|
||||
|
||||
onPanelOperationComplete(data: PanelPerformanceData): void {
|
||||
|
|
@ -139,17 +120,19 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
this.createStandardizedPanelMark(data, 'end');
|
||||
this.createStandardizedPanelMeasure(data);
|
||||
|
||||
const operationIcon = this.getOperationIcon(data.operation);
|
||||
writePerformanceLog('ScenePerformanceService', `${operationIcon} Panel Operation Complete [${data.operation}]:`, {
|
||||
panelId: data.panelId,
|
||||
panelKey: data.panelKey,
|
||||
pluginId: data.pluginId,
|
||||
operation: data.operation,
|
||||
duration: data.duration,
|
||||
timestamp: data.timestamp,
|
||||
metadata: data.metadata,
|
||||
operationId: data.operationId,
|
||||
});
|
||||
const duration = (data.duration || 0).toFixed(1);
|
||||
const slowWarning = (data.duration || 0) > 100 ? ' ⚠️ SLOW' : '';
|
||||
|
||||
// For query operations, include the queryId for correlation
|
||||
let operationDisplay: string = data.operation;
|
||||
if (data.operation === 'query') {
|
||||
operationDisplay = `${data.operation} [${data.metadata.queryId}]`;
|
||||
}
|
||||
|
||||
writePerformanceLog(
|
||||
'SPL',
|
||||
`[PANEL] ${data.pluginId}-${data.panelId} ${operationDisplay}: ${duration}ms${slowWarning}`
|
||||
);
|
||||
}
|
||||
|
||||
// Query-level events
|
||||
|
|
@ -158,14 +141,9 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
const queryStartMark = PERFORMANCE_MARKS.QUERY_START(data.origin, data.queryId);
|
||||
createPerformanceMark(queryStartMark, data.timestamp);
|
||||
|
||||
writePerformanceLog('ScenePerformanceService', '📊 Non-Panel Query Started:', {
|
||||
queryId: data.queryId,
|
||||
queryType: data.queryType,
|
||||
querySource: data.querySource,
|
||||
origin: data.origin,
|
||||
timestamp: data.timestamp,
|
||||
operationId: data.operationId,
|
||||
});
|
||||
// Mark that we're processing infrastructure queries
|
||||
|
||||
// Don't log start events - they're noise. Only log completions with timing.
|
||||
}
|
||||
|
||||
onQueryComplete(data: QueryPerformanceData): void {
|
||||
|
|
@ -177,15 +155,12 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
createPerformanceMark(queryEndMark, data.timestamp);
|
||||
createPerformanceMeasure(queryMeasureName, queryStartMark, queryEndMark);
|
||||
|
||||
writePerformanceLog('ScenePerformanceService', '📊 Non-Panel Query Complete:', {
|
||||
queryId: data.queryId,
|
||||
queryType: data.queryType,
|
||||
querySource: data.querySource,
|
||||
origin: data.origin,
|
||||
duration: data.duration,
|
||||
timestamp: data.timestamp,
|
||||
operationId: data.operationId,
|
||||
});
|
||||
const duration = (data.duration || 0).toFixed(1);
|
||||
const slowWarning = (data.duration || 0) > 100 ? ' ⚠️ SLOW' : '';
|
||||
|
||||
// Simple, clean format
|
||||
const queryType = data.queryType.replace(/^(getDataSource\/|AnnotationsDataLayer\/)/, ''); // Remove prefixes
|
||||
writePerformanceLog('SPL', `[QUERY ${data.origin}] ${queryType} [${data.queryId}]: ${duration}ms${slowWarning}`);
|
||||
}
|
||||
|
||||
// Standardized performance mark creation methods - now with full type safety!
|
||||
|
|
@ -302,44 +277,26 @@ export class ScenePerformanceService implements ScenePerformanceObserver {
|
|||
}
|
||||
}
|
||||
|
||||
// Helper method to get appropriate icon for operation type
|
||||
private getOperationIcon(operation: string): string {
|
||||
switch (operation) {
|
||||
case 'query':
|
||||
return '🔍';
|
||||
case 'transform':
|
||||
return '🔄';
|
||||
case 'fieldConfig':
|
||||
return '🔧';
|
||||
case 'render':
|
||||
return '🎨';
|
||||
case 'plugin-load':
|
||||
return '⚡';
|
||||
default:
|
||||
return '⚡';
|
||||
}
|
||||
}
|
||||
|
||||
// All performance marks now use standardized functions from performanceConstants.ts
|
||||
}
|
||||
|
||||
// Singleton instance
|
||||
let scenePerformanceService: ScenePerformanceService | null = null;
|
||||
let scenePerformanceLogger: ScenePerformanceLogger | null = null;
|
||||
|
||||
export function getScenePerformanceService(): ScenePerformanceService {
|
||||
if (!scenePerformanceService) {
|
||||
scenePerformanceService = new ScenePerformanceService();
|
||||
export function getScenePerformanceLogger(): ScenePerformanceLogger {
|
||||
if (!scenePerformanceLogger) {
|
||||
scenePerformanceLogger = new ScenePerformanceLogger();
|
||||
}
|
||||
return scenePerformanceService;
|
||||
return scenePerformanceLogger;
|
||||
}
|
||||
|
||||
export function initializeScenePerformanceService(): void {
|
||||
getScenePerformanceService().initialize();
|
||||
export function initializeScenePerformanceLogger(): void {
|
||||
getScenePerformanceLogger().initialize();
|
||||
}
|
||||
|
||||
export function destroyScenePerformanceService(): void {
|
||||
if (scenePerformanceService) {
|
||||
scenePerformanceService.destroy();
|
||||
scenePerformanceService = null;
|
||||
export function destroyScenePerformanceLogger(): void {
|
||||
if (scenePerformanceLogger) {
|
||||
scenePerformanceLogger.destroy();
|
||||
scenePerformanceLogger = null;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue