[ agent ] [ status ] - accomplish agent status - 4

This commit is contained in:
zeaslity
2023-01-05 14:57:31 +08:00
parent 24471df4f8
commit f4f8417e4d
19 changed files with 352 additions and 85 deletions

View File

@@ -39,14 +39,6 @@
</dependency>
<!-- Operating System and Hardware Information library for Java -->
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core-java11</artifactId>
<version>6.4.0</version>
</dependency>
</dependencies>
<dependencyManagement>

View File

@@ -1,39 +0,0 @@
package io.wdd.agent.status;
import io.wdd.agent.status.hardware.CpuInfo;
import io.wdd.agent.status.hardware.MemoryInfo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import oshi.hardware.HWDiskStore;
import oshi.hardware.NetworkIF;
import oshi.software.os.OperatingSystem;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class AgentStatus {
String time;
String agentName;
String agentTopicName;
CpuInfo cpuInfo;
MemoryInfo memoryInfo;
List<HWDiskStore> diskStoreInfo;
List<NetworkIF> networkInfo;
OperatingSystem osInfo;
}

View File

@@ -4,8 +4,12 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.wdd.agent.config.beans.init.AgentServerInfo;
import io.wdd.agent.config.utils.TimeUtils;
import io.wdd.agent.status.hardware.CpuInfo;
import io.wdd.agent.status.hardware.MemoryInfo;
import io.wdd.common.beans.status.CpuInfo;
import io.wdd.common.beans.status.DiskInfo;
import io.wdd.common.beans.status.MemoryInfo;
import io.wdd.common.beans.status.NetworkInfo;
import io.wdd.common.beans.status.AgentStatus;
import io.wdd.common.utils.FormatUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.connection.stream.StringRecord;
@@ -13,6 +17,7 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.OperatingSystem;
@@ -20,6 +25,7 @@ import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
@@ -61,13 +67,19 @@ public class AgentStatusCollector {
agentStatus.setCpuInfo(new CpuInfo(hardware.getProcessor(), 1000));
/* Memory */
agentStatus.setMemoryInfo(new MemoryInfo().build(hardware.getMemory()));
agentStatus.setMemoryInfo(
MemoryInfo.build(hardware.getMemory())
);
/* Storage */
agentStatus.setDiskStoreInfo(hardware.getDiskStores());
agentStatus.setDiskStoreInfo(
DiskInfo.mapFromDiskStore(hardware.getDiskStores())
);
/* Network */
agentStatus.setNetworkInfo(hardware.getNetworkIFs(false));
agentStatus.setNetworkInfo(
NetworkInfo.mapFromNetworkIFS(hardware.getNetworkIFs(false))
);
/* operating system info */
agentStatus.setOsInfo(os);
@@ -78,10 +90,21 @@ public class AgentStatusCollector {
return agentStatus;
}
/**
* when server first time boot up
* the server info are not collected completely
* this will be executed to update or complete the octopus agent server info
*/
@Scheduled(initialDelay = 180000)
public void updateAgentServerInfo(){
// agent boot up 60s then start to report its status
}
// agent boot up 120s then start to report its status
// at the fix rate of 15s
@Scheduled(initialDelay = 60000, fixedRate = 5000)
@Scheduled(initialDelay = 60000, fixedRate = 15000)
public void sendAgentStatusToRedis() {
try {
@@ -101,5 +124,4 @@ public class AgentStatusCollector {
}
}

View File

@@ -1,123 +0,0 @@
package io.wdd.agent.status.hardware;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import oshi.hardware.CentralProcessor;
import java.text.DecimalFormat;
@AllArgsConstructor
@Data
@NoArgsConstructor
public class CpuInfo {
private static final DecimalFormat LOAD_FORMAT = new DecimalFormat("#.00");
/**
* CPU总线程
*/
private Integer cpuTotal;
/**
* CPU核心数
* */
private Integer coreTotal;
/**
* CPU总数 计算方式理论上为 cpuTotal * 100
*/
private double cpuUsageTotol;
/**
* CPU系统使用率
*/
private double systemCpuUsage;
/**
* CPU用户使用率
*/
private double userCpuUsage;
/**
* CPU当前等待率
*/
private double wait;
/**
* CPU当前空闲率
*/
private double free;
/**
* CPU型号信息
*/
private String cpuModel;
private double[] cpuLoadAverage;
private double[] systemLoadAverage;
/**
* CPU型号信息
*/
private CpuTicks ticks;
public CpuInfo(CentralProcessor processor, long waitingTime){
this.init(processor, waitingTime);
}
/**
* 获取指定等待时间内系统CPU 系统使用率、用户使用率、利用率等等 相关信息
*
* @param processor {@link CentralProcessor}
* @param waitingTime 设置等待时间,单位毫秒
* @since 5.7.12
*/
private void init(CentralProcessor processor, long waitingTime) {
final CpuTicks ticks = new CpuTicks(processor, waitingTime);
this.ticks = ticks;
this.cpuTotal = processor.getLogicalProcessorCount();
this.coreTotal = processor.getPhysicalProcessorCount();
this.cpuModel = processor.toString();
final long totalCpu = ticks.totalCpu();
this.cpuUsageTotol = totalCpu;
this.systemCpuUsage = formatDouble(ticks.cSys, totalCpu);
this.userCpuUsage = formatDouble(ticks.user, totalCpu);
this.wait = formatDouble(ticks.ioWait, totalCpu);
this.free = formatDouble(ticks.idle, totalCpu);
// system load average
this.systemLoadAverage = processor.getSystemLoadAverage(3);
// cpu load average
this.cpuLoadAverage = processor.getProcessorCpuLoad(waitingTime);
}
/**
* 获取每个CPU核心的tick计算方式为 100 * tick / totalCpu
*
* @param tick tick
* @param totalCpu CPU总数
* @return 平均每个CPU核心的tick
* @since 5.7.12
*/
private static double formatDouble(long tick, long totalCpu) {
if (0 == totalCpu) {
return 0D;
}
return Double.parseDouble(LOAD_FORMAT.format(tick <= 0 ? 0 : (100d * tick / totalCpu)));
}
}

View File

@@ -1,100 +0,0 @@
package io.wdd.agent.status.hardware;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import oshi.hardware.CentralProcessor;
import oshi.util.Util;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CpuTicks {
long idle;
long nice;
long irq;
long softIrq;
long steal;
long cSys;
long user;
long ioWait;
private static int IDLEIndex;
private static int NICEIndex;
private static int IRQIndex;
private static int SOFTIRQIndex;
private static int STEALIndex;
private static int SYSTEMIndex;
private static int USERIndex;
private static int IOWAITIndex;
static {
IDLEIndex = CentralProcessor.TickType.IDLE.getIndex();
NICEIndex = CentralProcessor.TickType.NICE.getIndex();
IRQIndex =CentralProcessor.TickType.IRQ.getIndex();
SOFTIRQIndex = CentralProcessor.TickType.SOFTIRQ.getIndex();
STEALIndex = CentralProcessor.TickType.STEAL.getIndex();
SYSTEMIndex = CentralProcessor.TickType.SYSTEM.getIndex();
USERIndex = CentralProcessor.TickType.USER.getIndex();
IOWAITIndex = CentralProcessor.TickType.IOWAIT.getIndex();
}
/**
* 构造等待时间为用于计算在一定时长内的CPU负载情况如传入1000表示最近1秒的负载情况
*
* @param processor {@link CentralProcessor}
* @param waitingTime 设置等待时间,单位毫秒
*/
public CpuTicks(CentralProcessor processor, long waitingTime) {
// CPU信息
final long[] prevTicks = processor.getSystemCpuLoadTicks();
// 这里必须要设置延迟
Util.sleep(waitingTime);
final long[] ticks = processor.getSystemCpuLoadTicks();
this.idle = tick(prevTicks, ticks, IDLEIndex);
this.nice = tick(prevTicks, ticks, NICEIndex);
this.irq = tick(prevTicks, ticks, IRQIndex);
this.softIrq = tick(prevTicks, ticks, SOFTIRQIndex);
this.steal = tick(prevTicks, ticks, STEALIndex);
this.cSys = tick(prevTicks, ticks, SYSTEMIndex);
this.user = tick(prevTicks, ticks, USERIndex);
this.ioWait = tick(prevTicks, ticks, IOWAITIndex);
}
/**
* 获取CPU总的使用率
*
* @return CPU总使用率
*/
public long totalCpu() {
return Math.max(user + nice + cSys + idle + ioWait + irq + softIrq + steal, 0);
}
/**
* 获取一段时间内的CPU负载标记差
*
* @param prevTicks 开始的ticks
* @param ticks 结束的ticks
* @param tickType tick类型
* @return 标记差
* @since 5.7.12
*/
private static long tick(long[] prevTicks, long[] ticks, int index) {
return ticks[index] - prevTicks[index];
}
}

View File

@@ -1,47 +0,0 @@
package io.wdd.agent.status.hardware;
import io.wdd.agent.status.hardware.config.FormatUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import oshi.hardware.GlobalMemory;
import oshi.hardware.VirtualMemory;
@NoArgsConstructor
@AllArgsConstructor
@Data
@SuperBuilder(toBuilder = true)
public class MemoryInfo {
String total;
String usage;
String available;
String memoryType;
String swapTotal;
String swapAvailable;
String swapUsage;
public MemoryInfo build(GlobalMemory memory) {
VirtualMemory virtualMemory = memory.getVirtualMemory();
return MemoryInfo.builder()
.memoryType(memory.getPhysicalMemory().get(0).getMemoryType())
.total(FormatUtils.formatData(memory.getTotal()))
.available(FormatUtils.formatData(memory.getAvailable()))
.usage(FormatUtils.formatData(memory.getTotal() - memory.getAvailable()))
.swapTotal(FormatUtils.formatData(virtualMemory.getSwapTotal()))
.swapUsage(FormatUtils.formatData(virtualMemory.getSwapUsed()))
.swapAvailable(FormatUtils.formatData(virtualMemory.getSwapTotal() - virtualMemory.getSwapUsed()))
.build();
}
}

View File

@@ -1,27 +0,0 @@
package io.wdd.agent.status.hardware;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import oshi.hardware.NetworkIF;
import java.util.List;
import java.util.stream.Collectors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class NetworkInfo {
public static List<NetworkInfo> mapFromNetworkIFS(List<NetworkIF> networkIFList){
return networkIFList.stream().map(
networkIF -> NetworkInfo.builder()
.build()
).collect(Collectors.toList());
}
}

View File

@@ -1,64 +0,0 @@
package io.wdd.agent.status.hardware.config;
import org.springframework.util.unit.DataSize;
/**
* 数据单位封装<p>
* 此类来自于Spring-framework
*
* <pre>
* BYTES 1B 2^0 1
* KILOBYTES 1KB 2^10 1,024
* MEGABYTES 1MB 2^20 1,048,576
* GIGABYTES 1GB 2^30 1,073,741,824
* TERABYTES 1TB 2^40 1,099,511,627,776
* </pre>
*
* @author Sam BrannenStephane Nicoll
* @since 5.3.10
*/
public enum DataUnit {
/**
* Bytes, 后缀表示为: {@code B}.
*/
BYTES("B", DataSize.ofBytes(1)),
/**
* Kilobytes, 后缀表示为: {@code KB}.
*/
KILOBYTES("KB", DataSize.ofKilobytes(1)),
/**
* Megabytes, 后缀表示为: {@code MB}.
*/
MEGABYTES("MB", DataSize.ofMegabytes(1)),
/**
* Gigabytes, 后缀表示为: {@code GB}.
*/
GIGABYTES("GB", DataSize.ofGigabytes(1)),
/**
* Terabytes, 后缀表示为: {@code TB}.
*/
TERABYTES("TB", DataSize.ofTerabytes(1));
public static final String[] UNIT_NAMES = new String[]{"B", "KB", "MB", "GB", "TB", "PB", "EB"};
private final String suffix;
private final DataSize size;
DataUnit(String suffix, DataSize size) {
this.suffix = suffix;
this.size = size;
}
DataSize size() {
return this.size;
}
}

View File

@@ -1,33 +0,0 @@
package io.wdd.agent.status.hardware.config;
import java.text.DecimalFormat;
public class FormatUtils {
/**
* 格式化输出百分比
*
* @param rate
* @return
*/
public static String formatRate(double rate) {
return new DecimalFormat("#.##%").format(rate);
}
/**
* 格式化输出大小 B/KB/MB...
*
* @param size
* @return
*/
public static String formatData(long size) {
if (size <= 0L) {
return "0B";
} else {
int digitGroups = Math.min(DataUnit.UNIT_NAMES.length - 1, (int) (Math.log10((double) size) / Math.log10(1024.0D)));
return (new DecimalFormat("#,##0.##")).format((double) size / Math.pow(1024.0D, digitGroups)) + " " + DataUnit.UNIT_NAMES[digitGroups];
}
}
}