@once @endonce

Statistics

Monitor your server's performance metrics and resource utilization over time.

Live Telemetry

Processor Utilization

Network Traffic

Memory Utilization

Storage I/O

@php $statisticsExportRows = []; @endphp

Statistics History

New Report
Creating...
@forelse($this->statistics as $stat) @php $networkStats = $this->getCurrentNetworkStats($stat); $diskStats = $this->getCurrentDiskStats($stat); $cpuPercent = $stat->cpumax > 0 ? ($stat->cpuused / $stat->cpumax * 100) : 0; $memPercent = $stat->memorymax > 0 ? ($stat->memoryused / $stat->memorymax * 100) : 0; $diskPercent = ($stat->diskmax ?? 0) > 0 ? (($stat->diskused ?? 0) / ($stat->diskmax ?? 1) * 100) : 0; $statisticsExportRows[] = [ 'date_time' => $stat->DateTime ? $stat->DateTime->format('M d, Y H:i:s') : '-', 'status' => $stat->vmstatus ? ucfirst($stat->vmstatus) : '-', 'cpu' => number_format($cpuPercent, 1) . '%', 'memory' => number_format($memPercent, 1) . '%', 'disk' => (($stat->diskmax ?? 0) > 0 && ($stat->diskused ?? 0) > 0) ? number_format($diskPercent, 1) . '%' : 'N/A', 'network_in' => Illuminate\Support\Number::fileSize(bytes: $networkStats['netin']), 'network_out' => Illuminate\Support\Number::fileSize(bytes: $networkStats['netout']), 'disk_io' => sprintf( '%s / %s', Illuminate\Support\Number::fileSize(bytes: $diskStats['diskread'] ?? 0), Illuminate\Support\Number::fileSize(bytes: $diskStats['diskwrite'] ?? 0) ), 'uptime' => $stat->uptime > 0 ? $this->formatUptime($stat->uptime) : '-', ]; @endphp @empty @endforelse
Date & Time
Status
CPU
Memory
Disk
Network In
Network Out
Disk I/O
Uptime
Actions
{{ $stat->DateTime->format('M d, Y') }}
{{ $stat->DateTime->format('H:i:s') }}
@if($stat->vmstatus) {{ ucfirst($stat->vmstatus) }} @else - @endif
{{ number_format($cpuPercent, 1) }}%
{{ number_format($memPercent, 1) }}%
@if(($stat->diskmax ?? 0) > 0 && ($stat->diskused ?? 0) > 0)
{{ number_format($diskPercent, 1) }}%
@else N/A @endif
{{ Illuminate\Support\Number::fileSize(bytes: $networkStats['netin']) }}
@if($networkStats['netin_rate'] > 0)
{{ Illuminate\Support\Number::fileSize(bytes: (int)$networkStats['netin_rate']) }}/s
@endif
{{ Illuminate\Support\Number::fileSize(bytes: $networkStats['netout']) }}
@if($networkStats['netout_rate'] > 0)
{{ Illuminate\Support\Number::fileSize(bytes: (int)$networkStats['netout_rate']) }}/s
@endif
{{ Illuminate\Support\Number::fileSize(bytes: $diskStats['diskread'] ?? 0) }}
{{ Illuminate\Support\Number::fileSize(bytes: $diskStats['diskwrite'] ?? 0) }}
@if($stat->uptime > 0) {{ $this->formatUptime($stat->uptime) }} @else - @endif

No statistics available

Statistics are collected every 5 minutes automatically.

Show entries ({{ $this->statistics->total() }} total)
@if($this->statistics->hasPages())
{{ $this->statistics->links() }}
@endif
@php $taskHistoryExportRows = []; @endphp

Task History

@forelse($this->taskHistory as $task) @php $startTime = isset($task['starttime']) ? \Carbon\Carbon::createFromTimestamp($task['starttime']) : null; $endTime = isset($task['endtime']) && $task['endtime'] > 0 ? \Carbon\Carbon::createFromTimestamp($task['endtime']) : null; $duration = null; if ($startTime && $endTime) { $duration = $startTime->diffInSeconds($endTime); } elseif ($startTime && isset($task['status']) && $task['status'] === 'running') { $duration = $startTime->diffInSeconds(now()); } $taskUpid = $task['upid'] ?? $task['id'] ?? ''; $taskKey = md5($taskUpid . ($task['starttime'] ?? '')); $isExpanded = in_array($taskUpid, $this->expandedTaskUpids ?? []); $taskHistoryExportRows[] = [ 'type' => $task['type'] ?? 'N/A', 'status' => $task['status'] ?? '-', 'start_time' => $startTime ? $startTime->format('M d, Y H:i:s') : '-', 'end_time' => $endTime ? $endTime->format('M d, Y H:i:s') : '-', 'duration' => $duration !== null ? $this->formatUptime($duration) : '-', ]; @endphp @empty @endforelse
Type
Status
Start Time
End Time
Duration
{{ $task['type'] ?? 'N/A' }} @if(isset($task['status'])) @if($task['status'] === 'OK') Success @else Failure @endif @else - @endif @if($startTime)
{{ $startTime->format('M d, Y') }}
{{ $startTime->format('H:i:s') }}
@else - @endif
@if($endTime)
{{ $endTime->format('M d, Y') }}
{{ $endTime->format('H:i:s') }}
@else - @endif
@if($duration !== null) {{ $this->formatUptime($duration) }} @else - @endif

Task Information

Loading task details...

No detailed information available for this task.

No task history available

Task history will appear here as tasks are executed on the server.

@php $lifecycleEventsExportRows = []; @endphp

Recent Lifecycle Events

@forelse(collect($this->chartEvents)->take(20) as $index => $event) @php $startTime = isset($event['starttime']) ? \Carbon\Carbon::createFromTimestamp($event['starttime']) : null; $endTime = isset($event['endtime']) && $event['endtime'] > 0 ? \Carbon\Carbon::createFromTimestamp($event['endtime']) : null; $duration = $event['duration'] ?? null; $eventUpid = $event['upid'] ?? $event['timestamp'] ?? ''; $eventKey = md5($eventUpid . ($event['starttime'] ?? '')); $isExpanded = in_array($eventUpid, $this->expandedTaskUpids ?? []); $eventColorMap = [ 'start' => 'text-success', 'shutdown' => 'text-danger', 'reboot' => 'text-info', 'reset' => 'text-warning', 'backup' => 'text-purple-200', ]; $eventColor = $eventColorMap[$event['type']] ?? 'text-base/70'; $lifecycleEventsExportRows[] = [ 'type' => $event['label'] ?? 'N/A', 'status' => ucfirst($event['status'] ?? '-'), 'start_time' => $startTime ? $startTime->format('M d, Y H:i:s') : '-', 'end_time' => $endTime ? $endTime->format('M d, Y H:i:s') : '-', 'duration' => $duration !== null ? $this->formatUptime($duration) : '-', ]; @endphp @empty @endforelse
Type
Status
Start Time
End Time
Duration
{{ $event['label'] ?? 'N/A' }} @if(isset($event['status'])) @if(strtolower($event['status']) === 'ok') Success @elseif(strtolower($event['status']) === 'running') Running @else Failure @endif @else - @endif @if($startTime)
{{ $startTime->format('M d, Y') }}
{{ $startTime->format('H:i:s') }}
@else - @endif
@if($endTime)
{{ $endTime->format('M d, Y') }}
{{ $endTime->format('H:i:s') }}
@else - @endif
@if($duration !== null) {{ $this->formatUptime($duration) }} @else - @endif

Event Information

Type {{ $event['original_type'] ?? 'N/A' }}
Status {{ ucfirst($event['status'] ?? 'Unknown') }}
Event Type {{ $event['label'] ?? 'N/A' }}
@if(isset($event['upid']))
Task ID {{ str_replace([':root@pam!paymenter:', ':root@pam:'], '', $event['upid']) }}
@endif

No lifecycle events available

Lifecycle events will appear here as operations are performed on the server.

@php $historicalComparison = $this->historicalComparison; @endphp

Historical Data Comparison

@if($historicalPeriod === 'custom') @endif
@if($currentPeriod === 'custom') @endif
@if($historicalComparison && !isset($historicalComparison['error'])) @php $current = $historicalComparison['current']; $historical = $historicalComparison['historical']; $diff = $historicalComparison['differences']; @endphp
Metric
Historical ({{ $historical->DateTime->format('M d, Y H:i') }})
Current ({{ $current->DateTime->format('M d, Y H:i') }})
Change
Processor Utilization
{{ number_format($diff['cpu']['historical_percent'], 1) }}% {{ number_format($diff['cpu']['current_percent'], 1) }}% {{ $diff['cpu']['percent_change'] > 0 ? '+' : '' }}{{ number_format($diff['cpu']['percent_change'], 1) }}%
Memory Utilization
{{ number_format($diff['memory']['historical_percent'], 1) }}% {{ number_format($diff['memory']['current_percent'], 1) }}% {{ $diff['memory']['percent_change'] > 0 ? '+' : '' }}{{ number_format($diff['memory']['percent_change'], 1) }}%
Disk Read Rate
{{ $this->formatBytes($diff['disk_read']['historical_rate']) }}/s {{ $this->formatBytes($diff['disk_read']['current_rate']) }}/s {{ $diff['disk_read']['percent_change'] > 0 ? '+' : '' }}{{ number_format($diff['disk_read']['percent_change'], 1) }}%
Disk Write Rate
{{ $this->formatBytes($diff['disk_write']['historical_rate']) }}/s {{ $this->formatBytes($diff['disk_write']['current_rate']) }}/s {{ $diff['disk_write']['percent_change'] > 0 ? '+' : '' }}{{ number_format($diff['disk_write']['percent_change'], 1) }}%
Network Download Rate
{{ $this->formatBytes($diff['network_in']['historical_rate']) }}/s {{ $this->formatBytes($diff['network_in']['current_rate']) }}/s {{ $diff['network_in']['percent_change'] > 0 ? '+' : '' }}{{ number_format($diff['network_in']['percent_change'], 1) }}%
Network Upload Rate
{{ $this->formatBytes($diff['network_out']['historical_rate']) }}/s {{ $this->formatBytes($diff['network_out']['current_rate']) }}/s {{ $diff['network_out']['percent_change'] > 0 ? '+' : '' }}{{ number_format($diff['network_out']['percent_change'], 1) }}%
@elseif($historicalComparison && isset($historicalComparison['error']))

{{ $historicalComparison['message'] }}

@if(isset($historicalComparison['total_stats']))

Total statistics in database: {{ $historicalComparison['total_stats'] }} @if($historicalComparison['total_stats'] == 0) - Statistics are collected automatically every hour. You can also create manual statistics using the "Create Statistics" button above. @elseif($historicalComparison['total_stats'] < 2) - At least 2 statistics are needed for comparison. Wait for more data to be collected or create a manual statistic. @endif

@endif
@else

No comparison data available

Please select periods with available statistics data.

@endif

Network Analysis

Deep visibility into firewall sessions, security threats, and top consumers of bandwidth powered by the Core Router API.

@if($networkAnalysisLoading || ($networkAnalysis['lastUpdated'] === null && $networkAnalysis['error'] === null))

Fetching data from Core Router... reload page

@elseif($networkAnalysis['error'])

{{ $networkAnalysis['error'] }}

Ensure the Core Router API credentials are configured in your environment.

@else
@if(empty($networkAnalysis['connections']))
No matching connections tracked for this server.
@else
@foreach($this->paginatedConnections as $index => $connection) @php // Use raw bytes value from backend for reliable numeric sorting $bytesForSort = (int)($connection['bytes'] ?? 0); @endphp @endforeach
Direction
Protocol
Source
Destination
State
Traffic
@php $direction = $connection['direction'] ?? '—'; @endphp @if($direction !== '—')
{{ $direction }}
@else — @endif
@php $protocol = $connection['protocol'] ?? '—'; @endphp @if($protocol !== '—')
{{ $protocol }}
@else — @endif
@php $sourceIP = $connection['source'] ?? '—'; $isSourcePublic = $sourceIP !== '—' && $this->checkIsPublicIP($sourceIP); @endphp
{{ $sourceIP }} @if($isSourcePublic)
@endif
@if(isset($connection['source_port'])) {{ $connection['source_port'] }} @endif
@php $destIP = $connection['destination'] ?? '—'; $isDestPublic = $destIP !== '—' && $this->checkIsPublicIP($destIP); @endphp
{{ $destIP }} @if($isDestPublic)
@endif
@if(isset($connection['destination_port'])) {{ $connection['destination_port'] }} @endif
@php $state = $connection['state'] ?? '—'; @endphp @if($state !== '—')
{{ $state }}
@else — @endif
{{ $connection['bytes_human'] ?? '—' }} @if(isset($connection['packets'])) {{ number_format($connection['packets']) }} packets @endif
{{-- Connections Pagination Controls --}} @if(count($networkAnalysis['connections']) > 0)
{{-- Records per page selector --}}
per page
{{-- Page info and navigation --}}
Showing {{ (($connectionsCurrentPage - 1) * $connectionsPerPage) + 1 }} - {{ min($connectionsCurrentPage * $connectionsPerPage, count($networkAnalysis['connections'])) }} of {{ count($networkAnalysis['connections']) }} connections
{{-- First page --}} {{-- Previous page --}} {{-- Page numbers --}} @php $connectionsTotalPages = $this->connectionsTotalPages; $startPage = max(1, $connectionsCurrentPage - 2); $endPage = min($connectionsTotalPages, $connectionsCurrentPage + 2); @endphp @if($startPage > 1) @if($startPage > 2) ... @endif @endif @for($i = $startPage; $i <= $endPage; $i++) @endfor @if($endPage < $connectionsTotalPages) @if($endPage < $connectionsTotalPages - 1) ... @endif @endif {{-- Next page --}} {{-- Last page --}}
@endif
@endif
@if(empty($networkAnalysis['topConnections']))
No connection data available.
@else
@foreach($this->paginatedTopConnections as $index => $row) @php $endpointIP = $row['endpoint'] ?? '—'; $port = $row['port'] ?? 0; $connections = $row['count'] ?? 0; $bytes = $row['bytes'] ?? 0; $bytesForSort = $bytes; @endphp @endforeach
Endpoint
Port
Connections
Traffic
@php $isEndpointPublic = $endpointIP !== '—' && $this->checkIsPublicIP($endpointIP); @endphp
{{ $endpointIP }} @if($isEndpointPublic)
@endif
@if(isset($row['port']) && $row['port'] !== '—')
{{ $row['port'] }}
@else — @endif
{{ number_format($row['count']) }}
{{ $row['bytes_human'] }} {{ number_format($row['packets']) }} packets
{{-- Top Connections Pagination Controls --}} @if(count($networkAnalysis['topConnections']) > 0)
{{-- Records per page selector --}}
per page
{{-- Page info and navigation --}}
Showing {{ (($topConnectionsCurrentPage - 1) * $topConnectionsPerPage) + 1 }} - {{ min($topConnectionsCurrentPage * $topConnectionsPerPage, count($networkAnalysis['topConnections'])) }} of {{ count($networkAnalysis['topConnections']) }} peers
{{-- First page --}} {{-- Previous page --}} {{-- Page numbers --}} @php $topConnectionsTotalPages = $this->topConnectionsTotalPages; $startPage = max(1, $topConnectionsCurrentPage - 2); $endPage = min($topConnectionsTotalPages, $topConnectionsCurrentPage + 2); @endphp @if($startPage > 1) @if($startPage > 2) ... @endif @endif @for($i = $startPage; $i <= $endPage; $i++) @endfor @if($endPage < $topConnectionsTotalPages) @if($endPage < $topConnectionsTotalPages - 1) ... @endif @endif {{-- Next page --}} {{-- Last page --}}
@endif
@endif
@if(empty($networkAnalysis['topPorts']))
No port statistics are available.
@else
@foreach($this->paginatedTopPorts as $index => $row) @php $port = $row['port'] ?? 0; $connections = $row['connections'] ?? 0; $bytes = $row['bytes'] ?? 0; $bytesForSort = $bytes; @endphp @endforeach
Port
Connections
Traffic
{{ $row['port'] }}
{{ number_format($row['connections']) }}
{{ $row['bytes_human'] }} {{ number_format($row['packets']) }} packets
{{-- Top Ports Pagination Controls --}} @if(count($networkAnalysis['topPorts']) > 0)
{{-- Records per page selector --}}
per page
{{-- Page info and navigation --}}
Showing {{ (($topPortsCurrentPage - 1) * $topPortsPerPage) + 1 }} - {{ min($topPortsCurrentPage * $topPortsPerPage, count($networkAnalysis['topPorts'])) }} of {{ count($networkAnalysis['topPorts']) }} ports
{{-- First page --}} {{-- Previous page --}} {{-- Page numbers --}} @php $topPortsTotalPages = $this->topPortsTotalPages; $startPage = max(1, $topPortsCurrentPage - 2); $endPage = min($topPortsTotalPages, $topPortsCurrentPage + 2); @endphp @if($startPage > 1) @if($startPage > 2) ... @endif @endif @for($i = $startPage; $i <= $endPage; $i++) @endfor @if($endPage < $topPortsTotalPages) @if($endPage < $topPortsTotalPages - 1) ... @endif @endif {{-- Next page --}} {{-- Last page --}}
@endif
@endif
@if(empty($networkAnalysis['security']))
No security threats detected. All connections appear to be safe.
@else
@foreach($networkAnalysis['security'] as $warning) @php $conn = $warning['connection'] ?? []; @endphp @php $riskLevel = $warning['risk_level'] ?? 'Medium'; $attackType = $warning['attack_type'] ?? 'Unknown Threat'; $riskDescription = $warning['risk_description'] ?? 'Malicious IP detected from blocklist'; $riskBadgeClass = match($riskLevel) { 'Critical' => 'bg-danger/20 text-danger border-danger/30', 'High' => 'bg-warning/20 text-warning border-warning/30', 'Medium' => 'bg-warning/10 text-warning border-warning/20', 'Low' => 'bg-base/10 text-base/70 border-base/20', default => 'bg-warning/10 text-warning border-warning/20', }; @endphp
Security Threat Detected {{ $warning['type'] }} {{ $riskLevel }} Risk {{ $attackType }} @if(isset($warning['quantity']) && $warning['quantity'] > 1) {{ $warning['quantity'] }}x Repeated @endif

{{ $warning['threat'] }} @if(isset($warning['quantity']) && $warning['quantity'] > 1) ({{ $warning['quantity'] }} similar connection{{ $warning['quantity'] > 1 ? 's' : '' }} detected) @endif

@php $threatIP = $warning['ip'] ?? '—'; $isThreatPublic = $threatIP !== '—' && $this->checkIsPublicIP($threatIP); @endphp
IP Address: {{ $threatIP }} @if($isThreatPublic)
@endif
@endforeach
@endif
@endif
@script @endscript