1.33 日志通用查询
This commit is contained in:
parent
e70f6c5d41
commit
5056b133ca
@ -1,21 +1,22 @@
|
||||
package com.qqchen.deploy.backend.deploy.api;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.dto.TeamApplicationDTO;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.BaseLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.LogQueryResponse;
|
||||
import com.qqchen.deploy.backend.deploy.entity.TeamApplication;
|
||||
import com.qqchen.deploy.backend.deploy.query.TeamApplicationQuery;
|
||||
import com.qqchen.deploy.backend.deploy.service.ITeamApplicationService;
|
||||
import com.qqchen.deploy.backend.framework.api.Response;
|
||||
import com.qqchen.deploy.backend.framework.controller.BaseController;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@ -76,5 +77,58 @@ public class TeamApplicationApiController extends BaseController<TeamApplication
|
||||
protected void exportData(HttpServletResponse response, List<TeamApplicationDTO> data) {
|
||||
// TODO: 实现导出功能
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询应用日志
|
||||
* 统一的日志查询接口,支持K8S/Docker/Server三种运行时类型
|
||||
* 根据请求中的runtimeType字段自动选择对应的日志查询策略
|
||||
*
|
||||
* <p>注意:此接口不影响现有的K8s Deployment日志查询接口
|
||||
* (/api/v1/k8s-deployment/{deploymentId}/pods/{podName}/logs)
|
||||
*
|
||||
* <p>请求示例:
|
||||
* <pre>
|
||||
* // K8S日志查询
|
||||
* POST /api/v1/team-applications/123/logs
|
||||
* {
|
||||
* "runtimeType": "K8S",
|
||||
* "podName": "backend-xxx",
|
||||
* "container": "app",
|
||||
* "referenceTimestamp": "newest",
|
||||
* "direction": "next",
|
||||
* "logCount": 500
|
||||
* }
|
||||
*
|
||||
* // Docker日志查询
|
||||
* POST /api/v1/team-applications/123/logs
|
||||
* {
|
||||
* "runtimeType": "DOCKER",
|
||||
* "containerName": "my-container",
|
||||
* "lines": 100,
|
||||
* "since": "1h"
|
||||
* }
|
||||
*
|
||||
* // Server日志查询
|
||||
* POST /api/v1/team-applications/123/logs
|
||||
* {
|
||||
* "runtimeType": "SERVER",
|
||||
* "lines": 100
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@Operation(
|
||||
summary = "查询应用日志",
|
||||
description = "统一的日志查询接口,支持K8S/Docker/Server三种运行时类型。\n\n" +
|
||||
"使用POST请求,请求体中包含runtimeType字段用于区分不同类型的参数。\n\n" +
|
||||
"返回格式统一,前端无需关心运行时类型差异。"
|
||||
)
|
||||
@PostMapping("/{teamAppId}/logs")
|
||||
public Response<LogQueryResponse> queryLogs(
|
||||
@Parameter(description = "团队应用ID", required = true) @PathVariable Long teamAppId,
|
||||
@Parameter(description = "日志查询请求(根据runtimeType自动反序列化为对应的子类)", required = true)
|
||||
@Validated @RequestBody BaseLogQueryRequest request
|
||||
) {
|
||||
return Response.success(teamApplicationService.queryLogs(teamAppId, request));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.qqchen.deploy.backend.deploy.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.enums.BuildTypeEnum;
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@ -91,5 +92,52 @@ public class TeamApplicationDTO extends BaseDTO {
|
||||
|
||||
@Schema(description = "环境名称")
|
||||
private String environmentName;
|
||||
|
||||
// ==================== 运行时配置 ====================
|
||||
|
||||
@Schema(description = "运行时类型", example = "K8S")
|
||||
private RuntimeTypeEnum runtimeType;
|
||||
|
||||
// ==================== K8s运行时配置 ====================
|
||||
|
||||
@Schema(description = "K8s系统ID")
|
||||
private Long k8sSystemId;
|
||||
|
||||
@Schema(description = "K8s系统名称")
|
||||
private String k8sSystemName;
|
||||
|
||||
@Schema(description = "K8s命名空间ID")
|
||||
private Long k8sNamespaceId;
|
||||
|
||||
@Schema(description = "K8s命名空间名称")
|
||||
private String k8sNamespaceName;
|
||||
|
||||
@Schema(description = "K8s Deployment ID")
|
||||
private Long k8sDeploymentId;
|
||||
|
||||
@Schema(description = "K8s Deployment名称")
|
||||
private String k8sDeploymentName;
|
||||
|
||||
// ==================== Docker运行时配置 ====================
|
||||
|
||||
@Schema(description = "Docker服务器ID")
|
||||
private Long dockerServerId;
|
||||
|
||||
@Schema(description = "Docker服务器名称")
|
||||
private String dockerServerName;
|
||||
|
||||
@Schema(description = "Docker容器名称")
|
||||
private String dockerContainerName;
|
||||
|
||||
// ==================== 服务器运行时配置 ====================
|
||||
|
||||
@Schema(description = "服务器ID")
|
||||
private Long serverId;
|
||||
|
||||
@Schema(description = "服务器名称")
|
||||
private String serverName;
|
||||
|
||||
@Schema(description = "日志查询命令(支持占位符)", example = "tail -n {lines} /var/log/app.log")
|
||||
private String logQueryCommand;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
package com.qqchen.deploy.backend.deploy.dto.log;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
|
||||
/**
|
||||
* 日志查询请求基类
|
||||
* 不同运行时类型有不同的查询参数,使用多态设计
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@JsonTypeInfo(
|
||||
use = JsonTypeInfo.Id.NAME,
|
||||
include = JsonTypeInfo.As.PROPERTY,
|
||||
property = "runtimeType"
|
||||
)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = K8sLogQueryRequest.class, name = "K8S"),
|
||||
@JsonSubTypes.Type(value = DockerLogQueryRequest.class, name = "DOCKER"),
|
||||
@JsonSubTypes.Type(value = ServerLogQueryRequest.class, name = "SERVER")
|
||||
})
|
||||
public abstract class BaseLogQueryRequest {
|
||||
|
||||
/**
|
||||
* 获取运行时类型
|
||||
*/
|
||||
public abstract RuntimeTypeEnum getRuntimeType();
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.qqchen.deploy.backend.deploy.dto.log;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* Docker日志查询请求
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DockerLogQueryRequest extends BaseLogQueryRequest {
|
||||
|
||||
/**
|
||||
* 运行时类型(用于Jackson反序列化)
|
||||
*/
|
||||
private final RuntimeTypeEnum runtimeType = RuntimeTypeEnum.DOCKER;
|
||||
|
||||
/**
|
||||
* 容器名称(可选,默认使用TeamApplication.dockerContainerName)
|
||||
*/
|
||||
private String containerName;
|
||||
|
||||
/**
|
||||
* 日志行数(可选,默认100)
|
||||
*/
|
||||
@Positive(message = "日志行数必须大于0")
|
||||
private Integer lines = 100;
|
||||
|
||||
/**
|
||||
* 时间范围(可选)
|
||||
* 例如:1h(1小时)、30m(30分钟)、2d(2天)
|
||||
*/
|
||||
private String since;
|
||||
|
||||
/**
|
||||
* 是否显示时间戳(可选,默认false)
|
||||
*/
|
||||
private Boolean timestamps = false;
|
||||
|
||||
@Override
|
||||
public RuntimeTypeEnum getRuntimeType() {
|
||||
return RuntimeTypeEnum.DOCKER;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.qqchen.deploy.backend.deploy.dto.log;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* K8S日志查询请求
|
||||
* 复用现有K8S日志查询的参数设计
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class K8sLogQueryRequest extends BaseLogQueryRequest {
|
||||
|
||||
/**
|
||||
* 运行时类型(用于Jackson反序列化)
|
||||
*/
|
||||
private final RuntimeTypeEnum runtimeType = RuntimeTypeEnum.K8S;
|
||||
|
||||
/**
|
||||
* Pod名称(必填)
|
||||
*/
|
||||
@NotBlank(message = "Pod名称不能为空")
|
||||
private String podName;
|
||||
|
||||
/**
|
||||
* 容器名称(可选,默认第一个容器)
|
||||
*/
|
||||
private String container;
|
||||
|
||||
/**
|
||||
* 引用点时间戳(可选,默认newest)
|
||||
* 特殊值:
|
||||
* - "newest": 最新的日志行
|
||||
* - "oldest": 最早的日志行
|
||||
* - RFC3339时间戳:具体的时间点
|
||||
*/
|
||||
private String referenceTimestamp = "newest";
|
||||
|
||||
/**
|
||||
* 方向(可选,默认next)
|
||||
* - prev: 向上加载历史日志
|
||||
* - next: 向下加载新日志
|
||||
*/
|
||||
private String direction = "next";
|
||||
|
||||
/**
|
||||
* 每次加载的行数(可选,默认100)
|
||||
*/
|
||||
@Positive(message = "日志行数必须大于0")
|
||||
private Integer logCount = 100;
|
||||
|
||||
@Override
|
||||
public RuntimeTypeEnum getRuntimeType() {
|
||||
return RuntimeTypeEnum.K8S;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.qqchen.deploy.backend.deploy.dto.log;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 统一日志行
|
||||
* 适用于K8S/Docker/Server等所有运行时类型
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class LogLine {
|
||||
|
||||
/**
|
||||
* 日志时间戳(RFC3339格式或其他格式)
|
||||
* 例如:2025-12-16T10:30:00.123456789Z
|
||||
*/
|
||||
private String timestamp;
|
||||
|
||||
/**
|
||||
* 日志内容
|
||||
*/
|
||||
private String content;
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.qqchen.deploy.backend.deploy.dto.log;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 统一日志查询响应
|
||||
* 适用于K8S/Docker/Server等所有运行时类型
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class LogQueryResponse {
|
||||
|
||||
/**
|
||||
* 运行时类型
|
||||
*/
|
||||
private RuntimeTypeEnum runtimeType;
|
||||
|
||||
/**
|
||||
* 日志行列表
|
||||
*/
|
||||
private List<LogLine> logs;
|
||||
|
||||
/**
|
||||
* 是否还有更多日志
|
||||
*/
|
||||
private Boolean hasMore;
|
||||
|
||||
/**
|
||||
* 扩展元数据
|
||||
* 用于存放特定运行时类型的额外信息
|
||||
* 例如K8S的引用点信息:
|
||||
* - referenceForPrevious: K8sLogSelection对象
|
||||
* - referenceForNext: K8sLogSelection对象
|
||||
* - podName: Pod名称
|
||||
* - containerName: 容器名称
|
||||
* - truncated: 是否被截断
|
||||
*/
|
||||
private Map<String, Object> metadata;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.qqchen.deploy.backend.deploy.dto.log;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* Server日志查询请求
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ServerLogQueryRequest extends BaseLogQueryRequest {
|
||||
|
||||
/**
|
||||
* 运行时类型(用于Jackson反序列化)
|
||||
*/
|
||||
private final RuntimeTypeEnum runtimeType = RuntimeTypeEnum.SERVER;
|
||||
|
||||
/**
|
||||
* 日志行数(可选,默认100)
|
||||
* 将作为占位符{lines}替换到logQueryCommand中
|
||||
*/
|
||||
@Positive(message = "日志行数必须大于0")
|
||||
private Integer lines = 100;
|
||||
|
||||
@Override
|
||||
public RuntimeTypeEnum getRuntimeType() {
|
||||
return RuntimeTypeEnum.SERVER;
|
||||
}
|
||||
}
|
||||
@ -108,5 +108,71 @@ public class TeamApplication extends Entity<Long> {
|
||||
*/
|
||||
@Column(name = "workflow_definition_id")
|
||||
private Long workflowDefinitionId;
|
||||
|
||||
// ==================== 运行时配置 ====================
|
||||
|
||||
/**
|
||||
* 运行时类型(K8S-Kubernetes集群,DOCKER-Docker容器,SERVER-传统服务器)
|
||||
*/
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "runtime_type", length = 50)
|
||||
private com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum runtimeType;
|
||||
|
||||
// ==================== K8s运行时配置 ====================
|
||||
|
||||
/**
|
||||
* K8s系统ID(关联sys_external_system,type=K8S)
|
||||
* 仅当 runtimeType=K8S 时使用
|
||||
*/
|
||||
@Column(name = "k8s_system_id")
|
||||
private Long k8sSystemId;
|
||||
|
||||
/**
|
||||
* K8s命名空间ID(关联deploy_k8s_namespace)
|
||||
* 仅当 runtimeType=K8S 时使用
|
||||
*/
|
||||
@Column(name = "k8s_namespace_id")
|
||||
private Long k8sNamespaceId;
|
||||
|
||||
/**
|
||||
* K8s Deployment ID(关联deploy_k8s_deployment)
|
||||
* 仅当 runtimeType=K8S 时使用
|
||||
*/
|
||||
@Column(name = "k8s_deployment_id")
|
||||
private Long k8sDeploymentId;
|
||||
|
||||
// ==================== Docker运行时配置 ====================
|
||||
|
||||
/**
|
||||
* Docker服务器ID(关联sys_server)
|
||||
* 仅当 runtimeType=DOCKER 时使用
|
||||
*/
|
||||
@Column(name = "docker_server_id")
|
||||
private Long dockerServerId;
|
||||
|
||||
/**
|
||||
* Docker容器名称
|
||||
* 仅当 runtimeType=DOCKER 时使用
|
||||
*/
|
||||
@Column(name = "docker_container_name", length = 255)
|
||||
private String dockerContainerName;
|
||||
|
||||
// ==================== 服务器运行时配置 ====================
|
||||
|
||||
/**
|
||||
* 服务器ID(关联sys_server)
|
||||
* 仅当 runtimeType=SERVER 时使用
|
||||
*/
|
||||
@Column(name = "server_id")
|
||||
private Long serverId;
|
||||
|
||||
/**
|
||||
* 日志查询命令(支持占位符)
|
||||
* 例如:tail -n {lines} /var/log/app.log
|
||||
* 例如:supervisorctl tail -n {lines} {appName}
|
||||
* 仅当 runtimeType=SERVER 时使用
|
||||
*/
|
||||
@Column(name = "log_query_command", length = 500)
|
||||
private String logQueryCommand;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
package com.qqchen.deploy.backend.deploy.enums;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 运行时类型枚举
|
||||
* 定义应用的运行环境类型
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-15
|
||||
*/
|
||||
@Getter
|
||||
public enum RuntimeTypeEnum {
|
||||
|
||||
/**
|
||||
* Kubernetes集群
|
||||
*/
|
||||
K8S("K8S", "Kubernetes集群"),
|
||||
|
||||
/**
|
||||
* Docker容器
|
||||
*/
|
||||
DOCKER("DOCKER", "Docker容器"),
|
||||
|
||||
/**
|
||||
* 传统服务器(JAR、脚本等)
|
||||
*/
|
||||
SERVER("SERVER", "传统服务器");
|
||||
|
||||
/**
|
||||
* 枚举代码
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* 枚举描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
RuntimeTypeEnum(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
@JsonCreator
|
||||
public static RuntimeTypeEnum fromCode(String code) {
|
||||
if (code == null) {
|
||||
return null;
|
||||
}
|
||||
for (RuntimeTypeEnum type : RuntimeTypeEnum.values()) {
|
||||
if (type.code.equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("未知的运行时类型: " + code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化为JSON时使用code
|
||||
*/
|
||||
@JsonValue
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@ -2,11 +2,16 @@ package com.qqchen.deploy.backend.deploy.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.converter.TeamApplicationConverter;
|
||||
import com.qqchen.deploy.backend.deploy.dto.TeamApplicationDTO;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.BaseLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.LogQueryResponse;
|
||||
import com.qqchen.deploy.backend.deploy.entity.Application;
|
||||
import com.qqchen.deploy.backend.deploy.entity.DeployRecord;
|
||||
import com.qqchen.deploy.backend.deploy.entity.Environment;
|
||||
import com.qqchen.deploy.backend.deploy.entity.Team;
|
||||
import com.qqchen.deploy.backend.deploy.entity.TeamApplication;
|
||||
import com.qqchen.deploy.backend.deploy.entity.K8sNamespace;
|
||||
import com.qqchen.deploy.backend.deploy.entity.K8sDeployment;
|
||||
import com.qqchen.deploy.backend.deploy.entity.Server;
|
||||
import com.qqchen.deploy.backend.deploy.enums.BuildTypeEnum;
|
||||
import com.qqchen.deploy.backend.deploy.query.TeamApplicationQuery;
|
||||
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
|
||||
@ -18,7 +23,12 @@ import com.qqchen.deploy.backend.deploy.repository.IDeployRecordRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IEnvironmentRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.ITeamApplicationRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.ITeamRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IK8sNamespaceRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IK8sDeploymentRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IServerRepository;
|
||||
import com.qqchen.deploy.backend.deploy.service.ITeamApplicationService;
|
||||
import com.qqchen.deploy.backend.deploy.strategy.ILogQueryStrategy;
|
||||
import com.qqchen.deploy.backend.deploy.strategy.LogQueryStrategyFactory;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
@ -65,12 +75,48 @@ public class TeamApplicationServiceImpl extends BaseServiceImpl<TeamApplication,
|
||||
@Resource
|
||||
private TeamApplicationConverter teamApplicationConverter;
|
||||
|
||||
@Resource
|
||||
private LogQueryStrategyFactory logQueryStrategyFactory;
|
||||
|
||||
@Resource
|
||||
private IK8sNamespaceRepository k8sNamespaceRepository;
|
||||
|
||||
@Resource
|
||||
private IK8sDeploymentRepository k8sDeploymentRepository;
|
||||
|
||||
@Resource
|
||||
private IServerRepository serverRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public TeamApplicationDTO create(TeamApplicationDTO dto) {
|
||||
return super.create(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogQueryResponse queryLogs(Long teamAppId, BaseLogQueryRequest request) {
|
||||
log.info("查询应用日志,teamAppId: {}, runtimeType: {}", teamAppId, request.getRuntimeType());
|
||||
|
||||
// 1. 查询团队应用
|
||||
TeamApplication teamApp = teamApplicationRepository.findById(teamAppId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.TEAM_APPLICATION_NOT_FOUND));
|
||||
|
||||
// 2. 校验运行时类型是否匹配
|
||||
if (teamApp.getRuntimeType() != request.getRuntimeType()) {
|
||||
throw new BusinessException(ResponseCode.TEAM_APP_RUNTIME_TYPE_MISMATCH,
|
||||
new Object[]{teamApp.getRuntimeType(), request.getRuntimeType()});
|
||||
}
|
||||
|
||||
// 3. 获取对应的日志查询策略
|
||||
ILogQueryStrategy strategy = logQueryStrategyFactory.getStrategy(request.getRuntimeType());
|
||||
|
||||
// 4. 执行日志查询
|
||||
LogQueryResponse response = strategy.queryLogs(teamApp, request);
|
||||
|
||||
log.info("日志查询完成,返回 {} 条日志", response.getLogs() != null ? response.getLogs().size() : 0);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写父类的唯一性约束校验方法
|
||||
* <p>校验规则:
|
||||
@ -172,6 +218,28 @@ public class TeamApplicationServiceImpl extends BaseServiceImpl<TeamApplication,
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 收集K8S相关ID
|
||||
Set<Long> k8sNamespaceIds = teamApps.stream()
|
||||
.map(TeamApplicationDTO::getK8sNamespaceId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<Long> k8sDeploymentIds = teamApps.stream()
|
||||
.map(TeamApplicationDTO::getK8sDeploymentId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 收集Docker和Server相关ID
|
||||
Set<Long> dockerServerIds = teamApps.stream()
|
||||
.map(TeamApplicationDTO::getDockerServerId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<Long> serverIds = teamApps.stream()
|
||||
.map(TeamApplicationDTO::getServerId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 2. 批量查询团队信息
|
||||
Map<Long, Team> teamMap = new HashMap<>();
|
||||
if (!teamIds.isEmpty()) {
|
||||
@ -248,7 +316,34 @@ public class TeamApplicationServiceImpl extends BaseServiceImpl<TeamApplication,
|
||||
);
|
||||
}
|
||||
|
||||
// 11. 填充扩展字段
|
||||
// 11. 批量查询K8S Namespace信息
|
||||
Map<Long, K8sNamespace> k8sNamespaceMap = new HashMap<>();
|
||||
if (!k8sNamespaceIds.isEmpty()) {
|
||||
k8sNamespaceRepository.findAllById(k8sNamespaceIds).forEach(namespace ->
|
||||
k8sNamespaceMap.put(namespace.getId(), namespace)
|
||||
);
|
||||
}
|
||||
|
||||
// 12. 批量查询K8S Deployment信息
|
||||
Map<Long, K8sDeployment> k8sDeploymentMap = new HashMap<>();
|
||||
if (!k8sDeploymentIds.isEmpty()) {
|
||||
k8sDeploymentRepository.findAllById(k8sDeploymentIds).forEach(deployment ->
|
||||
k8sDeploymentMap.put(deployment.getId(), deployment)
|
||||
);
|
||||
}
|
||||
|
||||
// 13. 批量查询Server信息(Docker和Server共用)
|
||||
Map<Long, Server> serverMap = new HashMap<>();
|
||||
Set<Long> allServerIds = new HashSet<>();
|
||||
allServerIds.addAll(dockerServerIds);
|
||||
allServerIds.addAll(serverIds);
|
||||
if (!allServerIds.isEmpty()) {
|
||||
serverRepository.findAllById(allServerIds).forEach(server ->
|
||||
serverMap.put(server.getId(), server)
|
||||
);
|
||||
}
|
||||
|
||||
// 14. 填充扩展字段
|
||||
teamApps.forEach(teamApp -> {
|
||||
// 填充团队名称
|
||||
if (teamApp.getTeamId() != null) {
|
||||
@ -324,6 +419,38 @@ public class TeamApplicationServiceImpl extends BaseServiceImpl<TeamApplication,
|
||||
teamApp.setTargetGitProjectName(project.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// 填充K8S Namespace名称
|
||||
if (teamApp.getK8sNamespaceId() != null) {
|
||||
K8sNamespace namespace = k8sNamespaceMap.get(teamApp.getK8sNamespaceId());
|
||||
if (namespace != null) {
|
||||
teamApp.setK8sNamespaceName(namespace.getNamespaceName());
|
||||
}
|
||||
}
|
||||
|
||||
// 填充K8S Deployment名称
|
||||
if (teamApp.getK8sDeploymentId() != null) {
|
||||
K8sDeployment deployment = k8sDeploymentMap.get(teamApp.getK8sDeploymentId());
|
||||
if (deployment != null) {
|
||||
teamApp.setK8sDeploymentName(deployment.getDeploymentName());
|
||||
}
|
||||
}
|
||||
|
||||
// 填充Docker Server名称
|
||||
if (teamApp.getDockerServerId() != null) {
|
||||
Server server = serverMap.get(teamApp.getDockerServerId());
|
||||
if (server != null) {
|
||||
teamApp.setDockerServerName(server.getServerName());
|
||||
}
|
||||
}
|
||||
|
||||
// 填充Server名称
|
||||
if (teamApp.getServerId() != null) {
|
||||
Server server = serverMap.get(teamApp.getServerId());
|
||||
if (server != null) {
|
||||
teamApp.setServerName(server.getServerName());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
package com.qqchen.deploy.backend.deploy.strategy;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.BaseLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.LogQueryResponse;
|
||||
import com.qqchen.deploy.backend.deploy.entity.TeamApplication;
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
|
||||
/**
|
||||
* 日志查询策略接口
|
||||
* 使用策略模式支持不同运行时类型的日志查询
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
public interface ILogQueryStrategy {
|
||||
|
||||
/**
|
||||
* 支持的运行时类型
|
||||
*
|
||||
* @return 运行时类型枚举
|
||||
*/
|
||||
RuntimeTypeEnum supportedType();
|
||||
|
||||
/**
|
||||
* 查询日志
|
||||
*
|
||||
* @param teamApp 团队应用实体
|
||||
* @param request 日志查询请求
|
||||
* @return 统一的日志查询响应
|
||||
*/
|
||||
LogQueryResponse queryLogs(TeamApplication teamApp, BaseLogQueryRequest request);
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.qqchen.deploy.backend.deploy.strategy;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 日志查询策略工厂
|
||||
* 根据运行时类型选择对应的策略实现
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LogQueryStrategyFactory {
|
||||
|
||||
@Resource
|
||||
private List<ILogQueryStrategy> strategies;
|
||||
|
||||
private Map<RuntimeTypeEnum, ILogQueryStrategy> strategyMap;
|
||||
|
||||
/**
|
||||
* 初始化策略映射
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
strategyMap = new HashMap<>();
|
||||
for (ILogQueryStrategy strategy : strategies) {
|
||||
strategyMap.put(strategy.supportedType(), strategy);
|
||||
log.info("注册日志查询策略: {} -> {}",
|
||||
strategy.supportedType(), strategy.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日志查询策略
|
||||
*
|
||||
* @param runtimeType 运行时类型
|
||||
* @return 对应的策略实现
|
||||
* @throws BusinessException 如果找不到对应的策略
|
||||
*/
|
||||
public ILogQueryStrategy getStrategy(RuntimeTypeEnum runtimeType) {
|
||||
ILogQueryStrategy strategy = strategyMap.get(runtimeType);
|
||||
if (strategy == null) {
|
||||
throw new BusinessException(ResponseCode.LOG_QUERY_STRATEGY_NOT_FOUND,
|
||||
new Object[]{runtimeType});
|
||||
}
|
||||
return strategy;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package com.qqchen.deploy.backend.deploy.strategy.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.BaseLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.DockerLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.LogQueryResponse;
|
||||
import com.qqchen.deploy.backend.deploy.entity.TeamApplication;
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import com.qqchen.deploy.backend.deploy.strategy.ILogQueryStrategy;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Docker日志查询策略(骨架实现)
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DockerLogQueryStrategy implements ILogQueryStrategy {
|
||||
|
||||
@Override
|
||||
public RuntimeTypeEnum supportedType() {
|
||||
return RuntimeTypeEnum.DOCKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogQueryResponse queryLogs(TeamApplication teamApp, BaseLogQueryRequest request) {
|
||||
// 类型转换
|
||||
DockerLogQueryRequest dockerRequest = (DockerLogQueryRequest) request;
|
||||
|
||||
// 校验Docker配置
|
||||
validateDockerConfig(teamApp);
|
||||
|
||||
// TODO: 实现Docker日志查询逻辑
|
||||
// 1. 获取Docker服务器连接信息
|
||||
// 2. 执行docker logs命令
|
||||
// 3. 解析日志输出
|
||||
// 4. 转换为统一格式
|
||||
|
||||
throw new BusinessException(ResponseCode.FEATURE_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验Docker配置是否完整
|
||||
*/
|
||||
private void validateDockerConfig(TeamApplication teamApp) {
|
||||
if (teamApp.getDockerServerId() == null) {
|
||||
throw new BusinessException(ResponseCode.TEAM_APP_DOCKER_CONFIG_INCOMPLETE);
|
||||
}
|
||||
if (teamApp.getDockerContainerName() == null || teamApp.getDockerContainerName().isBlank()) {
|
||||
throw new BusinessException(ResponseCode.TEAM_APP_DOCKER_CONFIG_INCOMPLETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
package com.qqchen.deploy.backend.deploy.strategy.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.dto.K8sLogLine;
|
||||
import com.qqchen.deploy.backend.deploy.dto.K8sPodLogsResponse;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.BaseLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.K8sLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.LogLine;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.LogQueryResponse;
|
||||
import com.qqchen.deploy.backend.deploy.entity.TeamApplication;
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import com.qqchen.deploy.backend.deploy.service.IK8sPodService;
|
||||
import com.qqchen.deploy.backend.deploy.strategy.ILogQueryStrategy;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* K8S日志查询策略
|
||||
* 复用现有的IK8sPodService实现
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class K8sLogQueryStrategy implements ILogQueryStrategy {
|
||||
|
||||
@Resource
|
||||
private IK8sPodService k8sPodService;
|
||||
|
||||
@Override
|
||||
public RuntimeTypeEnum supportedType() {
|
||||
return RuntimeTypeEnum.K8S;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogQueryResponse queryLogs(TeamApplication teamApp, BaseLogQueryRequest request) {
|
||||
// 类型转换
|
||||
K8sLogQueryRequest k8sRequest = (K8sLogQueryRequest) request;
|
||||
|
||||
// 校验K8S配置
|
||||
validateK8sConfig(teamApp);
|
||||
|
||||
// 直接使用K8S Deployment ID
|
||||
Long deploymentId = teamApp.getK8sDeploymentId();
|
||||
|
||||
// 调用现有的K8S日志查询服务
|
||||
K8sPodLogsResponse k8sResponse = k8sPodService.getPodLogsWithReference(
|
||||
deploymentId,
|
||||
k8sRequest.getPodName(),
|
||||
k8sRequest.getContainer(),
|
||||
k8sRequest.getReferenceTimestamp(),
|
||||
k8sRequest.getDirection(),
|
||||
k8sRequest.getLogCount()
|
||||
);
|
||||
|
||||
// 转换为统一格式
|
||||
return convertToLogQueryResponse(k8sResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验K8S配置是否完整
|
||||
*/
|
||||
private void validateK8sConfig(TeamApplication teamApp) {
|
||||
if (teamApp.getK8sSystemId() == null) {
|
||||
throw new BusinessException(ResponseCode.TEAM_APP_K8S_CONFIG_INCOMPLETE);
|
||||
}
|
||||
if (teamApp.getK8sNamespaceId() == null) {
|
||||
throw new BusinessException(ResponseCode.TEAM_APP_K8S_CONFIG_INCOMPLETE);
|
||||
}
|
||||
if (teamApp.getK8sDeploymentId() == null) {
|
||||
throw new BusinessException(ResponseCode.TEAM_APP_K8S_CONFIG_INCOMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将K8sPodLogsResponse转换为统一的LogQueryResponse
|
||||
*/
|
||||
private LogQueryResponse convertToLogQueryResponse(K8sPodLogsResponse k8sResponse) {
|
||||
// 转换日志行
|
||||
List<LogLine> logs = k8sResponse.getLogs().stream()
|
||||
.map(this::convertLogLine)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 构建元数据
|
||||
Map<String, Object> metadata = new HashMap<>();
|
||||
metadata.put("podName", k8sResponse.getPodName());
|
||||
metadata.put("containerName", k8sResponse.getContainerName());
|
||||
metadata.put("referenceForPrevious", k8sResponse.getReferenceForPrevious());
|
||||
metadata.put("referenceForNext", k8sResponse.getReferenceForNext());
|
||||
metadata.put("truncated", k8sResponse.getTruncated());
|
||||
|
||||
// 构建响应
|
||||
return LogQueryResponse.builder()
|
||||
.runtimeType(RuntimeTypeEnum.K8S)
|
||||
.logs(logs)
|
||||
.hasMore(!Boolean.TRUE.equals(k8sResponse.getTruncated()))
|
||||
.metadata(metadata)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换单个日志行
|
||||
*/
|
||||
private LogLine convertLogLine(K8sLogLine k8sLogLine) {
|
||||
return new LogLine(k8sLogLine.getTimestamp(), k8sLogLine.getContent());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.qqchen.deploy.backend.deploy.strategy.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.BaseLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.LogQueryResponse;
|
||||
import com.qqchen.deploy.backend.deploy.dto.log.ServerLogQueryRequest;
|
||||
import com.qqchen.deploy.backend.deploy.entity.TeamApplication;
|
||||
import com.qqchen.deploy.backend.deploy.enums.RuntimeTypeEnum;
|
||||
import com.qqchen.deploy.backend.deploy.strategy.ILogQueryStrategy;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Server日志查询策略(骨架实现)
|
||||
* TODO: 待后续实现时注入ISSHCommandService
|
||||
*
|
||||
* @author qqchen
|
||||
* @since 2025-12-16
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ServerLogQueryStrategy implements ILogQueryStrategy {
|
||||
|
||||
@Override
|
||||
public RuntimeTypeEnum supportedType() {
|
||||
return RuntimeTypeEnum.SERVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogQueryResponse queryLogs(TeamApplication teamApp, BaseLogQueryRequest request) {
|
||||
// 类型转换
|
||||
ServerLogQueryRequest serverRequest = (ServerLogQueryRequest) request;
|
||||
|
||||
// 校验Server配置
|
||||
validateServerConfig(teamApp);
|
||||
|
||||
// TODO: 实现Server日志查询逻辑
|
||||
// 1. 获取服务器连接信息
|
||||
// 2. 替换logQueryCommand中的占位符(如{lines})
|
||||
// 3. 通过SSH执行命令
|
||||
// 4. 解析命令输出
|
||||
// 5. 转换为统一格式
|
||||
|
||||
throw new BusinessException(ResponseCode.FEATURE_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验Server配置是否完整
|
||||
*/
|
||||
private void validateServerConfig(TeamApplication teamApp) {
|
||||
if (teamApp.getServerId() == null) {
|
||||
throw new BusinessException(ResponseCode.TEAM_APP_SERVER_CONFIG_INCOMPLETE);
|
||||
}
|
||||
if (teamApp.getLogQueryCommand() == null || teamApp.getLogQueryCommand().isBlank()) {
|
||||
throw new BusinessException(ResponseCode.TEAM_APP_SERVER_CONFIG_INCOMPLETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -226,6 +226,14 @@ public enum ResponseCode {
|
||||
TEAM_APPLICATION_ALREADY_EXISTS(2928, "team.application.already.exists"),
|
||||
TEAM_CONFIG_NOT_FOUND(2929, "team.config.not.found"),
|
||||
TEAM_APPLICATION_DEPLOY_JOB_EXISTS(2930, "team.application.deploy.job.exists"),
|
||||
TEAM_APPLICATION_RUNTIME_TYPE_NOT_CONFIGURED(2931, "team.application.runtime.type.not.configured"),
|
||||
TEAM_APPLICATION_LOG_QUERY_STRATEGY_NOT_FOUND(2932, "team.application.log.query.strategy.not.found"),
|
||||
TEAM_APP_RUNTIME_TYPE_MISMATCH(2933, "team.application.runtime.type.mismatch"),
|
||||
TEAM_APP_K8S_CONFIG_INCOMPLETE(2934, "team.application.k8s.config.incomplete"),
|
||||
TEAM_APP_DOCKER_CONFIG_INCOMPLETE(2935, "team.application.docker.config.incomplete"),
|
||||
TEAM_APP_SERVER_CONFIG_INCOMPLETE(2936, "team.application.server.config.incomplete"),
|
||||
LOG_QUERY_STRATEGY_NOT_FOUND(2937, "log.query.strategy.not.found"),
|
||||
FEATURE_NOT_IMPLEMENTED(2938, "feature.not.implemented"),
|
||||
|
||||
// 服务器管理相关错误码 (2950-2969)
|
||||
SERVER_NOT_FOUND(2950, "server.not.found"),
|
||||
@ -289,7 +297,13 @@ public enum ResponseCode {
|
||||
K8S_DEPLOYMENT_SYNC_FAILED(3233, "k8s.deployment.sync.failed"),
|
||||
K8S_POD_NOT_FOUND(3234, "k8s.pod.not.found"),
|
||||
K8S_RESOURCE_NOT_FOUND(3235, "k8s.resource.not.found"),
|
||||
K8S_OPERATION_FAILED(3236, "k8s.operation.failed");
|
||||
K8S_OPERATION_FAILED(3236, "k8s.operation.failed"),
|
||||
|
||||
// Docker集成错误码 (3240-3259)
|
||||
DOCKER_LOG_QUERY_NOT_IMPLEMENTED(3240, "docker.log.query.not.implemented"),
|
||||
|
||||
// 服务器日志查询错误码 (3260-3279)
|
||||
SERVER_LOG_QUERY_NOT_IMPLEMENTED(3260, "server.log.query.not.implemented");
|
||||
|
||||
private final int code;
|
||||
private final String messageKey; // 国际化消息key
|
||||
|
||||
@ -825,6 +825,22 @@ CREATE TABLE deploy_team_application
|
||||
deploy_system_id BIGINT NULL COMMENT '部署系统ID(关联sys_external_system,type=JENKINS),仅当build_type=JENKINS时使用',
|
||||
deploy_job VARCHAR(100) NULL COMMENT '部署任务名称(Jenkins Job名称),仅当build_type=JENKINS时使用',
|
||||
workflow_definition_id BIGINT NULL COMMENT '工作流定义ID(关联workflow_definition)',
|
||||
|
||||
-- 运行时配置
|
||||
runtime_type VARCHAR(50) NULL COMMENT '运行时类型(K8S-Kubernetes集群,DOCKER-Docker容器,SERVER-传统服务器)',
|
||||
|
||||
-- K8s运行时配置
|
||||
k8s_system_id BIGINT NULL COMMENT 'K8s系统ID(关联sys_external_system,type=K8S),仅当runtime_type=K8S时使用',
|
||||
k8s_namespace_id BIGINT NULL COMMENT 'K8s命名空间ID(关联deploy_k8s_namespace),仅当runtime_type=K8S时使用',
|
||||
k8s_deployment_id BIGINT NULL COMMENT 'K8s Deployment ID(关联deploy_k8s_deployment),仅当runtime_type=K8S时使用',
|
||||
|
||||
-- Docker运行时配置
|
||||
docker_server_id BIGINT NULL COMMENT 'Docker服务器ID(关联sys_server),仅当runtime_type=DOCKER时使用',
|
||||
docker_container_name VARCHAR(255) NULL COMMENT 'Docker容器名称,仅当runtime_type=DOCKER时使用',
|
||||
|
||||
-- 服务器运行时配置
|
||||
server_id BIGINT NULL COMMENT '服务器ID(关联sys_server),仅当runtime_type=SERVER时使用',
|
||||
log_query_command VARCHAR(500) NULL COMMENT '日志查询命令(支持占位符,如tail -n {lines} /var/log/app.log),仅当runtime_type=SERVER时使用',
|
||||
|
||||
UNIQUE INDEX uk_team_app_env (team_id, application_id, environment_id),
|
||||
INDEX idx_team (team_id),
|
||||
@ -836,6 +852,11 @@ CREATE TABLE deploy_team_application
|
||||
INDEX idx_deploy_job (deploy_job),
|
||||
INDEX idx_workflow_definition (workflow_definition_id),
|
||||
INDEX idx_target_git_system (target_git_system_id),
|
||||
INDEX idx_runtime_type (runtime_type),
|
||||
INDEX idx_k8s_system (k8s_system_id),
|
||||
INDEX idx_k8s_namespace (k8s_namespace_id),
|
||||
INDEX idx_docker_server (docker_server_id),
|
||||
INDEX idx_server (server_id),
|
||||
CONSTRAINT fk_team_app_team FOREIGN KEY (team_id) REFERENCES deploy_team (id),
|
||||
CONSTRAINT fk_team_app_application FOREIGN KEY (application_id) REFERENCES deploy_application (id),
|
||||
CONSTRAINT fk_team_app_target_git_system FOREIGN KEY (target_git_system_id) REFERENCES sys_external_system (id)
|
||||
|
||||
@ -231,6 +231,14 @@ jenkins.response.parse.error=Jenkins response parse error: {0}
|
||||
# Team Application Related (2920-2939)
|
||||
team.application.already.exists=Application already configured for this environment
|
||||
team.application.deploy.job.exists=This Jenkins Job is already used by another application in this environment, please check the configuration
|
||||
team.application.runtime.type.not.configured=Application runtime type not configured, please contact administrator to configure runtime type (K8S/DOCKER/SERVER)
|
||||
team.application.log.query.strategy.not.found=Log query strategy not found for runtime type, please contact administrator to check system configuration
|
||||
team.application.runtime.type.mismatch=Team application runtime type does not match request type
|
||||
team.application.k8s.config.incomplete=K8S configuration incomplete, please check K8S system ID, namespace ID and deployment name
|
||||
team.application.docker.config.incomplete=Docker configuration incomplete, please check Docker server ID and container name
|
||||
team.application.server.config.incomplete=Server configuration incomplete, please check server ID and log query command
|
||||
log.query.strategy.not.found=Log query strategy not found for runtime type
|
||||
feature.not.implemented=Feature not implemented yet
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
# K8S Integration Related - 3220-3239
|
||||
@ -263,3 +271,9 @@ k8s.deployment.sync.failed=K8S deployment synchronization failed, please check c
|
||||
|
||||
# K8S Operation Errors
|
||||
k8s.operation.failed=K8S operation failed, please try again later
|
||||
|
||||
# Docker Integration Errors
|
||||
docker.log.query.not.implemented=Docker log query feature not implemented yet, please contact administrator
|
||||
|
||||
# Server Log Query Errors
|
||||
server.log.query.not.implemented=Server log query feature not implemented yet, please contact administrator
|
||||
|
||||
@ -231,6 +231,14 @@ jenkins.response.parse.error=Jenkins响应解析失败:{0}
|
||||
# 团队应用相关 (2920-2939)
|
||||
team.application.already.exists=该应用已配置到此环境
|
||||
team.application.deploy.job.exists=该环境下已有其他应用使用此 Jenkins Job,请检查配置
|
||||
team.application.runtime.type.not.configured=应用运行时类型未配置,请联系管理员配置运行时类型(K8S/DOCKER/SERVER)
|
||||
team.application.log.query.strategy.not.found=未找到运行时类型对应的日志查询策略,请联系管理员检查系统配置
|
||||
team.application.runtime.type.mismatch=团队应用的运行时类型与请求类型不匹配
|
||||
team.application.k8s.config.incomplete=K8S配置不完整,请检查K8S系统ID、命名空间ID和Deployment名称
|
||||
team.application.docker.config.incomplete=Docker配置不完整,请检查Docker服务器ID和容器名称
|
||||
team.application.server.config.incomplete=Server配置不完整,请检查服务器ID和日志查询命令
|
||||
log.query.strategy.not.found=未找到对应运行时类型的日志查询策略
|
||||
feature.not.implemented=功能待实现
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
# K8S集成相关 (K8S Integration) - 3220-3239
|
||||
@ -263,3 +271,9 @@ k8s.deployment.sync.failed=K8S Deployment同步失败,请检查集群配置和
|
||||
|
||||
# K8S操作错误
|
||||
k8s.operation.failed=K8S操作失败,请稍后重试
|
||||
|
||||
# Docker集成错误
|
||||
docker.log.query.not.implemented=Docker日志查询功能待实现,请联系管理员
|
||||
|
||||
# 服务器日志查询错误
|
||||
server.log.query.not.implemented=服务器日志查询功能待实现,请联系管理员
|
||||
|
||||
Loading…
Reference in New Issue
Block a user