бла бла бла
This commit is contained in:
@@ -18,6 +18,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-webflux'
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-webflux-test'
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
package com.htopweb.system;
|
||||
|
||||
import com.htopweb.system.linux.LinuxDetailsResponse;
|
||||
import com.htopweb.system.linux.LinuxDetailsService;
|
||||
|
||||
import com.htopweb.system.linux.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -15,12 +13,25 @@ public class SystemMetricsController {
|
||||
private final SystemMetricsService _systemMetricsService;
|
||||
private final LinuxDetailsService _linuxDetailsService;
|
||||
|
||||
private final CpuDetailsService _cpuDetailsService;
|
||||
|
||||
private final LinuxMemoryService _linuxMemoryService;
|
||||
private final LinuxDiskService _linuxDiskService;
|
||||
private final LinuxNetworkService _linuxNetworkService;
|
||||
|
||||
public SystemMetricsController(
|
||||
SystemMetricsService systemMetricsService,
|
||||
LinuxDetailsService linuxDetailsService
|
||||
LinuxDetailsService linuxDetailsService,
|
||||
CpuDetailsService cpuDetailsService,
|
||||
LinuxMemoryService linuxMemoryService, LinuxDiskService linuxDiskService, LinuxNetworkService linuxNetworkService
|
||||
|
||||
) {
|
||||
_systemMetricsService = systemMetricsService;
|
||||
_linuxDetailsService = linuxDetailsService;
|
||||
_cpuDetailsService = cpuDetailsService;
|
||||
_linuxMemoryService = linuxMemoryService;
|
||||
_linuxDiskService = linuxDiskService;
|
||||
_linuxNetworkService = linuxNetworkService;
|
||||
}
|
||||
|
||||
@GetMapping("/metrics")
|
||||
@@ -32,4 +43,24 @@ public class SystemMetricsController {
|
||||
public LinuxDetailsResponse getLinuxDetails() {
|
||||
return _linuxDetailsService.getDetails();
|
||||
}
|
||||
|
||||
@GetMapping("/cpu")
|
||||
public CpuDetailsResponse getCpuDetails() {
|
||||
return _cpuDetailsService.getDetails();
|
||||
}
|
||||
|
||||
@GetMapping("/linux/memory")
|
||||
public LinuxMemoryResponse getLinuxMemory() {
|
||||
return _linuxMemoryService.getDetails();
|
||||
}
|
||||
|
||||
@GetMapping("/linux/disks")
|
||||
public java.util.List<LinuxDiskResponse> getLinuxDisks() {
|
||||
return _linuxDiskService.getDisks();
|
||||
}
|
||||
|
||||
@GetMapping("/linux/network")
|
||||
public java.util.List<LinuxNetworkResponse> getLinuxNetwork() {
|
||||
return _linuxNetworkService.getInterfaces();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.htopweb.system.linux;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record CpuDetailsResponse(
|
||||
double totalUsagePercent,
|
||||
int logicalProcessors,
|
||||
List<CpuCoreResponse> cores
|
||||
) {
|
||||
public record CpuCoreResponse(
|
||||
int core,
|
||||
double usagePercent
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.htopweb.system.linux;
|
||||
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CpuDetailsService {
|
||||
|
||||
private final CentralProcessor _processor;
|
||||
private long[][] _previousCoreTicks;
|
||||
private long[] _previousSystemTicks;
|
||||
|
||||
public CpuDetailsService() {
|
||||
SystemInfo systemInfo = new SystemInfo();
|
||||
_processor = systemInfo.getHardware().getProcessor();
|
||||
|
||||
_previousCoreTicks = _processor.getProcessorCpuLoadTicks();
|
||||
_previousSystemTicks = _processor.getSystemCpuLoadTicks();
|
||||
}
|
||||
|
||||
public synchronized CpuDetailsResponse getDetails() {
|
||||
long[][] currentCoreTicks = _processor.getProcessorCpuLoadTicks();
|
||||
long[] currentSystemTicks = _processor.getSystemCpuLoadTicks();
|
||||
|
||||
double[] coreLoads = _processor.getProcessorCpuLoadBetweenTicks(
|
||||
_previousCoreTicks,
|
||||
currentCoreTicks
|
||||
);
|
||||
|
||||
double systemLoad = _processor.getSystemCpuLoadBetweenTicks(
|
||||
_previousSystemTicks,
|
||||
currentSystemTicks
|
||||
);
|
||||
|
||||
_previousCoreTicks = currentCoreTicks;
|
||||
_previousSystemTicks = currentSystemTicks;
|
||||
|
||||
List<CpuDetailsResponse.CpuCoreResponse> cores =
|
||||
new ArrayList<>(coreLoads.length);
|
||||
|
||||
for (int i = 0; i < coreLoads.length; i++) {
|
||||
cores.add(new CpuDetailsResponse.CpuCoreResponse(
|
||||
i,
|
||||
toPercent(coreLoads[i] * 100.0)
|
||||
));
|
||||
}
|
||||
|
||||
return new CpuDetailsResponse(
|
||||
toPercent(systemLoad * 100.0),
|
||||
_processor.getLogicalProcessorCount(),
|
||||
List.copyOf(cores)
|
||||
);
|
||||
}
|
||||
|
||||
private double toPercent(double value) {
|
||||
if (!Double.isFinite(value)) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return Math.round(
|
||||
Math.max(0.0, Math.min(100.0, value)) * 10.0
|
||||
) / 10.0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.htopweb.system.linux;
|
||||
|
||||
public record LinuxDiskResponse(
|
||||
String name,
|
||||
String mountPoint,
|
||||
String fileSystem,
|
||||
long totalBytes,
|
||||
long usableBytes,
|
||||
long usedBytes,
|
||||
double usagePercent
|
||||
) {}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.htopweb.system.linux;
|
||||
|
||||
import oshi.SystemInfo;
|
||||
import oshi.software.os.OSFileStore;
|
||||
import oshi.software.os.OperatingSystem;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class LinuxDiskService {
|
||||
|
||||
private final OperatingSystem _operatingSystem;
|
||||
|
||||
public LinuxDiskService() {
|
||||
SystemInfo systemInfo = new SystemInfo();
|
||||
_operatingSystem = systemInfo.getOperatingSystem();
|
||||
}
|
||||
|
||||
public List<LinuxDiskResponse> getDisks() {
|
||||
return _operatingSystem.getFileSystem()
|
||||
.getFileStores()
|
||||
.stream()
|
||||
.filter(store -> store.getMount().startsWith("/"))
|
||||
.filter(store -> store.getTotalSpace() > 0)
|
||||
.map(this::toResponse)
|
||||
.sorted(Comparator.comparing(LinuxDiskResponse::mountPoint))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private LinuxDiskResponse toResponse(OSFileStore store) {
|
||||
long total = Math.max(0L, store.getTotalSpace());
|
||||
long usable = Math.max(
|
||||
0L,
|
||||
Math.min(total, store.getUsableSpace())
|
||||
);
|
||||
long used = Math.max(0L, total - usable);
|
||||
|
||||
double usage = total > 0
|
||||
? Math.round((double) used / total * 1000.0) / 10.0
|
||||
: 0.0;
|
||||
|
||||
return new LinuxDiskResponse(
|
||||
store.getName(),
|
||||
store.getMount(),
|
||||
store.getType(),
|
||||
total,
|
||||
usable,
|
||||
used,
|
||||
usage
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.htopweb.system.linux;
|
||||
|
||||
public record LinuxMemoryResponse(
|
||||
long totalRamBytes,
|
||||
long usedRamBytes,
|
||||
long availableRamBytes,
|
||||
double ramUsagePercent,
|
||||
long totalSwapBytes,
|
||||
long usedSwapBytes,
|
||||
long freeSwapBytes,
|
||||
double swapUsagePercent
|
||||
) {}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.htopweb.system.linux;
|
||||
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.GlobalMemory;
|
||||
import oshi.hardware.VirtualMemory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class LinuxMemoryService {
|
||||
|
||||
private final GlobalMemory _memory;
|
||||
private final VirtualMemory _virtualMemory;
|
||||
|
||||
|
||||
public LinuxMemoryService() {
|
||||
SystemInfo systemInfo = new SystemInfo();
|
||||
_memory = systemInfo.getHardware().getMemory();
|
||||
_virtualMemory = _memory.getVirtualMemory();
|
||||
|
||||
}
|
||||
|
||||
public LinuxMemoryResponse getDetails() {
|
||||
long totalRam = Math.max(0L, _memory.getTotal());
|
||||
long availableRam = Math.max(0L, Math.min(totalRam, _memory.getAvailable()));
|
||||
long usedRam = Math.max(0L, totalRam - availableRam);
|
||||
|
||||
long totalSwap = Math.max(0L, _virtualMemory.getSwapTotal());
|
||||
long usedSwap = Math.max(
|
||||
0L,
|
||||
Math.min(totalSwap, _virtualMemory.getSwapUsed())
|
||||
);
|
||||
long freeSwap = Math.max(0L, totalSwap - usedSwap);
|
||||
|
||||
return new LinuxMemoryResponse(
|
||||
totalRam,
|
||||
usedRam,
|
||||
availableRam,
|
||||
percentage(usedRam, totalRam),
|
||||
totalSwap,
|
||||
usedSwap,
|
||||
freeSwap,
|
||||
percentage(usedSwap, totalSwap)
|
||||
);
|
||||
}
|
||||
|
||||
private double percentage(long used, long total) {
|
||||
if (total <= 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return Math.round((double) used / total * 1000.0) / 10.0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
package com.htopweb.system.linux;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record LinuxNetworkResponse(
|
||||
String name,
|
||||
String displayName,
|
||||
String macAddress,
|
||||
List<String> ipv4Addresses,
|
||||
List<String> ipv6Addresses,
|
||||
long bytesReceived,
|
||||
long bytesSent,
|
||||
long packetsReceived,
|
||||
long packetsSent,
|
||||
long inboundErrors,
|
||||
long outboundErrors,
|
||||
double receiveBytesPerSecond,
|
||||
double sendBytesPerSecond,
|
||||
double receiveMbps,
|
||||
double sendMbps
|
||||
) {}
|
||||
@@ -0,0 +1,93 @@
|
||||
|
||||
package com.htopweb.system.linux;
|
||||
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.NetworkIF;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@Service
|
||||
public class LinuxNetworkService {
|
||||
|
||||
private final SystemInfo _systemInfo;
|
||||
|
||||
private final ConcurrentMap<String, NetworkSnapshot> _previousSnapshots =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
public LinuxNetworkService() {
|
||||
_systemInfo = new SystemInfo();
|
||||
}
|
||||
|
||||
public List<LinuxNetworkResponse> getInterfaces() {
|
||||
return _systemInfo.getHardware()
|
||||
.getNetworkIFs()
|
||||
.stream()
|
||||
.map(this::toResponse)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private LinuxNetworkResponse toResponse(NetworkIF networkIF) {
|
||||
networkIF.updateAttributes();
|
||||
|
||||
String name = networkIF.getName();
|
||||
long received = Math.max(0L, networkIF.getBytesRecv());
|
||||
long sent = Math.max(0L, networkIF.getBytesSent());
|
||||
long now = System.nanoTime();
|
||||
|
||||
NetworkSnapshot current = new NetworkSnapshot(received, sent, now);
|
||||
NetworkSnapshot previous = _previousSnapshots.put(name, current);
|
||||
|
||||
double receiveBytesPerSecond = 0.0;
|
||||
double sendBytesPerSecond = 0.0;
|
||||
|
||||
if (previous != null && now > previous.timestampNanos()) {
|
||||
double elapsedSeconds =
|
||||
(now - previous.timestampNanos()) / 1_000_000_000.0;
|
||||
|
||||
if (received >= previous.bytesReceived()) {
|
||||
receiveBytesPerSecond =
|
||||
(received - previous.bytesReceived()) / elapsedSeconds;
|
||||
}
|
||||
|
||||
if (sent >= previous.bytesSent()) {
|
||||
sendBytesPerSecond =
|
||||
(sent - previous.bytesSent()) / elapsedSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
double receiveMbps = receiveBytesPerSecond * 8.0 / 1_000_000.0;
|
||||
double sendMbps = sendBytesPerSecond * 8.0 / 1_000_000.0;
|
||||
|
||||
return new LinuxNetworkResponse(
|
||||
name,
|
||||
networkIF.getDisplayName(),
|
||||
networkIF.getMacaddr(),
|
||||
Arrays.asList(networkIF.getIPv4addr()),
|
||||
Arrays.asList(networkIF.getIPv6addr()),
|
||||
received,
|
||||
sent,
|
||||
Math.max(0L, networkIF.getPacketsRecv()),
|
||||
Math.max(0L, networkIF.getPacketsSent()),
|
||||
Math.max(0L, networkIF.getInErrors()),
|
||||
Math.max(0L, networkIF.getOutErrors()),
|
||||
roundOne(receiveBytesPerSecond),
|
||||
roundOne(sendBytesPerSecond),
|
||||
roundOne(receiveMbps),
|
||||
roundOne(sendMbps)
|
||||
);
|
||||
}
|
||||
|
||||
private double roundOne(double value) {
|
||||
return Math.round(value * 10.0) / 10.0;
|
||||
}
|
||||
|
||||
private record NetworkSnapshot(
|
||||
long bytesReceived,
|
||||
long bytesSent,
|
||||
long timestampNanos
|
||||
) {}
|
||||
}
|
||||
@@ -9,5 +9,5 @@
|
||||
<link rel="stylesheet" href="styles-5INURTSO.css"></head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
<script src="main-7OF6PXJ5.js" type="module"></script></body>
|
||||
<script src="main-Y67327X6.js" type="module"></script></body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user