Skip to content

Commit 5949f59

Browse files
authored
Merge pull request #84 from Sysone-Final/feature/SYSONE-73-monitoring
Feature/sysone 73 monitoring
2 parents c928802 + 2ced00a commit 5949f59

13 files changed

Lines changed: 654 additions & 446 deletions

File tree

src/main/java/org/example/finalbe/domains/alert/controller/AlertController.java

Lines changed: 332 additions & 149 deletions
Large diffs are not rendered by default.

src/main/java/org/example/finalbe/domains/alert/domain/AlertHistory.java

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import jakarta.persistence.*;
44
import lombok.*;
55
import org.example.finalbe.domains.common.enumdir.AlertLevel;
6-
import org.example.finalbe.domains.common.enumdir.AlertStatus;
76
import org.example.finalbe.domains.common.enumdir.MetricType;
87
import org.example.finalbe.domains.common.enumdir.TargetType;
98

@@ -53,11 +52,6 @@ public class AlertHistory {
5352
@Column(name = "alert_level", nullable = false, length = 20)
5453
private AlertLevel level;
5554

56-
@Enumerated(EnumType.STRING)
57-
@Column(name = "status", nullable = false, length = 20)
58-
@Builder.Default
59-
private AlertStatus status = AlertStatus.TRIGGERED;
60-
6155
@Column(name = "measured_value", nullable = false)
6256
private Double measuredValue;
6357

@@ -67,48 +61,37 @@ public class AlertHistory {
6761
@Column(name = "triggered_at", nullable = false)
6862
private LocalDateTime triggeredAt;
6963

70-
@Column(name = "acknowledged_at")
71-
private LocalDateTime acknowledgedAt;
72-
73-
@Column(name = "resolved_at")
74-
private LocalDateTime resolvedAt;
64+
// 읽음 처리 관련 필드
65+
@Column(name = "is_read", nullable = false)
66+
@Builder.Default
67+
private Boolean isRead = false;
7568

76-
@Column(name = "acknowledged_by")
77-
private Long acknowledgedBy;
69+
@Column(name = "read_at")
70+
private LocalDateTime readAt;
7871

79-
@Column(name = "resolved_by")
80-
private Long resolvedBy;
72+
@Column(name = "read_by")
73+
private Long readBy;
8174

8275
@Column(name = "message", length = 500)
8376
private String message;
8477

8578
@Column(name = "additional_info", columnDefinition = "TEXT")
8679
private String additionalInfo;
8780

88-
@Column(name = "created_at")
89-
@Builder.Default
90-
private LocalDateTime createdAt = LocalDateTime.now();
91-
92-
public void acknowledge(Long userId) {
93-
if (this.status == AlertStatus.TRIGGERED) {
94-
this.status = AlertStatus.ACKNOWLEDGED;
95-
this.acknowledgedAt = LocalDateTime.now();
96-
this.acknowledgedBy = userId;
97-
}
98-
}
99-
100-
public void resolve(Long userId) {
101-
this.status = AlertStatus.RESOLVED;
102-
this.resolvedAt = LocalDateTime.now();
103-
this.resolvedBy = userId;
81+
@Column(name = "created_at", nullable = false, updatable = false)
82+
private LocalDateTime createdAt;
10483

105-
if (this.acknowledgedAt == null) {
106-
this.acknowledgedAt = LocalDateTime.now();
107-
this.acknowledgedBy = userId;
108-
}
84+
@PrePersist
85+
protected void onCreate() {
86+
this.createdAt = LocalDateTime.now();
10987
}
11088

111-
public boolean isActive() {
112-
return status != AlertStatus.RESOLVED;
89+
/**
90+
* 읽음 처리
91+
*/
92+
public void markAsRead(Long userId) {
93+
this.isRead = true;
94+
this.readAt = LocalDateTime.now();
95+
this.readBy = userId;
11396
}
114-
}
97+
}

src/main/java/org/example/finalbe/domains/alert/dto/AlertHistoryDto.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import org.example.finalbe.domains.alert.domain.AlertHistory;
44
import org.example.finalbe.domains.common.enumdir.AlertLevel;
5-
import org.example.finalbe.domains.common.enumdir.AlertStatus;
65
import org.example.finalbe.domains.common.enumdir.MetricType;
76
import org.example.finalbe.domains.common.enumdir.TargetType;
87

@@ -25,18 +24,16 @@ public record AlertHistoryDto(
2524

2625
// 알림 정보
2726
AlertLevel level,
28-
AlertStatus status,
2927
Double measuredValue,
3028
Double thresholdValue,
3129

3230
// 시간 정보
3331
LocalDateTime triggeredAt,
34-
LocalDateTime acknowledgedAt,
35-
LocalDateTime resolvedAt,
3632

37-
// 사용자 정보
38-
Long acknowledgedBy,
39-
Long resolvedBy,
33+
// 읽음 정보
34+
Boolean isRead,
35+
LocalDateTime readAt,
36+
Long readBy,
4037

4138
// 메시지
4239
String message,
@@ -56,14 +53,12 @@ public static AlertHistoryDto from(AlertHistory alert) {
5653
alert.getMetricType(),
5754
alert.getMetricName(),
5855
alert.getLevel(),
59-
alert.getStatus(),
6056
alert.getMeasuredValue(),
6157
alert.getThresholdValue(),
6258
alert.getTriggeredAt(),
63-
alert.getAcknowledgedAt(),
64-
alert.getResolvedAt(),
65-
alert.getAcknowledgedBy(),
66-
alert.getResolvedBy(),
59+
alert.getIsRead(),
60+
alert.getReadAt(),
61+
alert.getReadBy(),
6762
alert.getMessage(),
6863
alert.getAdditionalInfo(),
6964
alert.getCreatedAt()

src/main/java/org/example/finalbe/domains/alert/dto/AlertNotificationDto.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import org.example.finalbe.domains.alert.domain.AlertHistory;
44
import org.example.finalbe.domains.common.enumdir.AlertLevel;
5-
import org.example.finalbe.domains.common.enumdir.AlertStatus;
65
import org.example.finalbe.domains.common.enumdir.MetricType;
76
import org.example.finalbe.domains.common.enumdir.TargetType;
87

@@ -25,14 +24,15 @@ public record AlertNotificationDto(
2524

2625
// 알림 정보
2726
AlertLevel level,
28-
AlertStatus status,
2927
Double measuredValue,
3028
Double thresholdValue,
3129

3230
// 시간 정보
3331
LocalDateTime triggeredAt,
34-
LocalDateTime acknowledgedAt,
35-
LocalDateTime resolvedAt,
32+
33+
// 읽음 정보
34+
Boolean isRead,
35+
LocalDateTime readAt,
3636

3737
// 메시지
3838
String message
@@ -49,12 +49,11 @@ public static AlertNotificationDto from(AlertHistory alert) {
4949
alert.getMetricType(),
5050
alert.getMetricName(),
5151
alert.getLevel(),
52-
alert.getStatus(),
5352
alert.getMeasuredValue(),
5453
alert.getThresholdValue(),
5554
alert.getTriggeredAt(),
56-
alert.getAcknowledgedAt(),
57-
alert.getResolvedAt(),
55+
alert.getIsRead(),
56+
alert.getReadAt(),
5857
alert.getMessage()
5958
);
6059
}
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
1+
// src/main/java/org/example/finalbe/domains/alert/dto/AlertStatisticsDto.java
12
package org.example.finalbe.domains.alert.dto;
23

34
public record AlertStatisticsDto(
45
Long totalAlerts,
56
Long triggeredAlerts,
6-
Long acknowledgedAlerts,
7-
Long resolvedAlerts,
87

98
Long criticalAlerts,
109
Long warningAlerts,
1110

1211
Long equipmentAlerts,
1312
Long rackAlerts,
14-
Long serverRoomAlerts,
15-
Long dataCenterAlerts
13+
Long serverRoomAlerts
1614
) {
1715
/**
18-
* 빌더 패턴 대체 - 모든 필드 0으로 초기화
16+
* 빈 통계 (모든 필드 0으로 초기화)
1917
*/
2018
public static AlertStatisticsDto empty() {
21-
return new AlertStatisticsDto(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
19+
return new AlertStatisticsDto(0L, 0L, 0L, 0L, 0L, 0L, 0L);
2220
}
2321
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.example.finalbe.domains.alert.dto;
2+
3+
import jakarta.validation.constraints.NotEmpty;
4+
import java.util.List;
5+
6+
public record DeleteAlertsRequest(
7+
@NotEmpty(message = "알림 ID 목록은 필수입니다.")
8+
List<Long> alertIds
9+
) {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.example.finalbe.domains.alert.dto;
2+
3+
import jakarta.validation.constraints.NotEmpty;
4+
import java.util.List;
5+
6+
public record MarkAsReadRequest(
7+
@NotEmpty(message = "알림 ID 목록은 필수입니다.")
8+
List<Long> alertIds
9+
) {}

src/main/java/org/example/finalbe/domains/alert/repository/AlertHistoryRepository.java

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,126 @@
22

33
import org.example.finalbe.domains.alert.domain.AlertHistory;
44
import org.example.finalbe.domains.common.enumdir.AlertLevel;
5-
import org.example.finalbe.domains.common.enumdir.AlertStatus;
65
import org.example.finalbe.domains.common.enumdir.MetricType;
76
import org.example.finalbe.domains.common.enumdir.TargetType;
7+
import org.springframework.data.domain.Page;
8+
import org.springframework.data.domain.Pageable;
89
import org.springframework.data.jpa.repository.JpaRepository;
10+
import org.springframework.data.jpa.repository.Modifying;
911
import org.springframework.data.jpa.repository.Query;
1012
import org.springframework.data.repository.query.Param;
1113

14+
import java.time.LocalDateTime;
1215
import java.util.List;
1316

1417
public interface AlertHistoryRepository extends JpaRepository<AlertHistory, Long> {
1518

16-
// ========== 기존 메서드 ==========
19+
// ========== 기존 조회 메서드 (status 제거) ==========
1720

18-
List<AlertHistory> findByEquipmentIdAndStatusOrderByTriggeredAtDesc(
19-
Long equipmentId, AlertStatus status);
21+
List<AlertHistory> findByEquipmentIdOrderByTriggeredAtDesc(Long equipmentId);
2022

2123
@Query("SELECT a FROM AlertHistory a WHERE a.equipmentId = :equipmentId " +
2224
"AND a.metricType = :metricType AND a.metricName = :metricName " +
23-
"AND a.status != 'RESOLVED' ORDER BY a.triggeredAt DESC")
25+
"ORDER BY a.triggeredAt DESC")
2426
List<AlertHistory> findActiveAlertsByEquipmentIdAndMetric(
2527
@Param("equipmentId") Long equipmentId,
2628
@Param("metricType") MetricType metricType,
2729
@Param("metricName") String metricName);
2830

29-
List<AlertHistory> findByRackIdAndStatusOrderByTriggeredAtDesc(
30-
Long rackId, AlertStatus status);
31+
List<AlertHistory> findByRackIdOrderByTriggeredAtDesc(Long rackId);
3132

3233
@Query("SELECT a FROM AlertHistory a WHERE a.rackId = :rackId " +
3334
"AND a.metricType = :metricType AND a.metricName = :metricName " +
34-
"AND a.status != 'RESOLVED' ORDER BY a.triggeredAt DESC")
35+
"ORDER BY a.triggeredAt DESC")
3536
List<AlertHistory> findActiveAlertsByRackIdAndMetric(
3637
@Param("rackId") Long rackId,
3738
@Param("metricType") MetricType metricType,
3839
@Param("metricName") String metricName);
3940

40-
List<AlertHistory> findByStatusOrderByTriggeredAtDesc(AlertStatus status);
41+
List<AlertHistory> findAllByOrderByTriggeredAtDesc();
4142

42-
// ========== 통계 조회 메서드 (신규) ==========
43+
List<AlertHistory> findByServerRoomIdOrderByTriggeredAtDesc(Long serverRoomId);
4344

44-
/**
45-
* 상태별 알림 개수 조회
46-
*/
47-
long countByStatus(AlertStatus status);
45+
List<AlertHistory> findByDataCenterIdOrderByTriggeredAtDesc(Long dataCenterId);
46+
47+
// ========== 페이지네이션 및 필터링 메서드 ==========
48+
49+
@Query("SELECT a FROM AlertHistory a " +
50+
"WHERE a.serverRoomId IN :serverRoomIds " +
51+
"AND a.triggeredAt >= :startTime " +
52+
"AND a.targetType != :excludeTargetType")
53+
Page<AlertHistory> findByServerRoomIdInAndTriggeredAtAfterAndTargetTypeNot(
54+
@Param("serverRoomIds") List<Long> serverRoomIds,
55+
@Param("startTime") LocalDateTime startTime,
56+
@Param("excludeTargetType") TargetType excludeTargetType,
57+
Pageable pageable);
58+
59+
@Query("SELECT a FROM AlertHistory a " +
60+
"WHERE a.serverRoomId IN :serverRoomIds " +
61+
"AND a.level = :level " +
62+
"AND a.triggeredAt >= :startTime " +
63+
"AND a.targetType != :excludeTargetType")
64+
Page<AlertHistory> findByServerRoomIdInAndLevelAndTriggeredAtAfterAndTargetTypeNot(
65+
@Param("serverRoomIds") List<Long> serverRoomIds,
66+
@Param("level") AlertLevel level,
67+
@Param("startTime") LocalDateTime startTime,
68+
@Param("excludeTargetType") TargetType excludeTargetType,
69+
Pageable pageable);
70+
71+
// ========== 통계 조회 메서드 (서버실별 필터링) ==========
72+
73+
@Query("SELECT COUNT(a) FROM AlertHistory a WHERE a.serverRoomId IN :serverRoomIds")
74+
long countByServerRoomIdIn(@Param("serverRoomIds") List<Long> serverRoomIds);
75+
76+
@Query("SELECT COUNT(a) FROM AlertHistory a WHERE a.serverRoomId IN :serverRoomIds AND a.level = :level")
77+
long countByServerRoomIdInAndLevel(
78+
@Param("serverRoomIds") List<Long> serverRoomIds,
79+
@Param("level") AlertLevel level);
80+
81+
@Query("SELECT COUNT(a) FROM AlertHistory a WHERE a.serverRoomId IN :serverRoomIds AND a.targetType = :targetType")
82+
long countByServerRoomIdInAndTargetType(
83+
@Param("serverRoomIds") List<Long> serverRoomIds,
84+
@Param("targetType") TargetType targetType);
85+
86+
// ========== 기존 통계 조회 메서드 (전체 기준) ==========
4887

49-
/**
50-
* 레벨별 알림 개수 조회
51-
*/
5288
long countByLevel(AlertLevel level);
5389

54-
/**
55-
* 타겟 타입별 알림 개수 조회
56-
*/
5790
long countByTargetType(TargetType targetType);
91+
92+
// ========== 읽음 처리 관련 메서드 ==========
93+
94+
@Modifying
95+
@Query("UPDATE AlertHistory a SET a.isRead = true, a.readAt = :readAt, a.readBy = :readBy " +
96+
"WHERE a.serverRoomId IN :serverRoomIds AND a.isRead = false")
97+
int markAllAsReadByServerRoomIds(
98+
@Param("serverRoomIds") List<Long> serverRoomIds,
99+
@Param("readAt") LocalDateTime readAt,
100+
@Param("readBy") Long readBy
101+
);
102+
103+
@Modifying
104+
@Query("UPDATE AlertHistory a SET a.isRead = true, a.readAt = :readAt, a.readBy = :readBy " +
105+
"WHERE a.id IN :alertIds AND a.isRead = false")
106+
int markAsReadByIds(
107+
@Param("alertIds") List<Long> alertIds,
108+
@Param("readAt") LocalDateTime readAt,
109+
@Param("readBy") Long readBy
110+
);
111+
112+
// ========== 삭제 관련 메서드 ==========
113+
114+
@Modifying
115+
@Query("DELETE FROM AlertHistory a WHERE a.id IN :alertIds AND a.serverRoomId IN :serverRoomIds")
116+
int deleteByIdsAndServerRoomIds(
117+
@Param("alertIds") List<Long> alertIds,
118+
@Param("serverRoomIds") List<Long> serverRoomIds
119+
);
120+
121+
@Modifying
122+
@Query("DELETE FROM AlertHistory a WHERE a.serverRoomId IN :serverRoomIds")
123+
int deleteAllByServerRoomIds(@Param("serverRoomIds") List<Long> serverRoomIds);
124+
125+
@Query("SELECT COUNT(a) FROM AlertHistory a WHERE a.serverRoomId IN :serverRoomIds AND a.isRead = false")
126+
long countUnreadByServerRoomIds(@Param("serverRoomIds") List<Long> serverRoomIds);
58127
}

0 commit comments

Comments
 (0)