Skip to content

Commit 8412b9e

Browse files
authored
Merge branch 'master' into master
2 parents 3e7c5c7 + 3264979 commit 8412b9e

File tree

29 files changed

+790
-88
lines changed

29 files changed

+790
-88
lines changed

.all-contributorsrc

+9
Original file line numberDiff line numberDiff line change
@@ -2397,6 +2397,15 @@
23972397
"contributions": [
23982398
"code"
23992399
]
2400+
},
2401+
{
2402+
"login": "KevinLLF",
2403+
"name": "Jay丿167",
2404+
"avatar_url": "https://avatars.githubusercontent.com/u/85452733?v=4",
2405+
"profile": "https://github.com/KevinLLF",
2406+
"contributions": [
2407+
"code"
2408+
]
24002409
}
24012410
],
24022411
"contributorsPerLine": 7,

.gitignore

-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ build/
77
out/
88
micronaut-cli.yml
99
.mvn/
10-
mvnw
11-
mvnw.bat
1210
*.log
1311
package-lock.json
1412
*.zip

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ Thanks to these wonderful people, welcome to join us:
520520
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gagaradio"><img src="https://avatars.githubusercontent.com/u/18532370?v=4?s=100" width="100px;" alt="Walter Jia"/><br /><sub><b>Walter Jia</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=gagaradio" title="Code">💻</a></td>
521521
<td align="center" valign="top" width="14.28%"><a href="https://github.com/boyucjz"><img src="https://avatars.githubusercontent.com/u/18730041?v=4?s=100" width="100px;" alt="boyucjz"/><br /><sub><b>boyucjz</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=boyucjz" title="Code">💻</a></td>
522522
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Cyanty"><img src="https://avatars.githubusercontent.com/u/153884653?v=4?s=100" width="100px;" alt="Cyanty"/><br /><sub><b>Cyanty</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Cyanty" title="Code">💻</a></td>
523+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KevinLLF"><img src="https://avatars.githubusercontent.com/u/85452733?v=4?s=100" width="100px;" alt="Jay丿167"/><br /><sub><b>Jay丿167</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=KevinLLF" title="Code">💻</a></td>
523524
</tr>
524525
</tbody>
525526
</table>

README_CN.md

+1
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ Thanks these wonderful people, welcome to join us:
519519
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gagaradio"><img src="https://avatars.githubusercontent.com/u/18532370?v=4?s=100" width="100px;" alt="Walter Jia"/><br /><sub><b>Walter Jia</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=gagaradio" title="Code">💻</a></td>
520520
<td align="center" valign="top" width="14.28%"><a href="https://github.com/boyucjz"><img src="https://avatars.githubusercontent.com/u/18730041?v=4?s=100" width="100px;" alt="boyucjz"/><br /><sub><b>boyucjz</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=boyucjz" title="Code">💻</a></td>
521521
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Cyanty"><img src="https://avatars.githubusercontent.com/u/153884653?v=4?s=100" width="100px;" alt="Cyanty"/><br /><sub><b>Cyanty</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=Cyanty" title="Code">💻</a></td>
522+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KevinLLF"><img src="https://avatars.githubusercontent.com/u/85452733?v=4?s=100" width="100px;" alt="Jay丿167"/><br /><sub><b>Jay丿167</b></sub></a><br /><a href="https://github.com/apache/hertzbeat/commits?author=KevinLLF" title="Code">💻</a></td>
522523
</tr>
523524
</tbody>
524525
</table>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.hertzbeat.alert.calculate;
19+
20+
import org.apache.hertzbeat.alert.dao.SingleAlertDao;
21+
import org.apache.hertzbeat.alert.util.AlertUtil;
22+
import org.apache.hertzbeat.common.constants.CommonConstants;
23+
import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
24+
import org.springframework.stereotype.Component;
25+
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.concurrent.ConcurrentHashMap;
29+
30+
/**
31+
* alert cache manager
32+
*/
33+
@Component
34+
public class AlarmCacheManager {
35+
36+
/**
37+
* The alarm in the process is triggered
38+
* key - labels fingerprint
39+
*/
40+
private final Map<String, SingleAlert> pendingAlertMap;
41+
/**
42+
* The not recover alert
43+
* key - labels fingerprint
44+
*/
45+
private final Map<String, SingleAlert> firingAlertMap;
46+
47+
public AlarmCacheManager(SingleAlertDao singleAlertDao) {
48+
this.pendingAlertMap = new ConcurrentHashMap<>(8);
49+
this.firingAlertMap = new ConcurrentHashMap<>(8);
50+
List<SingleAlert> singleAlerts = singleAlertDao.querySingleAlertsByStatus(CommonConstants.ALERT_STATUS_FIRING);
51+
for (SingleAlert singleAlert : singleAlerts) {
52+
String fingerprint = AlertUtil.calculateFingerprint(singleAlert.getLabels());
53+
singleAlert.setId(null);
54+
this.firingAlertMap.put(fingerprint, singleAlert);
55+
}
56+
}
57+
58+
public void putPending(String fingerPrint, SingleAlert alert) {
59+
this.pendingAlertMap.put(fingerPrint, alert);
60+
}
61+
62+
public SingleAlert getPending(String fingerPrint) {
63+
return this.pendingAlertMap.get(fingerPrint);
64+
}
65+
66+
public SingleAlert removePending(String fingerPrint) {
67+
return this.pendingAlertMap.remove(fingerPrint);
68+
}
69+
70+
public void putFiring(String fingerPrint, SingleAlert alert) {
71+
this.firingAlertMap.put(fingerPrint, alert);
72+
}
73+
74+
public SingleAlert getFiring(String fingerPrint) {
75+
return this.firingAlertMap.get(fingerPrint);
76+
}
77+
78+
public SingleAlert removeFiring(String fingerPrint) {
79+
return this.firingAlertMap.remove(fingerPrint);
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.hertzbeat.alert.calculate;
19+
20+
import lombok.extern.slf4j.Slf4j;
21+
import org.apache.hertzbeat.alert.dao.AlertCollectorDao;
22+
import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
23+
import org.apache.hertzbeat.alert.util.AlertUtil;
24+
import org.apache.hertzbeat.common.constants.CommonConstants;
25+
import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
26+
import org.apache.hertzbeat.common.entity.manager.Collector;
27+
import org.apache.hertzbeat.common.support.event.SystemConfigChangeEvent;
28+
import org.apache.hertzbeat.common.util.ResourceBundleUtil;
29+
import org.springframework.context.event.EventListener;
30+
import org.springframework.stereotype.Component;
31+
32+
import java.util.HashMap;
33+
import java.util.Map;
34+
import java.util.ResourceBundle;
35+
36+
/**
37+
* handle collector alarm
38+
*/
39+
@Component
40+
@Slf4j
41+
public class CollectorAlertHandler {
42+
43+
private static final String KEY_COLLECTOR_NAME = "collectorName";
44+
private static final String KEY_COLLECTOR_VERSION = "collectorVersion";
45+
private static final String KEY_COLLECTOR_HOST = "collectorHost";
46+
47+
private final AlertCollectorDao alertCollectorDao;
48+
49+
private final AlarmCommonReduce alarmCommonReduce;
50+
51+
private final AlarmCacheManager alarmCacheManager;
52+
53+
private ResourceBundle bundle;
54+
55+
56+
public CollectorAlertHandler(AlarmCommonReduce alarmCommonReduce, AlertCollectorDao alertCollectorDao,
57+
AlarmCacheManager alarmCacheManager) {
58+
this.alarmCommonReduce = alarmCommonReduce;
59+
this.alertCollectorDao = alertCollectorDao;
60+
this.alarmCacheManager = alarmCacheManager;
61+
this.bundle = ResourceBundleUtil.getBundle("alerter");
62+
}
63+
64+
/**
65+
* handle collector online
66+
*
67+
* @param identity collector name
68+
*/
69+
public void online(final String identity) {
70+
Collector collector = alertCollectorDao.findCollectorByName(identity);
71+
if (collector == null) {
72+
return;
73+
}
74+
Map<String, String> fingerPrints = new HashMap<>(8);
75+
fingerPrints.put(KEY_COLLECTOR_NAME, collector.getName());
76+
fingerPrints.put(KEY_COLLECTOR_VERSION, collector.getVersion());
77+
fingerPrints.put(KEY_COLLECTOR_HOST, collector.getIp());
78+
String fingerprint = AlertUtil.calculateFingerprint(fingerPrints);
79+
SingleAlert firingAlert = alarmCacheManager.getFiring(fingerprint);
80+
if (firingAlert != null) {
81+
firingAlert.setTriggerTimes(1);
82+
firingAlert.setEndAt(System.currentTimeMillis());
83+
firingAlert.setStatus(CommonConstants.ALERT_STATUS_RESOLVED);
84+
alarmCommonReduce.reduceAndSendAlarm(firingAlert.clone());
85+
}
86+
}
87+
88+
89+
/**
90+
* handle collector offline
91+
*
92+
* @param identity collector name
93+
*/
94+
public void offline(final String identity) {
95+
Collector collector = alertCollectorDao.findCollectorByName(identity);
96+
if (collector == null) {
97+
return;
98+
}
99+
long currentTimeMill = System.currentTimeMillis();
100+
Map<String, String> fingerPrints = new HashMap<>(8);
101+
fingerPrints.put(KEY_COLLECTOR_NAME, collector.getName());
102+
fingerPrints.put(KEY_COLLECTOR_VERSION, collector.getVersion());
103+
fingerPrints.put(KEY_COLLECTOR_HOST, collector.getIp());
104+
String fingerprint = AlertUtil.calculateFingerprint(fingerPrints);
105+
SingleAlert existingAlert = alarmCacheManager.getFiring(fingerprint);
106+
if (existingAlert == null) {
107+
SingleAlert newAlert = SingleAlert.builder()
108+
.labels(fingerPrints)
109+
.annotations(fingerPrints)
110+
.content(this.bundle.getString("alerter.availability.collector.offline"))
111+
.status(CommonConstants.ALERT_STATUS_FIRING)
112+
.triggerTimes(1)
113+
.startAt(currentTimeMill)
114+
.activeAt(currentTimeMill)
115+
.build();
116+
alarmCacheManager.putFiring(fingerprint, newAlert);
117+
alarmCommonReduce.reduceAndSendAlarm(newAlert.clone());
118+
}
119+
120+
}
121+
122+
123+
@EventListener(SystemConfigChangeEvent.class)
124+
public void onSystemConfigChangeEvent(SystemConfigChangeEvent event) {
125+
log.info("calculate alarm receive system config change event: {}.", event.getSource());
126+
this.bundle = ResourceBundleUtil.getBundle("alerter");
127+
}
128+
129+
}

hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/calculate/PeriodicAlertCalculator.java

+15-32
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,17 @@
1717

1818
package org.apache.hertzbeat.alert.calculate;
1919

20-
import java.util.Arrays;
2120
import java.util.HashMap;
22-
import java.util.Objects;
2321
import lombok.extern.slf4j.Slf4j;
2422
import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
2523
import org.apache.hertzbeat.alert.service.DataSourceService;
2624
import org.apache.hertzbeat.alert.util.AlertTemplateUtil;
25+
import org.apache.hertzbeat.alert.util.AlertUtil;
2726
import org.apache.hertzbeat.common.constants.CommonConstants;
2827
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
2928
import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
3029
import java.util.List;
3130
import java.util.Map;
32-
import java.util.concurrent.ConcurrentHashMap;
3331
import org.apache.commons.lang3.StringUtils;
3432
import org.apache.commons.collections4.CollectionUtils;
3533
import org.springframework.stereotype.Component;
@@ -47,22 +45,13 @@ public class PeriodicAlertCalculator {
4745

4846
private final DataSourceService dataSourceService;
4947
private final AlarmCommonReduce alarmCommonReduce;
50-
/**
51-
* The alarm in the process is triggered
52-
* key - labels fingerprint
53-
*/
54-
private final Map<String, SingleAlert> pendingAlertMap;
55-
/**
56-
* The not recover alert
57-
* key - labels fingerprint
58-
*/
59-
private final Map<String, SingleAlert> firingAlertMap;
60-
61-
public PeriodicAlertCalculator(DataSourceService dataSourceService, AlarmCommonReduce alarmCommonReduce) {
48+
private final AlarmCacheManager alarmCacheManager;
49+
50+
public PeriodicAlertCalculator(DataSourceService dataSourceService, AlarmCommonReduce alarmCommonReduce,
51+
AlarmCacheManager alarmCacheManager) {
6252
this.dataSourceService = dataSourceService;
6353
this.alarmCommonReduce = alarmCommonReduce;
64-
this.pendingAlertMap = new ConcurrentHashMap<>(8);
65-
this.firingAlertMap = new ConcurrentHashMap<>(8);
54+
this.alarmCacheManager = alarmCacheManager;
6655
}
6756

6857
public void calculate(AlertDefine rule) {
@@ -122,8 +111,8 @@ public void calculate(AlertDefine rule) {
122111

123112
private void afterThresholdRuleMatch(long currentTimeMilli, Map<String, String> fingerPrints,
124113
Map<String, Object> fieldValueMap, AlertDefine define) {
125-
String fingerprint = calculateFingerprint(fingerPrints);
126-
SingleAlert existingAlert = pendingAlertMap.get(fingerprint);
114+
String fingerprint = AlertUtil.calculateFingerprint(fingerPrints);
115+
SingleAlert existingAlert = alarmCacheManager.getPending(fingerprint);
127116
Map<String, String> labels = new HashMap<>(8);
128117
fieldValueMap.putAll(define.getLabels());
129118
labels.putAll(fingerPrints);
@@ -144,11 +133,11 @@ private void afterThresholdRuleMatch(long currentTimeMilli, Map<String, String>
144133
// If required trigger times is 1, set to firing status directly
145134
if (requiredTimes <= 1) {
146135
newAlert.setStatus(CommonConstants.ALERT_STATUS_FIRING);
147-
firingAlertMap.put(fingerprint, newAlert);
136+
alarmCacheManager.putFiring(fingerprint, newAlert);
148137
alarmCommonReduce.reduceAndSendAlarm(newAlert.clone());
149138
} else {
150139
// Otherwise put into pending queue first
151-
pendingAlertMap.put(fingerprint, newAlert);
140+
alarmCacheManager.putPending(fingerprint, newAlert);
152141
}
153142
} else {
154143
// Update existing alert
@@ -158,31 +147,25 @@ private void afterThresholdRuleMatch(long currentTimeMilli, Map<String, String>
158147
// Check if required trigger times reached
159148
if (existingAlert.getStatus().equals(CommonConstants.ALERT_STATUS_PENDING) && existingAlert.getTriggerTimes() >= requiredTimes) {
160149
// Reached trigger times threshold, change to firing status
161-
pendingAlertMap.remove(fingerprint);
150+
alarmCacheManager.removePending(fingerprint);
162151
existingAlert.setStatus(CommonConstants.ALERT_STATUS_FIRING);
163-
firingAlertMap.put(fingerprint, existingAlert);
152+
alarmCacheManager.putFiring(fingerprint, existingAlert);
164153
alarmCommonReduce.reduceAndSendAlarm(existingAlert.clone());
165154
}
166155
}
167156
}
168157

169158
private void handleRecoveredAlert(Map<String, String> fingerprints) {
170-
String fingerprint = calculateFingerprint(fingerprints);
171-
SingleAlert firingAlert = firingAlertMap.remove(fingerprint);
159+
String fingerprint = AlertUtil.calculateFingerprint(fingerprints);
160+
SingleAlert firingAlert = alarmCacheManager.removeFiring(fingerprint);
172161
if (firingAlert != null) {
173162
// todo consider multi times to tig for resolved alert
174163
firingAlert.setTriggerTimes(1);
175164
firingAlert.setEndAt(System.currentTimeMillis());
176165
firingAlert.setStatus(CommonConstants.ALERT_STATUS_RESOLVED);
177166
alarmCommonReduce.reduceAndSendAlarm(firingAlert.clone());
178167
}
179-
pendingAlertMap.remove(fingerprint);
168+
alarmCacheManager.removePending(fingerprint);
180169
}
181170

182-
private String calculateFingerprint(Map<String, String> fingerPrints) {
183-
List<String> keyList = fingerPrints.keySet().stream().filter(Objects::nonNull).sorted().toList();
184-
List<String> valueList = fingerPrints.values().stream().filter(Objects::nonNull).sorted().toList();
185-
return Arrays.hashCode(keyList.toArray(new String[0])) + "-"
186-
+ Arrays.hashCode(valueList.toArray(new String[0]));
187-
}
188171
}

0 commit comments

Comments
 (0)