Merge pull request 'v1.0.2' (#6) from dev into master
Reviewed-on: #6
This commit was merged in pull request #6.
This commit is contained in:
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
import com.imyeyu.api.modules.system.bean.DockerStatusStore;
|
import com.imyeyu.api.modules.system.bean.DockerStatusStore;
|
||||||
import com.imyeyu.api.modules.system.util.DockerEngineClient;
|
import com.imyeyu.api.modules.system.util.DockerEngineClient;
|
||||||
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.utils.Time;
|
import com.imyeyu.utils.Time;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -15,12 +16,13 @@ import org.springframework.scheduling.support.PeriodicTrigger;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Docker 鐘舵€侀噰闆嗕换鍔?
|
* Docker 容器状态采集任务
|
||||||
*
|
*
|
||||||
* @author Codex
|
* @author Codex
|
||||||
* @since 2026-04-06
|
* @since 2026-04-06
|
||||||
@@ -56,20 +58,28 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
|||||||
try {
|
try {
|
||||||
ArrayNode containers = (ArrayNode) dockerEngineClient.getJson("/containers/json", DockerEngineClient.query("all", "true"));
|
ArrayNode containers = (ArrayNode) dockerEngineClient.getJson("/containers/json", DockerEngineClient.query("all", "true"));
|
||||||
long now = Time.now();
|
long now = Time.now();
|
||||||
synchronized (dockerStatusStore) {
|
Map<String, DockerStatusStore.Container> collectedContainers = new LinkedHashMap<>();
|
||||||
Set<String> activeIds = new HashSet<>();
|
|
||||||
for (JsonNode summary : containers) {
|
for (JsonNode summary : containers) {
|
||||||
try {
|
try {
|
||||||
String containerId = getAsString(summary, "Id");
|
String containerId = getAsString(summary, "Id");
|
||||||
activeIds.add(containerId);
|
DockerStatusStore.Container container = new DockerStatusStore.Container();
|
||||||
DockerStatusStore.Container container = dockerStatusStore.getContainers().computeIfAbsent(containerId, key -> new DockerStatusStore.Container());
|
if (TimiJava.isEmpty(container)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
updateContainerSummary(container, summary);
|
updateContainerSummary(container, summary);
|
||||||
updateContainerInspect(containerId, container);
|
updateContainerInspect(containerId, container);
|
||||||
updateContainerStats(containerId, container, now);
|
updateContainerStats(containerId, container, now);
|
||||||
|
collectedContainers.put(container.getId(), container);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("collect docker container item error", e);
|
log.error("collect docker container item error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
synchronized (dockerStatusStore) {
|
||||||
|
Set<String> activeIds = new HashSet<>(collectedContainers.keySet());
|
||||||
|
for (Map.Entry<String, DockerStatusStore.Container> item : collectedContainers.entrySet()) {
|
||||||
|
DockerStatusStore.Container container = dockerStatusStore.getContainers().computeIfAbsent(item.getKey(), key -> new DockerStatusStore.Container());
|
||||||
|
applyCollectedContainer(container, item.getValue());
|
||||||
|
}
|
||||||
dockerStatusStore.getContainers().entrySet().removeIf(item -> !activeIds.contains(item.getKey()));
|
dockerStatusStore.getContainers().entrySet().removeIf(item -> !activeIds.contains(item.getKey()));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -77,6 +87,39 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyCollectedContainer(DockerStatusStore.Container target, DockerStatusStore.Container source) {
|
||||||
|
target.setId(source.getId());
|
||||||
|
target.setName(source.getName());
|
||||||
|
target.setImage(source.getImage());
|
||||||
|
target.setImageId(source.getImageId());
|
||||||
|
target.setCreatedAt(source.getCreatedAt());
|
||||||
|
target.setState(source.getState());
|
||||||
|
target.setStatus(source.getStatus());
|
||||||
|
target.setHealthStatus(source.getHealthStatus());
|
||||||
|
target.setStartedAt(source.getStartedAt());
|
||||||
|
target.setFinishedAt(source.getFinishedAt());
|
||||||
|
target.setExitCode(source.getExitCode());
|
||||||
|
target.setRestartCount(source.getRestartCount());
|
||||||
|
target.setOomKilled(source.isOomKilled());
|
||||||
|
target.setCpuPercent(source.getCpuPercent());
|
||||||
|
target.setMemoryUsageBytes(source.getMemoryUsageBytes());
|
||||||
|
target.setMemoryLimitBytes(source.getMemoryLimitBytes());
|
||||||
|
target.setMemoryPercent(source.getMemoryPercent());
|
||||||
|
target.setNetworkRxBytes(source.getNetworkRxBytes());
|
||||||
|
target.setNetworkTxBytes(source.getNetworkTxBytes());
|
||||||
|
target.setBlockReadBytes(source.getBlockReadBytes());
|
||||||
|
target.setBlockWriteBytes(source.getBlockWriteBytes());
|
||||||
|
target.setPids(source.getPids());
|
||||||
|
target.setUpdatedAt(source.getUpdatedAt());
|
||||||
|
DockerStatusStore.Point point = source.getHistory().peekLast();
|
||||||
|
if (point != null) {
|
||||||
|
target.getHistory().addLast(point);
|
||||||
|
while (historyLimit < target.getHistory().size()) {
|
||||||
|
target.getHistory().pollFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateContainerSummary(DockerStatusStore.Container container, JsonNode summary) {
|
private void updateContainerSummary(DockerStatusStore.Container container, JsonNode summary) {
|
||||||
container.setId(getAsString(summary, "Id"));
|
container.setId(getAsString(summary, "Id"));
|
||||||
container.setName(trimContainerName(readFirstArrayText(summary, "Names")));
|
container.setName(trimContainerName(readFirstArrayText(summary, "Names")));
|
||||||
@@ -108,8 +151,8 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
|||||||
if (memoryUsageBytes != null && memoryLimitBytes != null && 0 < memoryLimitBytes) {
|
if (memoryUsageBytes != null && memoryLimitBytes != null && 0 < memoryLimitBytes) {
|
||||||
memoryPercent = memoryUsageBytes * 100D / memoryLimitBytes;
|
memoryPercent = memoryUsageBytes * 100D / memoryLimitBytes;
|
||||||
}
|
}
|
||||||
Long networkRxBytes = 0L;
|
long networkRxBytes = 0L;
|
||||||
Long networkTxBytes = 0L;
|
long networkTxBytes = 0L;
|
||||||
JsonNode networks = getAsObject(stats, "networks");
|
JsonNode networks = getAsObject(stats, "networks");
|
||||||
if (networks != null) {
|
if (networks != null) {
|
||||||
for (Map.Entry<String, JsonNode> item : (Iterable<Map.Entry<String, JsonNode>>) networks::fields) {
|
for (Map.Entry<String, JsonNode> item : (Iterable<Map.Entry<String, JsonNode>>) networks::fields) {
|
||||||
@@ -118,8 +161,8 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
|||||||
networkTxBytes += getAsLong(network, "tx_bytes", 0L);
|
networkTxBytes += getAsLong(network, "tx_bytes", 0L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Long blockReadBytes = 0L;
|
long blockReadBytes = 0L;
|
||||||
Long blockWriteBytes = 0L;
|
long blockWriteBytes = 0L;
|
||||||
JsonNode blkioStats = getAsObject(stats, "blkio_stats");
|
JsonNode blkioStats = getAsObject(stats, "blkio_stats");
|
||||||
ArrayNode ioServiceBytes = blkioStats == null ? null : getAsArray(blkioStats, "io_service_bytes_recursive");
|
ArrayNode ioServiceBytes = blkioStats == null ? null : getAsArray(blkioStats, "io_service_bytes_recursive");
|
||||||
if (ioServiceBytes != null) {
|
if (ioServiceBytes != null) {
|
||||||
@@ -134,7 +177,6 @@ public class DockerStatusTask implements SchedulingConfigurer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Integer pids = getNestedInteger(stats, "pids_stats", "current");
|
Integer pids = getNestedInteger(stats, "pids_stats", "current");
|
||||||
|
|
||||||
container.setCpuPercent(cpuPercent);
|
container.setCpuPercent(cpuPercent);
|
||||||
container.setMemoryUsageBytes(memoryUsageBytes);
|
container.setMemoryUsageBytes(memoryUsageBytes);
|
||||||
container.setMemoryLimitBytes(memoryLimitBytes);
|
container.setMemoryLimitBytes(memoryLimitBytes);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class UpsStatusTask implements SchedulingConfigurer {
|
|||||||
private final UpsStatusClient upsStatusClient;
|
private final UpsStatusClient upsStatusClient;
|
||||||
private final UpsStatusStore upsStatusStore;
|
private final UpsStatusStore upsStatusStore;
|
||||||
|
|
||||||
@Value("${ups.collect-enabled:true}")
|
@Value("${ups.collect-enabled:false}")
|
||||||
private boolean collectEnabled;
|
private boolean collectEnabled;
|
||||||
|
|
||||||
@Value("${ups.collect-rate-ms:60000}")
|
@Value("${ups.collect-rate-ms:60000}")
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import java.net.http.HttpResponse;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -73,6 +74,28 @@ public class DockerEngineClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 Docker Engine 当前是否可访问。
|
||||||
|
*
|
||||||
|
* @return 可访问返回 true,不可访问返回 false
|
||||||
|
*/
|
||||||
|
public boolean isAvailable() {
|
||||||
|
if (host.startsWith("unix://")) {
|
||||||
|
String socketPath = host.substring("unix://".length());
|
||||||
|
return Files.exists(Path.of(socketPath));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 Docker Engine 主机配置。
|
||||||
|
*
|
||||||
|
* @return 主机配置字符串
|
||||||
|
*/
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
private String buildRequestPath(String path, Map<String, String> queryParams) {
|
private String buildRequestPath(String path, Map<String, String> queryParams) {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("/");
|
builder.append("/");
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
server:
|
server:
|
||||||
shutdown: graceful
|
shutdown: graceful
|
||||||
|
# 压缩
|
||||||
|
compression:
|
||||||
|
enable: true
|
||||||
|
min-response-size: 10KB
|
||||||
|
|
||||||
# 开发环境语言,激活开发配置时,多语言系统始终使用此语言环境
|
# 开发环境语言,激活开发配置时,多语言系统始终使用此语言环境
|
||||||
dev:
|
dev:
|
||||||
|
|||||||
Reference in New Issue
Block a user