장애·지연 구분 및 집계 개선:
- 지연 유형 로직 및 UI/스타일 업데이트 - JPQL 조회와 공개 조건 로직 전면 개정
This commit is contained in:
+39
-24
@@ -15,31 +15,52 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 개발자포탈 API Status 화면 전용 조회. 읽기 전용이며 공개 조건(공지 게시 + 초안 아님)을 항상 적용한다.
|
||||
* 개발자포탈 API Status 화면 전용 조회. 읽기 전용이며 공개 조건을 항상 적용한다.
|
||||
*
|
||||
* <p>PTL_NOTICE 와의 조인은 두 가지 역할을 한다.
|
||||
* (1) 관리자가 미게시(USE_YN='N')한 장애/점검을 숨긴다.
|
||||
* (2) 공지가 삭제된 고아 장애 행을 자연히 제외한다 (물리 FK 없음 - ADR-F10).</p>
|
||||
* <p>공개 조건({@link #VISIBLE})은 두 갈래다.
|
||||
* <ul>
|
||||
* <li>공지가 붙은 이슈(장애·점검) - 그 공지가 게시(USE_YN='Y')되어 있어야 한다.
|
||||
* 공지가 삭제된 고아 행도 이 조건에서 자연히 빠진다 (물리 FK 없음 - ADR-F10).</li>
|
||||
* <li>공지가 없는 이슈(지연) - 자동 탐지 전용이라 검수할 공지가 없다.
|
||||
* 초안(DRAFT_YN='Y')만 아니면 노출한다.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>공지 조건을 EXISTS 로 쓰는 이유: 예전처럼 {@code FROM ... , PortalNotice n} 으로 조인하면
|
||||
* NOTICE_ID 가 없는 지연 이슈가 행 자체에서 사라진다.</p>
|
||||
*/
|
||||
public interface ApiStatusIncidentQueryRepository extends Repository<DjbApistatusIncident, Long> {
|
||||
|
||||
String VISIBLE = " i.noticeId = n.id AND n.useYn = 'Y' AND i.draftYn = 'N' ";
|
||||
String VISIBLE = " i.draftYn = 'N'"
|
||||
+ " AND (i.noticeId IS NULL"
|
||||
+ " OR EXISTS (SELECT 1 FROM PortalNotice n"
|
||||
+ " WHERE n.id = i.noticeId AND n.useYn = 'Y')) ";
|
||||
|
||||
/** 종결 판정이 STATE 로 이뤄지는 종류 (장애·지연). JPQL 리터럴로 써야 해서 FQCN 을 쓴다 */
|
||||
String KIND_INCIDENT = "com.eactive.apim.portal.djb.apistatus.incident.entity.IncidentKind.INCIDENT";
|
||||
String KIND_DELAY = "com.eactive.apim.portal.djb.apistatus.incident.entity.IncidentKind.DELAY";
|
||||
String KIND_MAINTENANCE = "com.eactive.apim.portal.djb.apistatus.incident.entity.IncidentKind.MAINTENANCE";
|
||||
|
||||
/** 종결 조건 - 장애·지연은 STATE 로, 점검은 종료 시각 경과로 판정한다 */
|
||||
String CLOSED_CONDITION = " ((i.kind IN (" + KIND_INCIDENT + ", " + KIND_DELAY + ")"
|
||||
+ " AND i.state IN :closedStates)"
|
||||
+ " OR (i.kind = " + KIND_MAINTENANCE
|
||||
+ " AND i.endAt IS NOT NULL AND i.endAt < :now)) ";
|
||||
|
||||
/**
|
||||
* 진행 중 장애 (P3)
|
||||
* 진행 중 이슈 (P3). 장애와 지연을 함께 본다.
|
||||
*/
|
||||
@Query("SELECT i FROM DjbApistatusIncident i, PortalNotice n"
|
||||
@Query("SELECT i FROM DjbApistatusIncident i"
|
||||
+ " WHERE " + VISIBLE
|
||||
+ " AND i.kind = :kind"
|
||||
+ " AND i.kind IN :kinds"
|
||||
+ " AND i.state NOT IN :closedStates"
|
||||
+ " ORDER BY i.startedAt DESC")
|
||||
List<DjbApistatusIncident> findVisibleOpenIncidents(@Param("kind") IncidentKind kind,
|
||||
List<DjbApistatusIncident> findVisibleOpenIncidents(@Param("kinds") Collection<IncidentKind> kinds,
|
||||
@Param("closedStates") Collection<IncidentState> closedStates);
|
||||
|
||||
/**
|
||||
* 예정/진행 중 점검 (P5). 종료 시각이 없거나 아직 지나지 않은 점검.
|
||||
*/
|
||||
@Query("SELECT i FROM DjbApistatusIncident i, PortalNotice n"
|
||||
@Query("SELECT i FROM DjbApistatusIncident i"
|
||||
+ " WHERE " + VISIBLE
|
||||
+ " AND i.kind = :kind"
|
||||
+ " AND (i.endAt IS NULL OR i.endAt >= :now)"
|
||||
@@ -48,21 +69,15 @@ public interface ApiStatusIncidentQueryRepository extends Repository<DjbApistatu
|
||||
@Param("now") LocalDateTime now);
|
||||
|
||||
/**
|
||||
* 종결된 이슈 (P6). 장애는 종결 상태, 점검은 종료 시각 경과.
|
||||
* 종결된 이슈 (P6). 장애·지연은 종결 상태, 점검은 종료 시각 경과.
|
||||
*/
|
||||
@Query(value = "SELECT i FROM DjbApistatusIncident i, PortalNotice n"
|
||||
@Query(value = "SELECT i FROM DjbApistatusIncident i"
|
||||
+ " WHERE " + VISIBLE
|
||||
+ " AND ((i.kind = com.eactive.apim.portal.djb.apistatus.incident.entity.IncidentKind.INCIDENT"
|
||||
+ " AND i.state IN :closedStates)"
|
||||
+ " OR (i.kind = com.eactive.apim.portal.djb.apistatus.incident.entity.IncidentKind.MAINTENANCE"
|
||||
+ " AND i.endAt IS NOT NULL AND i.endAt < :now))"
|
||||
+ " AND " + CLOSED_CONDITION
|
||||
+ " ORDER BY i.startedAt DESC",
|
||||
countQuery = "SELECT COUNT(i) FROM DjbApistatusIncident i, PortalNotice n"
|
||||
countQuery = "SELECT COUNT(i) FROM DjbApistatusIncident i"
|
||||
+ " WHERE " + VISIBLE
|
||||
+ " AND ((i.kind = com.eactive.apim.portal.djb.apistatus.incident.entity.IncidentKind.INCIDENT"
|
||||
+ " AND i.state IN :closedStates)"
|
||||
+ " OR (i.kind = com.eactive.apim.portal.djb.apistatus.incident.entity.IncidentKind.MAINTENANCE"
|
||||
+ " AND i.endAt IS NOT NULL AND i.endAt < :now))")
|
||||
+ " AND " + CLOSED_CONDITION)
|
||||
Page<DjbApistatusIncident> findVisibleClosedIssues(@Param("closedStates") Collection<IncidentState> closedStates,
|
||||
@Param("now") LocalDateTime now,
|
||||
Pageable pageable);
|
||||
@@ -71,7 +86,7 @@ public interface ApiStatusIncidentQueryRepository extends Repository<DjbApistatu
|
||||
* 기간과 겹치는 모든 이슈 (P2 가동률 집계, P9 일자 인덱스, P10 목록).
|
||||
* 진행 중(END_AT IS NULL) 이슈도 포함한다.
|
||||
*/
|
||||
@Query("SELECT i FROM DjbApistatusIncident i, PortalNotice n"
|
||||
@Query("SELECT i FROM DjbApistatusIncident i"
|
||||
+ " WHERE " + VISIBLE
|
||||
+ " AND i.startedAt < :to"
|
||||
+ " AND (i.endAt IS NULL OR i.endAt >= :from)"
|
||||
@@ -82,7 +97,7 @@ public interface ApiStatusIncidentQueryRepository extends Repository<DjbApistatu
|
||||
/**
|
||||
* 기간과 겹치고 특정 API 에 영향을 준 이슈 (P9/P10 의 apiId 필터).
|
||||
*/
|
||||
@Query("SELECT DISTINCT i FROM DjbApistatusIncident i, PortalNotice n, DjbApistatusIncidentApi a"
|
||||
@Query("SELECT DISTINCT i FROM DjbApistatusIncident i, DjbApistatusIncidentApi a"
|
||||
+ " WHERE " + VISIBLE
|
||||
+ " AND a.incidentId = i.incidentId"
|
||||
+ " AND a.apiId = :apiId"
|
||||
@@ -96,7 +111,7 @@ public interface ApiStatusIncidentQueryRepository extends Repository<DjbApistatu
|
||||
/**
|
||||
* 공개 상세 (P7)
|
||||
*/
|
||||
@Query("SELECT i FROM DjbApistatusIncident i, PortalNotice n"
|
||||
@Query("SELECT i FROM DjbApistatusIncident i"
|
||||
+ " WHERE " + VISIBLE
|
||||
+ " AND i.incidentId = :incidentId")
|
||||
Optional<DjbApistatusIncident> findVisibleById(@Param("incidentId") Long incidentId);
|
||||
|
||||
+12
-11
@@ -149,10 +149,10 @@ public class ApiCurrentStatusService {
|
||||
return names;
|
||||
}
|
||||
|
||||
/** 진행 중(미종결) 장애 중 API 별로 가장 심각한 한 건 */
|
||||
/** 진행 중(미종결) 장애·지연 중 API 별로 가장 심각한 한 건 */
|
||||
private Map<String, DjbApistatusIncident> mapOpenIncidents(Set<String> apiIds) {
|
||||
List<DjbApistatusIncident> openIncidents = incidentQueryRepository
|
||||
.findVisibleOpenIncidents(IncidentKind.INCIDENT, ApiStatusSupport.CLOSED_STATES);
|
||||
.findVisibleOpenIncidents(IncidentKind.DEGRADING, ApiStatusSupport.CLOSED_STATES);
|
||||
if (openIncidents.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
@@ -204,12 +204,12 @@ public class ApiCurrentStatusService {
|
||||
return byApi;
|
||||
}
|
||||
|
||||
/** 조회 기간 내 마지막 장애 발생 시각 */
|
||||
/** 조회 기간 내 마지막 장애·지연 발생 시각 */
|
||||
private Map<String, LocalDateTime> collectLastIncidentAt(Set<String> apiIds, LocalDateTime now, int windowDays) {
|
||||
LocalDateTime windowStart = now.toLocalDate().minusDays(windowDays - 1L).atStartOfDay();
|
||||
List<DjbApistatusIncident> incidents = incidentQueryRepository
|
||||
.findVisibleOverlapping(windowStart, now.toLocalDate().plusDays(1).atStartOfDay()).stream()
|
||||
.filter(incident -> incident.getKind() == IncidentKind.INCIDENT)
|
||||
.filter(incident -> incident.getKind() != null && incident.getKind().isDegrading())
|
||||
.collect(Collectors.toList());
|
||||
if (incidents.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
@@ -233,14 +233,15 @@ public class ApiCurrentStatusService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 진행 중 장애 + 점검 여부로 현재 상태를 정한다.
|
||||
* 진행 중 장애·지연 + 점검 여부로 현재 상태를 정한다.
|
||||
*
|
||||
* <p>자동 탐지 지연(INTERFACE_ID {@code DELAY_START:}) 과 모니터링 단계는 장애가 아닌 지연으로 본다.
|
||||
* 이슈 이력 화면의 "지연/장애" 필터와 같은 기준이다.</p>
|
||||
* <p>KIND 가 DELAY 면 지연이다. 장애(INCIDENT)라도 모니터링 단계면 이미 완화된 상태라
|
||||
* 지연으로 표기한다 - 이슈 이력의 유형 필터(KIND 기준)와는 이 지점만 다르다.</p>
|
||||
*/
|
||||
private String resolveStatus(DjbApistatusIncident open, boolean underMaintenance) {
|
||||
if (open != null) {
|
||||
boolean degraded = open.getState() == IncidentState.MONITORING || ApiStatusSupport.isDelay(open);
|
||||
boolean degraded = open.getKind() == IncidentKind.DELAY
|
||||
|| open.getState() == IncidentState.MONITORING;
|
||||
return degraded ? ApiStatusSupport.STATUS_DEGRADED : ApiStatusSupport.STATUS_OUTAGE;
|
||||
}
|
||||
if (underMaintenance) {
|
||||
@@ -250,14 +251,14 @@ public class ApiCurrentStatusService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 같은 API 에 열린 장애가 여럿일 때의 우선순위 (낮을수록 심각).
|
||||
* 지연으로 판정되는 건은 장애보다 뒤로 민다.
|
||||
* 같은 API 에 열린 이슈가 여럿일 때의 우선순위 (낮을수록 심각).
|
||||
* 지연은 장애보다 뒤로 민다.
|
||||
*/
|
||||
private int severity(DjbApistatusIncident incident) {
|
||||
if (incident == null) {
|
||||
return 99;
|
||||
}
|
||||
int base = ApiStatusSupport.isDelay(incident) ? 10 : 0;
|
||||
int base = incident.getKind() == IncidentKind.DELAY ? 10 : 0;
|
||||
IncidentState state = incident.getState();
|
||||
if (state == null) {
|
||||
return base + 9;
|
||||
|
||||
@@ -125,7 +125,7 @@ public class ApiStatusAssembler {
|
||||
}
|
||||
|
||||
/**
|
||||
* 지난 이슈 카드. 장애는 타임라인 전체를 붙이고 점검은 붙이지 않는다 (ADR-F15).
|
||||
* 지난 이슈 카드. 장애·지연은 타임라인 전체를 붙이고 점검은 붙이지 않는다 (ADR-F15).
|
||||
*/
|
||||
public List<PastIssueCardDTO> toPastIssueCards(List<DjbApistatusIncident> incidents) {
|
||||
if (incidents.isEmpty()) {
|
||||
@@ -135,7 +135,7 @@ public class ApiStatusAssembler {
|
||||
Map<Long, List<AffectedApiDTO>> apis = loadApis(ids);
|
||||
|
||||
List<Long> incidentKindIds = incidents.stream()
|
||||
.filter(incident -> incident.getKind() == IncidentKind.INCIDENT)
|
||||
.filter(incident -> incident.getKind() != null && incident.getKind().isDegrading())
|
||||
.map(DjbApistatusIncident::getIncidentId)
|
||||
.collect(Collectors.toList());
|
||||
Map<Long, List<TimelineEntryDTO>> timelines = loadTimelines(incidentKindIds);
|
||||
|
||||
+12
-27
@@ -30,9 +30,6 @@ import java.util.stream.Collectors;
|
||||
@Transactional(readOnly = true)
|
||||
public class ApiStatusIssueHistoryService {
|
||||
|
||||
/** 지연은 IncidentKind 가 아니라 INCIDENT 의 하위 구분이므로 필터 값만 따로 둔다 */
|
||||
private static final String KIND_DELAY = "DELAY";
|
||||
|
||||
private final ApiStatusIncidentQueryRepository incidentQueryRepository;
|
||||
private final ApiStatusAssembler assembler;
|
||||
private final ApiStatusCatalogService catalogService;
|
||||
@@ -85,19 +82,17 @@ public class ApiStatusIssueHistoryService {
|
||||
* 인덱스바 1칸에 이슈 1건을 집계한다. 유형은 이슈 목록 필터와 같은 세 축(장애/지연/점검)으로 가른다.
|
||||
*/
|
||||
private void tally(IssueDateEntryDTO entry, DjbApistatusIncident incident) {
|
||||
String kind;
|
||||
if (incident.getKind() == IncidentKind.MAINTENANCE) {
|
||||
entry.setMntCount(entry.getMntCount() + 1);
|
||||
kind = IncidentKind.MAINTENANCE.name();
|
||||
} else if (ApiStatusSupport.isDelay(incident)) {
|
||||
entry.setDlyCount(entry.getDlyCount() + 1);
|
||||
kind = KIND_DELAY;
|
||||
} else {
|
||||
entry.setIncCount(entry.getIncCount() + 1);
|
||||
kind = IncidentKind.INCIDENT.name();
|
||||
IncidentKind kind = incident.getKind();
|
||||
if (kind == null) {
|
||||
return;
|
||||
}
|
||||
if (!entry.getKinds().contains(kind)) {
|
||||
entry.getKinds().add(kind);
|
||||
switch (kind) {
|
||||
case MAINTENANCE: entry.setMntCount(entry.getMntCount() + 1); break;
|
||||
case DELAY: entry.setDlyCount(entry.getDlyCount() + 1); break;
|
||||
default: entry.setIncCount(entry.getIncCount() + 1); break;
|
||||
}
|
||||
if (!entry.getKinds().contains(kind.name())) {
|
||||
entry.getKinds().add(kind.name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,24 +143,14 @@ public class ApiStatusIssueHistoryService {
|
||||
|
||||
/**
|
||||
* 유형 필터. 미지정/ALL/알 수 없는 값은 전체(null)로 본다.
|
||||
*
|
||||
* <p>지연(DELAY)은 별도 KIND 가 아니라 자동 탐지 시 INCIDENT 로 흡수된다(ADR-F12).
|
||||
* 자동 탐지 지연 건은 INTERFACE_ID 가 {@code DELAY_START:} 로 시작하므로 이를 기준으로 가른다.
|
||||
* "장애만" 은 지연을 제외한 INCIDENT 다.</p>
|
||||
* 필터 값은 {@link IncidentKind} 이름 그대로다 (INCIDENT / DELAY / MAINTENANCE).
|
||||
*/
|
||||
private java.util.function.Predicate<DjbApistatusIncident> kindFilter(String kind) {
|
||||
if (StringUtils.isBlank(kind) || "ALL".equalsIgnoreCase(kind)) {
|
||||
return null;
|
||||
}
|
||||
if (KIND_DELAY.equalsIgnoreCase(kind)) {
|
||||
return ApiStatusSupport::isDelay;
|
||||
}
|
||||
if ("INCIDENT".equalsIgnoreCase(kind)) {
|
||||
return incident -> incident.getKind() == IncidentKind.INCIDENT
|
||||
&& !ApiStatusSupport.isDelay(incident);
|
||||
}
|
||||
try {
|
||||
IncidentKind selected = IncidentKind.valueOf(kind.toUpperCase());
|
||||
IncidentKind selected = IncidentKind.valueOf(kind.trim().toUpperCase());
|
||||
return incident -> incident.getKind() == selected;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
|
||||
+2
-2
@@ -26,11 +26,11 @@ public class ApiStatusQueryService {
|
||||
private final ApiStatusIncidentQueryRepository incidentQueryRepository;
|
||||
private final ApiStatusAssembler assembler;
|
||||
|
||||
/** P3 - 진행 중 장애 */
|
||||
/** P3 - 진행 중 장애·지연 */
|
||||
public List<ActiveIncidentDTO> getActiveIncidents() {
|
||||
LocalDateTime now = ApiStatusSupport.now();
|
||||
List<DjbApistatusIncident> incidents = incidentQueryRepository
|
||||
.findVisibleOpenIncidents(IncidentKind.INCIDENT, ApiStatusSupport.CLOSED_STATES);
|
||||
.findVisibleOpenIncidents(IncidentKind.DEGRADING, ApiStatusSupport.CLOSED_STATES);
|
||||
return assembler.toActiveIncidents(incidents, now);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,6 @@ public final class ApiStatusSupport {
|
||||
public static final String STATUS_OUTAGE = "OUTAGE";
|
||||
public static final String STATUS_MAINTENANCE = "MAINTENANCE";
|
||||
|
||||
/**
|
||||
* 자동 탐지 지연 건의 INTERFACE_ID prefix (admin ApiStatusDetectionService 가 event 명으로 생성).
|
||||
*
|
||||
* <p>지연(DELAY)은 별도 KIND 가 아니라 INCIDENT 로 흡수되므로(ADR-F12) 이 prefix 로 가른다.</p>
|
||||
*/
|
||||
public static final String DELAY_INTERFACE_PREFIX = "DELAY_START:";
|
||||
|
||||
private ApiStatusSupport() {
|
||||
}
|
||||
|
||||
@@ -45,12 +38,22 @@ public final class ApiStatusSupport {
|
||||
return LocalDateTime.now(ZONE);
|
||||
}
|
||||
|
||||
/** 자동 탐지된 지연 건인지 여부 (장애와 구분) */
|
||||
/** 지연 건인지 여부 (장애와 구분) */
|
||||
public static boolean isDelay(DjbApistatusIncident incident) {
|
||||
return incident != null
|
||||
&& incident.getKind() == IncidentKind.INCIDENT
|
||||
&& incident.getInterfaceId() != null
|
||||
&& incident.getInterfaceId().startsWith(DELAY_INTERFACE_PREFIX);
|
||||
return incident != null && incident.getKind() == IncidentKind.DELAY;
|
||||
}
|
||||
|
||||
/** 이슈 종류에 대응하는 현재 상태 코드 */
|
||||
public static String statusOf(IncidentKind kind) {
|
||||
if (kind == null) {
|
||||
return STATUS_NORMAL;
|
||||
}
|
||||
switch (kind) {
|
||||
case INCIDENT: return STATUS_OUTAGE;
|
||||
case DELAY: return STATUS_DEGRADED;
|
||||
case MAINTENANCE: return STATUS_MAINTENANCE;
|
||||
default: return STATUS_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -64,9 +64,10 @@ public class ApiStatusUptimeService {
|
||||
LocalDateTime now = ApiStatusSupport.now();
|
||||
LocalDateTime windowStart = now.toLocalDate().minusDays(windowDays - 1L).atStartOfDay();
|
||||
|
||||
// 장애와 지연 모두 서비스 저하이므로 가동률에서 차감한다. 점검은 계획된 작업이라 제외.
|
||||
List<DjbApistatusIncident> incidents = incidentQueryRepository
|
||||
.findVisibleOverlapping(windowStart, now.toLocalDate().plusDays(1).atStartOfDay()).stream()
|
||||
.filter(incident -> incident.getKind() == IncidentKind.INCIDENT)
|
||||
.filter(incident -> incident.getKind() != null && incident.getKind().isDegrading())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Map<String, List<long[]>> intervalsByApi = new HashMap<>();
|
||||
@@ -135,7 +136,7 @@ public class ApiStatusUptimeService {
|
||||
maintenanceIntervals.add(interval);
|
||||
} else {
|
||||
incidentIntervals.add(interval);
|
||||
if (ApiStatusSupport.isDelay(incident)) {
|
||||
if (incident.getKind() == IncidentKind.DELAY) {
|
||||
delayIntervals.add(interval);
|
||||
} else {
|
||||
outageIntervals.add(interval);
|
||||
|
||||
@@ -27221,6 +27221,9 @@ input[type=checkbox]:checked + .custom-checkbox {
|
||||
.api-status .as-issue-card.is-incident {
|
||||
border-left: 4px solid var(--as-err);
|
||||
}
|
||||
.api-status .as-issue-card.is-degraded {
|
||||
border-left: 4px solid var(--as-warn);
|
||||
}
|
||||
.api-status .as-issue-card.is-maintenance {
|
||||
border-left: 4px solid var(--as-info);
|
||||
}
|
||||
@@ -27243,6 +27246,9 @@ input[type=checkbox]:checked + .custom-checkbox {
|
||||
.api-status .as-issue-card.is-incident .as-issue-title {
|
||||
color: var(--as-err);
|
||||
}
|
||||
.api-status .as-issue-card.is-degraded .as-issue-title {
|
||||
color: var(--as-warn);
|
||||
}
|
||||
.api-status .as-issue-card.is-maintenance .as-issue-title {
|
||||
color: var(--as-info);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
/** 오픈 API 목록에 노출되는 API (링크 가능 대상) */
|
||||
const linkableApiIds = new Set();
|
||||
|
||||
const KIND_LABEL = { INCIDENT: '장애', MAINTENANCE: '점검' };
|
||||
const KIND_LABEL = { INCIDENT: '장애', DELAY: '지연', MAINTENANCE: '점검' };
|
||||
const KIND_CLASS = { INCIDENT: 'is-incident', DELAY: 'is-degraded', MAINTENANCE: 'is-maintenance' };
|
||||
const PAGE_SIZE = 10;
|
||||
const API_LIST_LIMIT = 50; // 라이브서치 결과 표시 상한
|
||||
|
||||
@@ -191,7 +192,7 @@
|
||||
}
|
||||
|
||||
function issueCardHtml(issue) {
|
||||
const kindClass = issue.kind === 'MAINTENANCE' ? 'is-maintenance' : 'is-incident';
|
||||
const kindClass = KIND_CLASS[issue.kind] || 'is-incident';
|
||||
|
||||
let inner;
|
||||
if (issue.kind === 'MAINTENANCE') {
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
/** 오픈 API 목록에 노출되는 API (링크 가능 대상) */
|
||||
const linkableApiIds = new Set();
|
||||
|
||||
const KIND_LABEL = { INCIDENT: '장애', MAINTENANCE: '점검' };
|
||||
const KIND_LABEL = { INCIDENT: '장애', DELAY: '지연', MAINTENANCE: '점검' };
|
||||
const KIND_CLASS = { INCIDENT: 'is-incident', DELAY: 'is-degraded', MAINTENANCE: 'is-maintenance' };
|
||||
|
||||
/** 진행 중 장애 카드 노출 상한. 초과분은 전체 이력 링크로 넘긴다. */
|
||||
const ACTIVE_INCIDENT_LIMIT = 1;
|
||||
@@ -262,8 +263,8 @@
|
||||
|
||||
// ---------------- ❺ 지난 이슈 사항 ----------------
|
||||
function issueCardHtml(issue) {
|
||||
const kindClass = issue.kind === 'MAINTENANCE' ? 'is-maintenance' : 'is-incident';
|
||||
const kindBadge = issue.kind === 'MAINTENANCE' ? 'is-maintenance' : 'is-incident';
|
||||
const kindClass = KIND_CLASS[issue.kind] || 'is-incident';
|
||||
const kindBadge = kindClass;
|
||||
|
||||
let inner;
|
||||
if (issue.kind === 'MAINTENANCE') {
|
||||
|
||||
@@ -495,6 +495,7 @@
|
||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
|
||||
|
||||
&.is-incident { border-left: 4px solid var(--as-err); }
|
||||
&.is-degraded { border-left: 4px solid var(--as-warn); }
|
||||
&.is-maintenance { border-left: 4px solid var(--as-info); }
|
||||
|
||||
.as-issue-meta-row {
|
||||
@@ -516,6 +517,7 @@
|
||||
}
|
||||
|
||||
&.is-incident .as-issue-title { color: var(--as-err); }
|
||||
&.is-degraded .as-issue-title { color: var(--as-warn); }
|
||||
&.is-maintenance .as-issue-title { color: var(--as-info); }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user