feat: implement collapsible tree view with inclusive resource metrics and improved memory calculation
This commit is contained in:
182
src/App.tsx
182
src/App.tsx
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, useMemo } from 'react';
|
import { useState, useEffect, useMemo, Fragment } from 'react';
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import {
|
import {
|
||||||
AreaChart, Area, XAxis, YAxis, Tooltip, ResponsiveContainer,
|
AreaChart, Area, XAxis, YAxis, Tooltip, ResponsiveContainer,
|
||||||
@@ -45,15 +45,19 @@ interface ProcessHistoryPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface AggregatedProcess {
|
interface AggregatedProcess {
|
||||||
|
pid: number;
|
||||||
name: string;
|
name: string;
|
||||||
avg_cpu: number;
|
avg_cpu: number;
|
||||||
peak_cpu: number;
|
peak_cpu: number;
|
||||||
avg_memory_mb: number;
|
avg_memory_mb: number;
|
||||||
peak_memory_mb: number;
|
peak_memory_mb: number;
|
||||||
|
inclusive_avg_cpu: number;
|
||||||
|
inclusive_avg_memory_mb: number;
|
||||||
instance_count: number;
|
instance_count: number;
|
||||||
warnings: string[];
|
warnings: string[];
|
||||||
history: ProcessHistoryPoint[];
|
history: ProcessHistoryPoint[];
|
||||||
is_syspulse: boolean;
|
is_syspulse: boolean;
|
||||||
|
children: AggregatedProcess[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProfilingReport {
|
interface ProfilingReport {
|
||||||
@@ -148,7 +152,7 @@ function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stats) return <div className="h-screen w-screen flex items-center justify-center text-text bg-base font-black italic tracking-tighter uppercase text-2xl">Initializing SysPulse...</div>;
|
if (!stats) return <div className="h-screen w-screen flex items-center justify-center text-text bg-base font-black italic tracking-tighter uppercase text-2xl animate-pulse">Initializing SysPulse...</div>;
|
||||||
|
|
||||||
const avgCpu = stats.cpu_usage.reduce((a, b) => a + b, 0) / stats.cpu_usage.length;
|
const avgCpu = stats.cpu_usage.reduce((a, b) => a + b, 0) / stats.cpu_usage.length;
|
||||||
const memoryPercent = (stats.used_memory / stats.total_memory) * 100;
|
const memoryPercent = (stats.used_memory / stats.total_memory) * 100;
|
||||||
@@ -261,7 +265,7 @@ function App() {
|
|||||||
<span className="text-subtext0 font-black mb-2">Processes</span>
|
<span className="text-subtext0 font-black mb-2">Processes</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 text-xs text-subtext1 font-medium leading-relaxed bg-base/30 p-3 rounded-xl border border-surface1">
|
<div className="mt-4 text-xs text-subtext1 font-medium leading-relaxed bg-base/30 p-3 rounded-xl border border-surface1">
|
||||||
Automatic aggregation is active. Child processes are merged for cleaner profiling.
|
Live system feed. Profiling session will provide a full hierarchical tree.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -296,7 +300,7 @@ function App() {
|
|||||||
)} />
|
)} />
|
||||||
{proc.name}
|
{proc.name}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-mono text-overlay2 text-xs text-right self-center">{proc.pid}</div>
|
<div className="font-mono text-overlay2 text-xs text-right self-center tabular-nums">{proc.pid}</div>
|
||||||
<div className="text-blue font-black text-sm text-right self-center tabular-nums">{proc.cpu_usage.toFixed(1)}%</div>
|
<div className="text-blue font-black text-sm text-right self-center tabular-nums">{proc.cpu_usage.toFixed(1)}%</div>
|
||||||
<div className="text-mauve font-black text-sm text-right self-center tabular-nums">{(proc.memory / 1024 / 1024).toFixed(0)} MB</div>
|
<div className="text-mauve font-black text-sm text-right self-center tabular-nums">{(proc.memory / 1024 / 1024).toFixed(0)} MB</div>
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center">
|
||||||
@@ -319,13 +323,21 @@ function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type SortField = 'name' | 'avg_cpu' | 'peak_cpu' | 'avg_memory_mb' | 'peak_memory_mb' | 'instance_count';
|
type SortField = 'name' | 'pid' | 'inclusive_avg_cpu' | 'peak_cpu' | 'inclusive_avg_memory_mb' | 'peak_memory_mb';
|
||||||
|
|
||||||
function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () => void }) {
|
function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () => void }) {
|
||||||
const [sortField, setSortField] = useState<SortField>('avg_cpu');
|
const [sortField, setSortField] = useState<SortField>('inclusive_avg_cpu');
|
||||||
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
|
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
|
||||||
const [selectedProcess, setSelectedProcess] = useState<AggregatedProcess | null>(null);
|
const [selectedProcess, setSelectedProcess] = useState<AggregatedProcess | null>(null);
|
||||||
const [hideProfiler, setHideProfiler] = useState(true);
|
const [hideProfiler, setHideProfiler] = useState(true);
|
||||||
|
const [expandedNodes, setExpandedNodes] = useState<Set<number>>(new Set());
|
||||||
|
|
||||||
|
const toggleExpand = (pid: number) => {
|
||||||
|
const newExpanded = new Set(expandedNodes);
|
||||||
|
if (newExpanded.has(pid)) newExpanded.delete(pid);
|
||||||
|
else newExpanded.add(pid);
|
||||||
|
setExpandedNodes(newExpanded);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSort = (field: SortField) => {
|
const handleSort = (field: SortField) => {
|
||||||
if (sortField === field) {
|
if (sortField === field) {
|
||||||
@@ -363,6 +375,73 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const renderTreeRows = (nodes: AggregatedProcess[], depth = 0): React.ReactNode => {
|
||||||
|
return nodes.map((proc) => {
|
||||||
|
const isExpanded = expandedNodes.has(proc.pid);
|
||||||
|
const hasChildren = proc.children && proc.children.length > 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment key={proc.pid}>
|
||||||
|
<div
|
||||||
|
className="grid grid-cols-[1fr_80px_100px_100px_100px_100px_200px] gap-4 px-4 py-3 border-b border-surface1/20 hover:bg-surface1/20 cursor-pointer transition-all rounded-xl group relative"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setSelectedProcess(proc);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="font-black text-text truncate text-sm flex items-center gap-2 group-hover:text-blue transition-colors" style={{ paddingLeft: depth * 20 }}>
|
||||||
|
{hasChildren ? (
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
toggleExpand(proc.pid);
|
||||||
|
}}
|
||||||
|
className="p-1 hover:bg-surface2 rounded transition-colors"
|
||||||
|
>
|
||||||
|
<Play size={10} className={cn("transition-transform duration-200 fill-current", isExpanded ? "rotate-90" : "")} />
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<div className="w-4" />
|
||||||
|
)}
|
||||||
|
<div className={cn(
|
||||||
|
"w-2 h-2 rounded-full shrink-0",
|
||||||
|
proc.is_syspulse ? "bg-mauve" : "bg-surface2 group-hover:bg-blue"
|
||||||
|
)} />
|
||||||
|
<span title={proc.name}>{proc.name}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-overlay2 font-mono text-xs text-right self-center tabular-nums">{proc.pid}</div>
|
||||||
|
|
||||||
|
<div className="text-blue font-black text-sm text-right self-center tabular-nums">
|
||||||
|
{proc.inclusive_avg_cpu.toFixed(1)}%
|
||||||
|
{proc.children.length > 0 && <span className="block text-[9px] text-overlay1 font-normal">({proc.avg_cpu.toFixed(1)}% self)</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{proc.peak_cpu.toFixed(1)}%</div>
|
||||||
|
|
||||||
|
<div className="text-mauve font-black text-sm text-right self-center tabular-nums">
|
||||||
|
{proc.inclusive_avg_memory_mb.toFixed(0)}MB
|
||||||
|
{proc.children.length > 0 && <span className="block text-[9px] text-overlay1 font-normal">({proc.avg_memory_mb.toFixed(0)}MB self)</span>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{proc.peak_memory_mb.toFixed(0)}MB</div>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap gap-1.5 pl-4 items-center">
|
||||||
|
{proc.warnings.length > 0 ? proc.warnings.map((w, idx) => (
|
||||||
|
<span key={idx} className="bg-red/10 text-red text-[9px] font-black px-2 py-1 rounded-lg border border-red/20 flex items-center gap-1 uppercase tracking-tighter">
|
||||||
|
<AlertTriangle size={8} strokeWidth={3} /> {w}
|
||||||
|
</span>
|
||||||
|
)) : (
|
||||||
|
proc.children.length > 0 ? <span className="text-[10px] text-overlay1 font-bold uppercase tracking-widest">{proc.children.length} units</span> : null
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{hasChildren && isExpanded && renderTreeRows(proc.children, depth + 1)}
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-screen bg-base text-text">
|
<div className="flex flex-col h-screen bg-base text-text">
|
||||||
<div className="titlebar shrink-0">
|
<div className="titlebar shrink-0">
|
||||||
@@ -410,7 +489,7 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
|
|||||||
<div className="text-xl font-bold text-text tabular-nums">{new Date(report.end_time).toLocaleTimeString()}</div>
|
<div className="text-xl font-bold text-text tabular-nums">{new Date(report.end_time).toLocaleTimeString()}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center group hover:border-green/30 transition-colors">
|
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center group hover:border-green/30 transition-colors">
|
||||||
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Unique Processes</div>
|
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-1">Root Processes</div>
|
||||||
<div className="text-2xl font-black text-blue tabular-nums">{report.aggregated_processes.length}</div>
|
<div className="text-2xl font-black text-blue tabular-nums">{report.aggregated_processes.length}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center group hover:border-red/30 transition-colors">
|
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-xl text-center group hover:border-red/30 transition-colors">
|
||||||
@@ -453,50 +532,35 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
|
|||||||
<div className="card flex-1 flex flex-col min-h-0 border border-surface1/50 shadow-[0_35px_60px_-15px_rgba(0,0,0,0.5)] overflow-hidden">
|
<div className="card flex-1 flex flex-col min-h-0 border border-surface1/50 shadow-[0_35px_60px_-15px_rgba(0,0,0,0.5)] overflow-hidden">
|
||||||
<div className="flex justify-between items-center mb-6 px-2">
|
<div className="flex justify-between items-center mb-6 px-2">
|
||||||
<h3 className="text-xl font-black tracking-tighter uppercase italic flex items-center gap-2">
|
<h3 className="text-xl font-black tracking-tighter uppercase italic flex items-center gap-2">
|
||||||
<Server size={24} className="text-green" strokeWidth={3} /> Analysis Matrix
|
<Server size={24} className="text-green" strokeWidth={3} /> Hierarchical Matrix
|
||||||
</h3>
|
</h3>
|
||||||
<span className="text-[10px] bg-surface1 px-3 py-1.5 rounded-full font-black text-overlay1 uppercase tracking-widest">Select Process to Inspect</span>
|
<div className="flex items-center gap-4">
|
||||||
|
<div className="flex items-center gap-1.5 text-[9px] font-bold text-overlay1 uppercase">
|
||||||
|
<div className="w-2 h-2 rounded-full bg-blue/40" /> Inclusive Sum
|
||||||
|
</div>
|
||||||
|
<span className="text-[10px] bg-surface1 px-3 py-1.5 rounded-full font-black text-overlay1 uppercase tracking-widest">Toggle Nodes to Expand</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-[1fr_80px_100px_100px_100px_100px_200px] gap-4 px-6 py-4 bg-surface1/50 rounded-2xl font-black uppercase tracking-widest text-[10px] text-overlay1 mb-2">
|
<div className="grid grid-cols-[1fr_80px_100px_100px_100px_100px_200px] gap-4 px-6 py-4 bg-surface1/50 rounded-2xl font-black uppercase tracking-widest text-[10px] text-overlay1 mb-2">
|
||||||
<div className="cursor-pointer hover:text-text transition-colors flex items-center gap-1" onClick={() => handleSort('name')}>
|
<div className="cursor-pointer hover:text-text transition-colors flex items-center gap-1" onClick={() => handleSort('name')}>
|
||||||
Process {sortField === 'name' && (sortOrder === 'asc' ? '↑' : '↓')}
|
Process {sortField === 'name' && (sortOrder === 'asc' ? '↑' : '↓')}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('instance_count')}>Units</div>
|
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('pid')}>PID</div>
|
||||||
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('avg_cpu')}>Avg CPU</div>
|
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('inclusive_avg_cpu')}>Total CPU</div>
|
||||||
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('peak_cpu')}>Peak CPU</div>
|
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('peak_cpu')}>Peak</div>
|
||||||
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('avg_memory_mb')}>Avg Mem</div>
|
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('inclusive_avg_memory_mb')}>Total Mem</div>
|
||||||
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('peak_memory_mb')}>Peak Mem</div>
|
<div className="text-right cursor-pointer hover:text-text transition-colors" onClick={() => handleSort('peak_memory_mb')}>Peak</div>
|
||||||
<div className="pl-4">Insights</div>
|
<div className="pl-4">Insights</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-y-auto flex-1 custom-scrollbar px-2">
|
<div className="overflow-y-auto flex-1 custom-scrollbar px-2">
|
||||||
{sortedProcesses.map((proc, i) => (
|
{renderTreeRows(sortedProcesses)}
|
||||||
<div
|
</div>
|
||||||
key={i}
|
|
||||||
onClick={() => setSelectedProcess(proc)}
|
<div className="p-4 bg-surface0/50 border-t border-surface1 text-[9px] text-overlay1 font-medium italic flex items-center gap-2">
|
||||||
className="grid grid-cols-[1fr_80px_100px_100px_100px_100px_200px] gap-4 px-4 py-4 border-b border-surface1/20 hover:bg-surface1/20 cursor-pointer transition-all rounded-xl group"
|
<AlertTriangle size={10} />
|
||||||
>
|
<span>Memory is Resident Set Size (RSS). Summed totals may exceed physical RAM due to shared segments.</span>
|
||||||
<div className="font-black text-text truncate text-sm flex items-center gap-3 group-hover:text-blue transition-colors" title={proc.name}>
|
|
||||||
<div className="w-2 h-2 rounded-full bg-surface2 group-hover:bg-blue transition-colors shrink-0" />
|
|
||||||
{proc.name}
|
|
||||||
</div>
|
|
||||||
<div className="text-overlay2 font-mono text-xs text-right self-center tabular-nums">{proc.instance_count}</div>
|
|
||||||
<div className="text-blue font-black text-sm text-right self-center tabular-nums">{proc.avg_cpu.toFixed(1)}%</div>
|
|
||||||
<div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{proc.peak_cpu.toFixed(1)}%</div>
|
|
||||||
<div className="text-mauve font-black text-sm text-right self-center tabular-nums">{proc.avg_memory_mb.toFixed(0)}MB</div>
|
|
||||||
<div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{proc.peak_memory_mb.toFixed(0)}MB</div>
|
|
||||||
<div className="flex flex-wrap gap-1.5 pl-4 items-center">
|
|
||||||
{proc.warnings.length > 0 ? proc.warnings.map((w, idx) => (
|
|
||||||
<span key={idx} className="bg-red/10 text-red text-[9px] font-black px-2 py-1 rounded-lg border border-red/20 flex items-center gap-1 uppercase tracking-tighter">
|
|
||||||
<AlertTriangle size={8} strokeWidth={3} /> {w}
|
|
||||||
</span>
|
|
||||||
)) : (
|
|
||||||
<span className="text-[10px] text-green/40 font-black uppercase italic tracking-tighter">Healthy</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -506,7 +570,7 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
|
|||||||
<div className="w-full max-w-2xl h-full bg-mantle rounded-3xl border border-surface1 shadow-3xl flex flex-col overflow-hidden">
|
<div className="w-full max-w-2xl h-full bg-mantle rounded-3xl border border-surface1 shadow-3xl flex flex-col overflow-hidden">
|
||||||
<div className="p-8 border-b border-surface1 flex justify-between items-start shrink-0">
|
<div className="p-8 border-b border-surface1 flex justify-between items-start shrink-0">
|
||||||
<div>
|
<div>
|
||||||
<div className="text-xs font-black text-blue uppercase tracking-widest mb-1">Process Inspector</div>
|
<div className="text-xs font-black text-blue uppercase tracking-widest mb-1">Process Inspector (PID: {selectedProcess.pid})</div>
|
||||||
<h2 className="text-3xl font-black text-text tracking-tighter uppercase italic truncate max-w-md">{selectedProcess.name}</h2>
|
<h2 className="text-3xl font-black text-text tracking-tighter uppercase italic truncate max-w-md">{selectedProcess.name}</h2>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@@ -520,19 +584,19 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
|
|||||||
<div className="flex-1 overflow-y-auto p-8 flex flex-col gap-8 custom-scrollbar">
|
<div className="flex-1 overflow-y-auto p-8 flex flex-col gap-8 custom-scrollbar">
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-lg">
|
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-lg">
|
||||||
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-2">Instances Detected</div>
|
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-2">Total Avg CPU</div>
|
||||||
<div className="text-4xl font-black text-text">{selectedProcess.instance_count}</div>
|
<div className="text-4xl font-black text-text tabular-nums">{selectedProcess.inclusive_avg_cpu.toFixed(1)}%</div>
|
||||||
<p className="text-xs text-subtext1 mt-2">Maximum concurrent processes seen with this name.</p>
|
<p className="text-xs text-subtext1 mt-2">Sum of this process and all its children.</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-lg">
|
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-lg">
|
||||||
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-2">Average Impact</div>
|
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-2">Total Avg RAM</div>
|
||||||
<div className="text-4xl font-black text-blue">{selectedProcess.avg_cpu.toFixed(1)}%</div>
|
<div className="text-4xl font-black text-mauve tabular-nums">{selectedProcess.inclusive_avg_memory_mb.toFixed(0)}MB</div>
|
||||||
<p className="text-xs text-subtext1 mt-2">Mean CPU usage across the entire session.</p>
|
<p className="text-xs text-subtext1 mt-2">Combined RSS memory of the subtree.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="card h-64 shrink-0 bg-base border border-surface1">
|
<div className="card h-64 shrink-0 bg-base border border-surface1">
|
||||||
<div className="card-title mb-4">Resource History (Summed)</div>
|
<div className="card-title mb-4">Self-Resource History (Exclusive)</div>
|
||||||
<div className="flex-1 min-h-0">
|
<div className="flex-1 min-h-0">
|
||||||
<ResponsiveContainer width="100%" height="100%">
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
<AreaChart data={selectedProcess.history}>
|
<AreaChart data={selectedProcess.history}>
|
||||||
@@ -552,13 +616,31 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
contentStyle={{ background: 'var(--crust)', border: '1px solid var(--surface1)', borderRadius: '12px' }}
|
contentStyle={{ background: 'var(--crust)', border: '1px solid var(--surface1)', borderRadius: '12px' }}
|
||||||
/>
|
/>
|
||||||
<Area type="monotone" dataKey="cpu_usage" name="Total CPU %" stroke="var(--blue)" fill="url(#procCpuGrad)" strokeWidth={3} />
|
<Area type="monotone" dataKey="cpu_usage" name="Self CPU %" stroke="var(--blue)" fill="url(#procCpuGrad)" strokeWidth={3} />
|
||||||
<Area type="monotone" dataKey="memory_mb" name="Total Mem (MB)" stroke="var(--mauve)" fill="url(#procMemGrad)" strokeWidth={2} />
|
<Area type="monotone" dataKey="memory_mb" name="Self Mem (MB)" stroke="var(--mauve)" fill="url(#procMemGrad)" strokeWidth={2} />
|
||||||
</AreaChart>
|
</AreaChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h4 className="text-xs font-black text-overlay2 uppercase tracking-widest">Process Details</h4>
|
||||||
|
<div className="bg-surface0 border border-surface1 rounded-2xl p-6 space-y-3">
|
||||||
|
<div className="flex justify-between text-sm">
|
||||||
|
<span className="text-subtext1">Peak Self CPU</span>
|
||||||
|
<span className="font-black text-blue">{selectedProcess.peak_cpu.toFixed(1)}%</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between text-sm">
|
||||||
|
<span className="text-subtext1">Peak Self RAM</span>
|
||||||
|
<span className="font-black text-mauve">{selectedProcess.peak_memory_mb.toFixed(0)}MB</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between text-sm">
|
||||||
|
<span className="text-subtext1">Child Process Count</span>
|
||||||
|
<span className="font-black text-green">{selectedProcess.children.length}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h4 className="text-xs font-black text-overlay2 uppercase tracking-widest">Profiling Insights</h4>
|
<h4 className="text-xs font-black text-overlay2 uppercase tracking-widest">Profiling Insights</h4>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user