/* js/dataProcessor.js * Verantwortlich für Transformierung der eBPF Analyse-Rohdaten * in darstellungsfähige Strukturen (Diagramme & Tabellen) */ /** * Verknüpft write_pre und write_post Events anhand derselben corr_id. * @param {Array<{corr_id: string, type: string, timestamp: number, details: object}>} rawData * @returns {Array<{corr_id: string, pre: object|null, post: object|null, duration: number|null}>} */ export function aggregatePrePostPairs(rawData) { if (!Array.isArray(rawData)) return []; const grouped = new Map(); for (const event of rawData) { if (!event?.corr_id || !event?.type) continue; const group = grouped.get(event.corr_id) ?? { corr_id: event.corr_id, pre: null, post: null, duration: null }; if (event.type === 'write_pre') { group.pre = event; } else if (event.type === 'write_post') { group.post = event; } grouped.set(event.corr_id, group); } const pairs = []; for (const [, pair] of grouped) { if (pair.pre && pair.post) { pair.duration = pair.post.timestamp - pair.pre.timestamp; } pairs.push(pair); } return pairs; } /** * Berechnet Kennzahlen wie mittlere Dauer, Eventanzahl pro Typ. * @param {Array<{corr_id: string, pre: object|null, post: object|null, duration: number|null}>} aggregatedEvents * @returns {{totalEvents: number, counts: Record, meanDuration: number|null}} */ export function computeStats(aggregatedEvents) { if (!Array.isArray(aggregatedEvents)) return { totalEvents: 0, counts: {}, meanDuration: null }; const counts = { write_pre: 0, write_post: 0, read: 0 }; let totalDuration = 0; let validDurations = 0; let totalEvents = 0; aggregatedEvents.forEach(entry => { if (entry.pre) counts.write_pre++; if (entry.post) counts.write_post++; totalEvents++; if (typeof entry.duration === 'number' && !isNaN(entry.duration)) { totalDuration += entry.duration; validDurations++; } }); const meanDuration = validDurations > 0 ? totalDuration / validDurations : null; return { totalEvents, counts, meanDuration }; }