mirror of
https://github.com/dromara/hertzbeat.git
synced 2026-09-17 18:19:02 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ab18d3f78 | ||
|
|
d834a74cf0 | ||
|
|
55f745ecef | ||
|
|
b228cf57f1 |
+18
-49
@@ -17,9 +17,6 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.calculate;
|
||||
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.Tables;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.alert.dao.SingleAlertDao;
|
||||
import org.apache.hertzbeat.alert.util.AlertUtil;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
@@ -27,6 +24,7 @@ import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
@@ -35,78 +33,49 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
@Component
|
||||
public class AlarmCacheManager {
|
||||
|
||||
private static final String CUSTOM_FIRING_ROW_KEY = "CUSTOM_FIRING_";
|
||||
|
||||
/**
|
||||
* The alarm in the process is triggered
|
||||
* rowKey - define id
|
||||
* columnKey - labels fingerprint
|
||||
* key - labels fingerprint
|
||||
*/
|
||||
private final Table<String, String, SingleAlert> pendingAlertMap;
|
||||
|
||||
private final Map<String, SingleAlert> pendingAlertMap;
|
||||
/**
|
||||
* The not recover alert
|
||||
* rowKey - define id
|
||||
* columnKey - labels fingerprint
|
||||
* key - labels fingerprint
|
||||
*/
|
||||
private final Table<String, String, SingleAlert> firingAlertMap;
|
||||
private final Map<String, SingleAlert> firingAlertMap;
|
||||
|
||||
public AlarmCacheManager(SingleAlertDao singleAlertDao) {
|
||||
this.pendingAlertMap = Tables.newCustomTable(new ConcurrentHashMap<>(8), ConcurrentHashMap::new);
|
||||
this.firingAlertMap = Tables.newCustomTable(new ConcurrentHashMap<>(8), ConcurrentHashMap::new);
|
||||
this.pendingAlertMap = new ConcurrentHashMap<>(8);
|
||||
this.firingAlertMap = new ConcurrentHashMap<>(8);
|
||||
List<SingleAlert> singleAlerts = singleAlertDao.querySingleAlertsByStatus(CommonConstants.ALERT_STATUS_FIRING);
|
||||
for (SingleAlert singleAlert : singleAlerts) {
|
||||
String fingerprint = AlertUtil.calculateFingerprint(singleAlert.getLabels());
|
||||
String defineId = singleAlert.getLabels().get(CommonConstants.LABEL_DEFINE_ID);
|
||||
if (StringUtils.isBlank(defineId)) {
|
||||
defineId = getCustomKey(fingerprint);
|
||||
}
|
||||
singleAlert.setId(null);
|
||||
this.firingAlertMap.put(defineId, fingerprint, singleAlert);
|
||||
this.firingAlertMap.put(fingerprint, singleAlert);
|
||||
}
|
||||
}
|
||||
|
||||
public void putPending(Long defineId, String fingerPrint, SingleAlert alert) {
|
||||
this.pendingAlertMap.put(String.valueOf(defineId), fingerPrint, alert);
|
||||
public void putPending(String fingerPrint, SingleAlert alert) {
|
||||
this.pendingAlertMap.put(fingerPrint, alert);
|
||||
}
|
||||
|
||||
public SingleAlert getPending(Long defineId, String fingerPrint) {
|
||||
return this.pendingAlertMap.get(String.valueOf(defineId), fingerPrint);
|
||||
public SingleAlert getPending(String fingerPrint) {
|
||||
return this.pendingAlertMap.get(fingerPrint);
|
||||
}
|
||||
|
||||
public void removePending(Long defineId, String fingerPrint) {
|
||||
this.pendingAlertMap.remove(String.valueOf(defineId), fingerPrint);
|
||||
}
|
||||
|
||||
public void putFiring(Long defineId, String fingerPrint, SingleAlert alert) {
|
||||
this.firingAlertMap.put(String.valueOf(defineId), fingerPrint, alert);
|
||||
public SingleAlert removePending(String fingerPrint) {
|
||||
return this.pendingAlertMap.remove(fingerPrint);
|
||||
}
|
||||
|
||||
public void putFiring(String fingerPrint, SingleAlert alert) {
|
||||
this.firingAlertMap.put(getCustomKey(fingerPrint), fingerPrint, alert);
|
||||
}
|
||||
|
||||
public SingleAlert getFiring(Long defineId, String fingerPrint) {
|
||||
SingleAlert singleAlert = this.firingAlertMap.get(String.valueOf(defineId), fingerPrint);
|
||||
if (null != singleAlert) {
|
||||
return singleAlert;
|
||||
}
|
||||
return getFiring(fingerPrint);
|
||||
}
|
||||
|
||||
public SingleAlert removeFiring(Long defineId, String fingerPrint) {
|
||||
SingleAlert singleAlert = this.firingAlertMap.remove(String.valueOf(defineId), fingerPrint);
|
||||
if (null == singleAlert) {
|
||||
return this.firingAlertMap.remove(getCustomKey(fingerPrint), fingerPrint);
|
||||
}
|
||||
return singleAlert;
|
||||
this.firingAlertMap.put(fingerPrint, alert);
|
||||
}
|
||||
|
||||
public SingleAlert getFiring(String fingerPrint) {
|
||||
return this.firingAlertMap.get(getCustomKey(fingerPrint), fingerPrint);
|
||||
return this.firingAlertMap.get(fingerPrint);
|
||||
}
|
||||
|
||||
private String getCustomKey(String fingerPrint) {
|
||||
return CUSTOM_FIRING_ROW_KEY + fingerPrint;
|
||||
public SingleAlert removeFiring(String fingerPrint) {
|
||||
return this.firingAlertMap.remove(fingerPrint);
|
||||
}
|
||||
}
|
||||
|
||||
+24
-27
@@ -17,9 +17,8 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.calculate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
|
||||
import org.apache.hertzbeat.alert.service.DataSourceService;
|
||||
import org.apache.hertzbeat.alert.util.AlertTemplateUtil;
|
||||
@@ -27,11 +26,11 @@ import org.apache.hertzbeat.alert.util.AlertUtil;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Periodic Alert Calculator
|
||||
@@ -55,9 +54,9 @@ public class PeriodicAlertCalculator {
|
||||
this.alarmCacheManager = alarmCacheManager;
|
||||
}
|
||||
|
||||
public void calculate(AlertDefine define) {
|
||||
if (!define.isEnable() || StringUtils.isEmpty(define.getExpr())) {
|
||||
log.error("Periodic define {} is disabled or expression is empty", define.getName());
|
||||
public void calculate(AlertDefine rule) {
|
||||
if (!rule.isEnable() || StringUtils.isEmpty(rule.getExpr())) {
|
||||
log.error("Periodic rule {} is disabled or expression is empty", rule.getName());
|
||||
return;
|
||||
}
|
||||
long currentTimeMilli = System.currentTimeMillis();
|
||||
@@ -67,8 +66,8 @@ public class PeriodicAlertCalculator {
|
||||
// the return result should be matched with threshold
|
||||
try {
|
||||
List<Map<String, Object>> results = dataSourceService.calculate(
|
||||
define.getDatasource(),
|
||||
define.getExpr()
|
||||
rule.getDatasource(),
|
||||
rule.getExpr()
|
||||
);
|
||||
// if no match the expr threshold, the results item map {'value': null} should be null and others field keep
|
||||
// if results has multi list, should trigger multi alert
|
||||
@@ -78,9 +77,8 @@ public class PeriodicAlertCalculator {
|
||||
for (Map<String, Object> result : results) {
|
||||
Map<String, String> fingerPrints = new HashMap<>(8);
|
||||
// here use the alert name as finger, not care the alert name may be changed
|
||||
fingerPrints.put(CommonConstants.LABEL_DEFINE_ID, String.valueOf(define.getId()));
|
||||
fingerPrints.put(CommonConstants.LABEL_ALERT_NAME, define.getName());
|
||||
fingerPrints.putAll(define.getLabels());
|
||||
fingerPrints.put(CommonConstants.LABEL_ALERT_NAME, rule.getName());
|
||||
fingerPrints.putAll(rule.getLabels());
|
||||
for (Map.Entry<String, Object> entry : result.entrySet()) {
|
||||
if (entry.getValue() != null && !VALUE.equals(entry.getKey())
|
||||
&& !TIMESTAMP.equals(entry.getKey())) {
|
||||
@@ -89,33 +87,32 @@ public class PeriodicAlertCalculator {
|
||||
}
|
||||
if (result.get(VALUE) == null) {
|
||||
// recovery the alert
|
||||
handleRecoveredAlert(define.getId(), fingerPrints);
|
||||
handleRecoveredAlert(fingerPrints);
|
||||
continue;
|
||||
}
|
||||
Map<String, Object> fieldValueMap = new HashMap<>(8);
|
||||
fieldValueMap.putAll(define.getLabels());
|
||||
fieldValueMap.put(CommonConstants.LABEL_ALERT_NAME, define.getName());
|
||||
fieldValueMap.putAll(rule.getLabels());
|
||||
fieldValueMap.put(CommonConstants.LABEL_ALERT_NAME, rule.getName());
|
||||
for (Map.Entry<String, Object> entry : result.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
fieldValueMap.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
afterThresholdRuleMatch(currentTimeMilli, fingerPrints, fieldValueMap, define);
|
||||
afterThresholdRuleMatch(currentTimeMilli, fingerPrints, fieldValueMap, rule);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// ignore the query exception eg: no result, timeout, etc
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Calculate periodic define {} failed: {}", define.getName(), e.getMessage());
|
||||
log.error("Calculate periodic rule {} failed: {}", rule.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void afterThresholdRuleMatch(long currentTimeMilli, Map<String, String> fingerPrints,
|
||||
Map<String, Object> fieldValueMap, AlertDefine define) {
|
||||
Long defineId = define.getId();
|
||||
String fingerprint = AlertUtil.calculateFingerprint(fingerPrints);
|
||||
SingleAlert existingAlert = alarmCacheManager.getPending(defineId, fingerprint);
|
||||
SingleAlert existingAlert = alarmCacheManager.getPending(fingerprint);
|
||||
Map<String, String> labels = new HashMap<>(8);
|
||||
fieldValueMap.putAll(define.getLabels());
|
||||
labels.putAll(fingerPrints);
|
||||
@@ -136,11 +133,11 @@ public class PeriodicAlertCalculator {
|
||||
// If required trigger times is 1, set to firing status directly
|
||||
if (requiredTimes <= 1) {
|
||||
newAlert.setStatus(CommonConstants.ALERT_STATUS_FIRING);
|
||||
alarmCacheManager.putFiring(defineId, fingerprint, newAlert);
|
||||
alarmCacheManager.putFiring(fingerprint, newAlert);
|
||||
alarmCommonReduce.reduceAndSendAlarm(newAlert.clone());
|
||||
} else {
|
||||
// Otherwise put into pending queue first
|
||||
alarmCacheManager.putPending(defineId, fingerprint, newAlert);
|
||||
alarmCacheManager.putPending(fingerprint, newAlert);
|
||||
}
|
||||
} else {
|
||||
// Update existing alert
|
||||
@@ -150,17 +147,17 @@ public class PeriodicAlertCalculator {
|
||||
// Check if required trigger times reached
|
||||
if (existingAlert.getStatus().equals(CommonConstants.ALERT_STATUS_PENDING) && existingAlert.getTriggerTimes() >= requiredTimes) {
|
||||
// Reached trigger times threshold, change to firing status
|
||||
alarmCacheManager.removePending(defineId, fingerprint);
|
||||
alarmCacheManager.removePending(fingerprint);
|
||||
existingAlert.setStatus(CommonConstants.ALERT_STATUS_FIRING);
|
||||
alarmCacheManager.putFiring(defineId, fingerprint, existingAlert);
|
||||
alarmCacheManager.putFiring(fingerprint, existingAlert);
|
||||
alarmCommonReduce.reduceAndSendAlarm(existingAlert.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRecoveredAlert(Long defineId, Map<String, String> fingerprints) {
|
||||
private void handleRecoveredAlert(Map<String, String> fingerprints) {
|
||||
String fingerprint = AlertUtil.calculateFingerprint(fingerprints);
|
||||
SingleAlert firingAlert = alarmCacheManager.removeFiring(defineId, fingerprint);
|
||||
SingleAlert firingAlert = alarmCacheManager.removeFiring(fingerprint);
|
||||
if (firingAlert != null) {
|
||||
// todo consider multi times to tig for resolved alert
|
||||
firingAlert.setTriggerTimes(1);
|
||||
@@ -168,7 +165,7 @@ public class PeriodicAlertCalculator {
|
||||
firingAlert.setStatus(CommonConstants.ALERT_STATUS_RESOLVED);
|
||||
alarmCommonReduce.reduceAndSendAlarm(firingAlert.clone());
|
||||
}
|
||||
alarmCacheManager.removePending(defineId, fingerprint);
|
||||
alarmCacheManager.removePending(fingerprint);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-17
@@ -183,11 +183,9 @@ public class RealTimeAlertCalculator {
|
||||
if (StringUtils.isBlank(expr)) {
|
||||
continue;
|
||||
}
|
||||
Long defineId = define.getId();
|
||||
Map<String, String> commonFingerPrints = new HashMap<>(8);
|
||||
commonFingerPrints.put(CommonConstants.LABEL_INSTANCE, instance);
|
||||
// here use the alert name as finger, not care the alert name may be changed
|
||||
commonFingerPrints.put(CommonConstants.LABEL_DEFINE_ID, String.valueOf(define.getId()));
|
||||
commonFingerPrints.put(CommonConstants.LABEL_ALERT_NAME, define.getName());
|
||||
commonFingerPrints.put(CommonConstants.LABEL_INSTANCE_NAME, instanceName);
|
||||
commonFingerPrints.put(CommonConstants.LABEL_INSTANCE_HOST, instanceHost);
|
||||
@@ -202,9 +200,9 @@ public class RealTimeAlertCalculator {
|
||||
try {
|
||||
if (match) {
|
||||
// If the threshold rule matches, the number of times the threshold has been triggered is determined and an alarm is triggered
|
||||
afterThresholdRuleMatch(defineId, currentTimeMilli, commonFingerPrints, fieldValueMap, define, annotations);
|
||||
afterThresholdRuleMatch(currentTimeMilli, commonFingerPrints, fieldValueMap, define, annotations);
|
||||
} else {
|
||||
handleRecoveredAlert(defineId, commonFingerPrints);
|
||||
handleRecoveredAlert(commonFingerPrints);
|
||||
}
|
||||
// if this threshold pre compile success, ignore blew
|
||||
continue;
|
||||
@@ -256,9 +254,9 @@ public class RealTimeAlertCalculator {
|
||||
boolean match = execAlertExpression(fieldValueMap, expr, false);
|
||||
try {
|
||||
if (match) {
|
||||
afterThresholdRuleMatch(defineId, currentTimeMilli, fingerPrints, fieldValueMap, define, annotations);
|
||||
afterThresholdRuleMatch(currentTimeMilli, fingerPrints, fieldValueMap, define, annotations);
|
||||
} else {
|
||||
handleRecoveredAlert(defineId, fingerPrints);
|
||||
handleRecoveredAlert(fingerPrints);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
@@ -336,9 +334,9 @@ public class RealTimeAlertCalculator {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void handleRecoveredAlert(Long defineId, Map<String, String> fingerprints) {
|
||||
private void handleRecoveredAlert(Map<String, String> fingerprints) {
|
||||
String fingerprint = AlertUtil.calculateFingerprint(fingerprints);
|
||||
SingleAlert firingAlert = alarmCacheManager.removeFiring(defineId, fingerprint);
|
||||
SingleAlert firingAlert = alarmCacheManager.removeFiring(fingerprint);
|
||||
if (firingAlert != null) {
|
||||
// todo consider multi times to tig for resolved alert
|
||||
firingAlert.setTriggerTimes(1);
|
||||
@@ -346,14 +344,13 @@ public class RealTimeAlertCalculator {
|
||||
firingAlert.setStatus(CommonConstants.ALERT_STATUS_RESOLVED);
|
||||
alarmCommonReduce.reduceAndSendAlarm(firingAlert.clone());
|
||||
}
|
||||
alarmCacheManager.removePending(defineId, fingerprint);
|
||||
alarmCacheManager.removePending(fingerprint);
|
||||
}
|
||||
|
||||
private void afterThresholdRuleMatch(long defineId, long currentTimeMilli, Map<String, String> fingerPrints,
|
||||
Map<String, Object> fieldValueMap, AlertDefine define,
|
||||
Map<String, String> annotations) {
|
||||
private void afterThresholdRuleMatch(long currentTimeMilli, Map<String, String> fingerPrints,
|
||||
Map<String, Object> fieldValueMap, AlertDefine define, Map<String, String> annotations) {
|
||||
String fingerprint = AlertUtil.calculateFingerprint(fingerPrints);
|
||||
SingleAlert existingAlert = alarmCacheManager.getPending(defineId, fingerprint);
|
||||
SingleAlert existingAlert = alarmCacheManager.getPending(fingerprint);
|
||||
fieldValueMap.putAll(define.getLabels());
|
||||
int requiredTimes = define.getTimes() == null ? 1 : define.getTimes();
|
||||
if (existingAlert == null) {
|
||||
@@ -385,11 +382,11 @@ public class RealTimeAlertCalculator {
|
||||
// If required trigger times is 1, set to firing status directly
|
||||
if (requiredTimes <= 1) {
|
||||
newAlert.setStatus(CommonConstants.ALERT_STATUS_FIRING);
|
||||
alarmCacheManager.putFiring(defineId, fingerprint, newAlert);
|
||||
alarmCacheManager.putFiring(fingerprint, newAlert);
|
||||
alarmCommonReduce.reduceAndSendAlarm(newAlert.clone());
|
||||
} else {
|
||||
// Otherwise put into pending queue first
|
||||
alarmCacheManager.putPending(define.getId(), fingerprint, newAlert);
|
||||
alarmCacheManager.putPending(fingerprint, newAlert);
|
||||
}
|
||||
} else {
|
||||
// Update existing alert
|
||||
@@ -399,9 +396,9 @@ public class RealTimeAlertCalculator {
|
||||
// Check if required trigger times reached
|
||||
if (existingAlert.getStatus().equals(CommonConstants.ALERT_STATUS_PENDING) && existingAlert.getTriggerTimes() >= requiredTimes) {
|
||||
// Reached trigger times threshold, change to firing status
|
||||
alarmCacheManager.removePending(defineId, fingerprint);
|
||||
alarmCacheManager.removePending(fingerprint);
|
||||
existingAlert.setStatus(CommonConstants.ALERT_STATUS_FIRING);
|
||||
alarmCacheManager.putFiring(defineId, fingerprint, existingAlert);
|
||||
alarmCacheManager.putFiring(fingerprint, existingAlert);
|
||||
alarmCommonReduce.reduceAndSendAlarm(existingAlert.clone());
|
||||
}
|
||||
}
|
||||
|
||||
-6
@@ -28,9 +28,6 @@ import org.apache.hertzbeat.alert.dto.ExportAlertDefineDTO;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineImExportService;
|
||||
import org.apache.hertzbeat.alert.service.AlertDefineService;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.util.LogUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -44,15 +41,12 @@ public abstract class AlertDefineAbstractImExportServiceImpl implements AlertDef
|
||||
@Lazy
|
||||
private AlertDefineService alertDefineService;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AlertDefineAbstractImExportServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void importConfig(InputStream is) {
|
||||
var formList = parseImport(is)
|
||||
.stream()
|
||||
.map(this::convert)
|
||||
.toList();
|
||||
LogUtil.info(logger, "Importing alert defines from {0}", formList);
|
||||
if (!CollectionUtils.isEmpty(formList)) {
|
||||
formList.forEach(alertDefine -> {
|
||||
alertDefineService.validate(alertDefine, false);
|
||||
|
||||
+1
-6
@@ -27,14 +27,11 @@ import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
|
||||
import org.apache.hertzbeat.common.entity.alerter.NoticeTemplate;
|
||||
import org.apache.hertzbeat.common.support.exception.SendMessageException;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.hertzbeat.common.util.LogUtil;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -65,7 +62,6 @@ public class AlibabaSmsClientImpl implements SmsClient {
|
||||
private final String accessKeySecret;
|
||||
private final String signName;
|
||||
private final String templateCode;
|
||||
private static final Logger logger = LoggerFactory.getLogger(AlibabaSmsClientImpl.class);
|
||||
|
||||
public AlibabaSmsClientImpl(AlibabaSmsProperties config) {
|
||||
if (config != null) {
|
||||
@@ -177,7 +173,7 @@ public class AlibabaSmsClientImpl implements SmsClient {
|
||||
log.info("Successfully sent SMS to phone: {}", phoneNumber);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.warn(logger, "Failed to send SMS: {0}", e.getMessage());
|
||||
log.warn("Failed to send SMS: {}", e.getMessage());
|
||||
throw new SendMessageException(e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -196,7 +192,6 @@ public class AlibabaSmsClientImpl implements SmsClient {
|
||||
// Step 4: Build authorization header
|
||||
return ALGORITHM + " Credential=" + accessKeyId + ",SignedHeaders=host;x-acs-action;x-acs-content-sha256;x-acs-date;" + "x-acs-signature-nonce;x-acs-version,Signature=" + signature;
|
||||
} catch (Exception e) {
|
||||
LogUtil.warn(logger, "Failed to calculate authorization {0}", e.getMessage());
|
||||
throw new RuntimeException("Failed to calculate authorization", e);
|
||||
}
|
||||
}
|
||||
|
||||
-135
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.alert.calculate;
|
||||
|
||||
import org.apache.hertzbeat.alert.dao.SingleAlertDao;
|
||||
import org.apache.hertzbeat.alert.util.AlertUtil;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* alert cache manager test
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class AlarmCacheManagerTest {
|
||||
|
||||
@Mock
|
||||
private SingleAlertDao singleAlertDao;
|
||||
|
||||
private AlarmCacheManager alarmCacheManager;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
labels.put(CommonConstants.LABEL_ALERT_SEVERITY, CommonConstants.ALERT_SEVERITY_CRITICAL);
|
||||
labels.put(CommonConstants.LABEL_DEFINE_ID, String.valueOf(1L));
|
||||
SingleAlert alert = new SingleAlert();
|
||||
alert.setContent("Alert cache manager test");
|
||||
alert.setLabels(labels);
|
||||
when(singleAlertDao.querySingleAlertsByStatus(CommonConstants.ALERT_STATUS_FIRING)).thenReturn(Collections.singletonList(alert));
|
||||
alarmCacheManager = new AlarmCacheManager(singleAlertDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInit() {
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
labels.put(CommonConstants.LABEL_ALERT_SEVERITY, CommonConstants.ALERT_SEVERITY_CRITICAL);
|
||||
labels.put(CommonConstants.LABEL_DEFINE_ID, String.valueOf(1L));
|
||||
|
||||
String fingerprint = AlertUtil.calculateFingerprint(labels);
|
||||
SingleAlert firingSingleAlert = alarmCacheManager.getFiring(1L, fingerprint);
|
||||
assertNotNull(firingSingleAlert);
|
||||
assertEquals("Alert cache manager test", firingSingleAlert.getContent());
|
||||
alarmCacheManager.removeFiring(1L, fingerprint);
|
||||
firingSingleAlert = alarmCacheManager.getFiring(1L, fingerprint);
|
||||
assertNull(firingSingleAlert);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPending() {
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
labels.put(CommonConstants.LABEL_ALERT_SEVERITY, CommonConstants.ALERT_SEVERITY_CRITICAL);
|
||||
labels.put(CommonConstants.ALERT_SEVERITY_INFO, CommonConstants.ALERT_STATUS_PENDING);
|
||||
labels.put(CommonConstants.LABEL_DEFINE_ID, String.valueOf(2L));
|
||||
|
||||
SingleAlert alert = new SingleAlert();
|
||||
alert.setContent("Alert cache manager test");
|
||||
alert.setLabels(labels);
|
||||
|
||||
String fingerprint = AlertUtil.calculateFingerprint(alert.getLabels());
|
||||
alarmCacheManager.putPending(2L, fingerprint, alert);
|
||||
|
||||
SingleAlert pendingSingleAlert = alarmCacheManager.getPending(2L, fingerprint);
|
||||
assertNotNull(pendingSingleAlert);
|
||||
alarmCacheManager.removePending(2L, fingerprint);
|
||||
pendingSingleAlert = alarmCacheManager.getPending(2L, fingerprint);
|
||||
assertNull(pendingSingleAlert);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFiring() {
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
labels.put(CommonConstants.LABEL_ALERT_SEVERITY, CommonConstants.ALERT_SEVERITY_CRITICAL);
|
||||
labels.put(CommonConstants.ALERT_SEVERITY_INFO, CommonConstants.ALERT_STATUS_PENDING);
|
||||
labels.put(CommonConstants.LABEL_DEFINE_ID, String.valueOf(3L));
|
||||
|
||||
SingleAlert alert = new SingleAlert();
|
||||
alert.setContent("Alert cache manager test");
|
||||
alert.setLabels(labels);
|
||||
|
||||
String fingerprint = AlertUtil.calculateFingerprint(alert.getLabels());
|
||||
alarmCacheManager.putFiring(3L, fingerprint, alert);
|
||||
|
||||
SingleAlert firingSingleAlert = alarmCacheManager.getFiring(3L, fingerprint);
|
||||
assertNotNull(firingSingleAlert);
|
||||
alarmCacheManager.removeFiring(3L, fingerprint);
|
||||
firingSingleAlert = alarmCacheManager.getFiring(3L, fingerprint);
|
||||
assertNull(firingSingleAlert);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHistorical() {
|
||||
SingleAlert alert = new SingleAlert();
|
||||
alert.setContent("Alert cache manager test");
|
||||
alert.setLabels(Collections.singletonMap(CommonConstants.LABEL_ALERT_SEVERITY, CommonConstants.ALERT_SEVERITY_CRITICAL));
|
||||
when(singleAlertDao.querySingleAlertsByStatus(CommonConstants.ALERT_STATUS_FIRING)).thenReturn(Collections.singletonList(alert));
|
||||
alarmCacheManager = new AlarmCacheManager(singleAlertDao);
|
||||
|
||||
String fingerprint = AlertUtil.calculateFingerprint(alert.getLabels());
|
||||
SingleAlert historicalSingleAlert = alarmCacheManager.getFiring(4L, fingerprint);
|
||||
assertNotNull(historicalSingleAlert);
|
||||
SingleAlert singleAlert = alarmCacheManager.removeFiring(4L, fingerprint);
|
||||
assertNotNull(singleAlert);
|
||||
historicalSingleAlert = alarmCacheManager.getFiring(4L, fingerprint);
|
||||
assertNull(historicalSingleAlert);
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -42,7 +42,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -93,12 +92,12 @@ class PeriodicAlertCalculatorTest {
|
||||
result.put("__value__", 95.0); // Non-null, matched with threshold
|
||||
result.put("__timestamp__", System.currentTimeMillis());
|
||||
when(dataSourceService.calculate(anyString(), anyString())).thenReturn(List.of(result));
|
||||
when(alarmCacheManager.getPending(eq(rule.getId()), anyString())).thenReturn(null);
|
||||
when(alarmCacheManager.getPending(anyString())).thenReturn(null);
|
||||
periodicAlertCalculator.calculate(rule);
|
||||
// Verify that putFiring is called
|
||||
ArgumentCaptor<String> idCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<SingleAlert> alertCaptor = ArgumentCaptor.forClass(SingleAlert.class);
|
||||
verify(alarmCacheManager).putFiring(eq(rule.getId()), idCaptor.capture(), alertCaptor.capture());
|
||||
verify(alarmCacheManager).putFiring(idCaptor.capture(), alertCaptor.capture());
|
||||
// Assertion alarm status and content
|
||||
SingleAlert alert = alertCaptor.getValue();
|
||||
assertAll(() -> assertEquals(CommonConstants.ALERT_STATUS_FIRING, alert.getStatus()),
|
||||
@@ -113,7 +112,7 @@ class PeriodicAlertCalculatorTest {
|
||||
result.put("__timestamp__", System.currentTimeMillis());
|
||||
when(dataSourceService.calculate(anyString(), anyString())).thenReturn(List.of(result));
|
||||
periodicAlertCalculator.calculate(rule);
|
||||
verify(alarmCacheManager, times(0)).putFiring(any(), any(), any());
|
||||
verify(alarmCacheManager, times(0)).putFiring(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,7 +126,7 @@ class PeriodicAlertCalculatorTest {
|
||||
.triggerTimes(2).startAt(System.currentTimeMillis() - 60000)
|
||||
.activeAt(System.currentTimeMillis() - 30000)
|
||||
.build();
|
||||
when(alarmCacheManager.removeFiring(eq(rule.getId()), anyString())).thenReturn(pendingAlert);
|
||||
when(alarmCacheManager.removeFiring(anyString())).thenReturn(pendingAlert);
|
||||
when(dataSourceService.calculate(anyString(), anyString())).thenReturn(List.of(result));
|
||||
periodicAlertCalculator.calculate(rule);
|
||||
ArgumentCaptor<SingleAlert> resolvedCaptor = ArgumentCaptor.forClass(SingleAlert.class);
|
||||
|
||||
+6
-9
@@ -132,7 +132,6 @@ public class RealTimeAlertCalculatorMatchTest {
|
||||
|
||||
|
||||
AlertDefine matchDefine = new AlertDefine();
|
||||
matchDefine.setId(1L);
|
||||
matchDefine.setName("test");
|
||||
matchDefine.setExpr(
|
||||
"equals(__app__,\"prometheus\") && "
|
||||
@@ -152,8 +151,8 @@ public class RealTimeAlertCalculatorMatchTest {
|
||||
|
||||
Thread.sleep(3000);
|
||||
|
||||
verify(alarmCacheManager, times(1)).getPending(any(), any());
|
||||
verify(alarmCacheManager, times(1)).putFiring(any(), any(), any());
|
||||
verify(alarmCacheManager, times(1)).getPending(any());
|
||||
verify(alarmCacheManager, times(1)).putFiring(any(), any());
|
||||
verify(alarmCommonReduce, times(1)).reduceAndSendAlarm(any());
|
||||
}
|
||||
|
||||
@@ -181,7 +180,6 @@ public class RealTimeAlertCalculatorMatchTest {
|
||||
CollectRep.MetricsData metricsData = builder.build();
|
||||
|
||||
AlertDefine matchDefine = new AlertDefine();
|
||||
matchDefine.setId(1L);
|
||||
matchDefine.setName("test");
|
||||
matchDefine.setExpr("equals(__app__,\"prometheus\") && equals(__metrics__,\"canal_instance\") && metric_value > 0");
|
||||
matchDefine.setTemplate("Canal instance val: ${value}%");
|
||||
@@ -196,8 +194,8 @@ public class RealTimeAlertCalculatorMatchTest {
|
||||
|
||||
Thread.sleep(3000);
|
||||
|
||||
verify(alarmCacheManager, times(1)).getPending(any(), any());
|
||||
verify(alarmCacheManager, times(1)).putFiring(any(), any(), any());
|
||||
verify(alarmCacheManager, times(1)).getPending(any());
|
||||
verify(alarmCacheManager, times(1)).putFiring(any(), any());
|
||||
verify(alarmCommonReduce, times(1)).reduceAndSendAlarm(any());
|
||||
}
|
||||
|
||||
@@ -231,7 +229,6 @@ public class RealTimeAlertCalculatorMatchTest {
|
||||
CollectRep.MetricsData metricsData = builder.build();
|
||||
|
||||
AlertDefine matchDefine = new AlertDefine();
|
||||
matchDefine.setId(1L);
|
||||
matchDefine.setName("test");
|
||||
matchDefine.setExpr("equals(__app__,\"springboot3\") && equals(__metrics__,\"available\") && equals(__instance__, \"518679137103104\") && responseTime > 0");
|
||||
matchDefine.setTemplate("Canal instance val: ${value}%");
|
||||
@@ -246,8 +243,8 @@ public class RealTimeAlertCalculatorMatchTest {
|
||||
|
||||
Thread.sleep(3000);
|
||||
|
||||
verify(alarmCacheManager, times(1)).getPending(any(), any());
|
||||
verify(alarmCacheManager, times(1)).putFiring(any(), any(), any());
|
||||
verify(alarmCacheManager, times(1)).getPending(any());
|
||||
verify(alarmCacheManager, times(1)).putFiring(any(), any());
|
||||
verify(alarmCommonReduce, times(1)).reduceAndSendAlarm(any());
|
||||
}
|
||||
|
||||
|
||||
+7
-10
@@ -42,6 +42,7 @@ import javax.management.remote.JMXServiceURL;
|
||||
import javax.management.remote.rmi.RMIConnectorServer;
|
||||
import javax.naming.Context;
|
||||
import javax.rmi.ssl.SslRMIClientSocketFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.collector.collect.AbstractCollect;
|
||||
import org.apache.hertzbeat.collector.collect.common.cache.AbstractConnection;
|
||||
import org.apache.hertzbeat.collector.collect.common.cache.CacheIdentifier;
|
||||
@@ -53,15 +54,13 @@ import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.entity.job.protocol.JmxProtocol;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.util.CommonUtil;
|
||||
import org.apache.hertzbeat.common.util.LogUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* jmx protocol acquisition implementation
|
||||
*/
|
||||
@Slf4j
|
||||
public class JmxCollectImpl extends AbstractCollect {
|
||||
|
||||
private static final String JMX_URL_PREFIX = "service:jmx:rmi:///jndi/rmi://";
|
||||
@@ -76,8 +75,6 @@ public class JmxCollectImpl extends AbstractCollect {
|
||||
|
||||
private final ClassLoader jmxClassLoader;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JmxCollectImpl.class);
|
||||
|
||||
public JmxCollectImpl() {
|
||||
jmxClassLoader = new JmxClassLoader(ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
@@ -198,12 +195,12 @@ public class JmxCollectImpl extends AbstractCollect {
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
String errorMsg = CommonUtil.getMessageFromThrowable(exception);
|
||||
LogUtil.error(logger, "JMX IOException: {0}", errorMsg);
|
||||
log.error("JMX IOException :{}", errorMsg);
|
||||
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
|
||||
builder.setMsg(errorMsg);
|
||||
} catch (Exception e) {
|
||||
String errorMsg = CommonUtil.getMessageFromThrowable(e);
|
||||
LogUtil.error(logger, "JMX Error: {0}", errorMsg);
|
||||
log.error("JMX Error :{}", errorMsg);
|
||||
builder.setCode(CollectRep.Code.FAIL);
|
||||
builder.setMsg(errorMsg);
|
||||
} finally {
|
||||
@@ -224,7 +221,7 @@ public class JmxCollectImpl extends AbstractCollect {
|
||||
for (Attribute attribute : attributeList.asList()) {
|
||||
Object value = attribute.getValue();
|
||||
if (value == null) {
|
||||
LogUtil.info(logger, "attribute {0} value is null.", attribute.getName());
|
||||
log.info("attribute {} value is null.", attribute.getName());
|
||||
continue;
|
||||
}
|
||||
if (value instanceof Number || value instanceof String || value instanceof ObjectName
|
||||
@@ -248,7 +245,7 @@ public class JmxCollectImpl extends AbstractCollect {
|
||||
}
|
||||
attributeValueMap.put(attribute.getName(), builder.toString());
|
||||
} else {
|
||||
LogUtil.warn(logger, "attribute value type {0} not support.", value.getClass().getName());
|
||||
log.warn("attribute value type {} not support.", value.getClass().getName());
|
||||
}
|
||||
}
|
||||
return attributeValueMap;
|
||||
@@ -322,7 +319,7 @@ public class JmxCollectImpl extends AbstractCollect {
|
||||
connectionCommonCache.addCache(identifier, new JmxConnect(conn));
|
||||
return conn;
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(logger, "Failed to connect to JMX connection: {0}", e.getMessage());
|
||||
log.error("Failed to connect to JMX server: {}", e.getMessage());
|
||||
throw new IOException("Failed to connect to JMX server: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
-5
@@ -87,11 +87,6 @@ public interface CommonConstants {
|
||||
*/
|
||||
String LABEL_INSTANCE = "instance";
|
||||
|
||||
/**
|
||||
* label key: defineid
|
||||
*/
|
||||
String LABEL_DEFINE_ID = "defineid";
|
||||
|
||||
/**
|
||||
* label key: alert name
|
||||
*/
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
package org.apache.hertzbeat.common.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
@@ -46,7 +44,6 @@ public final class JsonUtil {
|
||||
OBJECT_MAPPER
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
|
||||
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
|
||||
.registerModule(new JavaTimeModule());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.common.util;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* Log utility class that provides formatted logging methods with location information.
|
||||
* This class enhances standard SLF4J logging by automatically adding caller location details.
|
||||
*/
|
||||
public class LogUtil {
|
||||
|
||||
private static final String TEMPLATE_REGEX = "\\{\\d}";
|
||||
|
||||
/**
|
||||
* Print debug level formatted log
|
||||
* Example: LogUtil.debug(logger, "hello,{0},here has a {1} exception", "other information");
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void debug(Logger logger, String msg, Object... params) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
if (ArrayUtils.isEmpty(params)) {
|
||||
logger.debug(LogUtil.buildLocationInfo() + msg);
|
||||
} else {
|
||||
logger.debug(LogUtil.buildLocationInfo() + format(msg, params));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print info level formatted log
|
||||
* Example: LogUtil.info(logger, "hello,{0},{1} exception", "dear", "database operation");
|
||||
*/
|
||||
public static void info(Logger logger, String msg, Object... params) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
if (ArrayUtils.isEmpty(params)) {
|
||||
logger.info(LogUtil.buildLocationInfo() + msg);
|
||||
} else {
|
||||
logger.info(LogUtil.buildLocationInfo() + format(msg, params));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print warn level formatted log
|
||||
*/
|
||||
public static void warn(Logger logger, String msg, Object... params) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
if (ArrayUtils.isEmpty(params)) {
|
||||
logger.warn(LogUtil.buildLocationInfo() + msg);
|
||||
} else {
|
||||
logger.warn(LogUtil.buildLocationInfo() + format(msg, params));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error level formatted log, use {0},{1},.. for parameter replacement
|
||||
* Example: LogUtil.error(logger, "hello,{0}, a {1} exception occurred here", "dear", "database operation");
|
||||
*/
|
||||
public static void error(Logger logger, String msg, Object... params) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
if (ArrayUtils.isEmpty(params)) {
|
||||
logger.error(LogUtil.buildLocationInfo() + msg);
|
||||
} else {
|
||||
logger.error(LogUtil.buildLocationInfo() + format(msg, params));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print warn level formatted log with exception, use {0},{1},.. for parameter replacement
|
||||
* Example: LogUtil.warn(logger, e, "hello,{0}, a {1} exception occurred here", "dear", "database operation");
|
||||
*/
|
||||
public static void warn(Logger logger, Throwable e, String msg, Object... params) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
if (ArrayUtils.isEmpty(params)) {
|
||||
logger.warn(LogUtil.buildLocationInfo() + msg, e);
|
||||
} else {
|
||||
logger.warn(LogUtil.buildLocationInfo() + format(msg, params), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print error level formatted log with exception, use {0},{1},.. for parameter replacement
|
||||
* Example: LogUtil.error(logger, e, "hello,{0}, a {1} exception occurred here", "dear", "database operation");
|
||||
*/
|
||||
public static void error(Logger logger, Throwable e, String msg, Object... params) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
if (ArrayUtils.isEmpty(params)) {
|
||||
logger.error(LogUtil.buildLocationInfo() + msg, e);
|
||||
} else {
|
||||
logger.error(LogUtil.buildLocationInfo() + format(msg, params), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the class name, method and line number that calls LogUtil
|
||||
*
|
||||
* @return location information string
|
||||
*/
|
||||
private static String buildLocationInfo() {
|
||||
StringBuilder header = new StringBuilder();
|
||||
// LOG4J2-1029 new Throwable().getStackTrace is faster than Thread.currentThread().getStackTrace().
|
||||
final StackTraceElement[] stackTraceElements = new Throwable().getStackTrace();
|
||||
|
||||
for (int i = 0; i < stackTraceElements.length - 1; i++) {
|
||||
StackTraceElement currentStackTrace = stackTraceElements[i];
|
||||
StackTraceElement nextStackTrace = stackTraceElements[i + 1];
|
||||
|
||||
// If current stack trace is in LogUtil
|
||||
// and next stack trace is not in LogUtil
|
||||
// then the next node is the caller of LogUtil
|
||||
if (LogUtil.class.getName().equals(currentStackTrace.getClassName())
|
||||
&& !LogUtil.class.getName().equals(nextStackTrace.getClassName())) {
|
||||
String stackTrace = nextStackTrace.toString();
|
||||
header.append(" ").append(StringUtils.removeStart(stackTrace, nextStackTrace.getClassName() + "."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return header.append(":").toString();
|
||||
}
|
||||
|
||||
private static String format(String msg, Object... params) {
|
||||
if (StringUtils.isEmpty(msg)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
if (params != null && params.length > 0) {
|
||||
msg = MessageFormat.format(msg, params);
|
||||
}
|
||||
return msg.replaceAll(TEMPLATE_REGEX, StringUtils.EMPTY);
|
||||
}
|
||||
|
||||
private static String toString(Object object) {
|
||||
return ToStringBuilder.reflectionToString(object, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.common.util;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.slf4j.Logger;
|
||||
import java.lang.reflect.Method;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.contains;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class LogUtilTest {
|
||||
|
||||
@Mock
|
||||
private Logger mockLogger;
|
||||
|
||||
private AutoCloseable mocks;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() throws Exception {
|
||||
if (mocks != null) {
|
||||
mocks.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFormat_noParams_returnsOriginalMessage() throws Exception {
|
||||
String original = "hello world";
|
||||
Method formatMethod = LogUtil.class.getDeclaredMethod("format", String.class, Object[].class);
|
||||
formatMethod.setAccessible(true);
|
||||
String formatted = (String) formatMethod.invoke(null, original, new Object[0]);
|
||||
assertEquals(original, formatted);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFormat_withParams_replacesPlaceholders() throws Exception {
|
||||
String template = "hello,{0}, world {1}!";
|
||||
Method formatMethod = LogUtil.class.getDeclaredMethod("format", String.class, Object[].class);
|
||||
formatMethod.setAccessible(true);
|
||||
Object[] params = {"Alice", 123};
|
||||
String result = (String) formatMethod.invoke(null, template, params);
|
||||
assertTrue(result.contains("hello,Alice"));
|
||||
assertTrue(result.contains("world 123!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDebug_noParams_logsRawMessage() {
|
||||
when(mockLogger.isDebugEnabled()).thenReturn(true);
|
||||
String msg = "test-debug";
|
||||
LogUtil.debug(mockLogger, msg);
|
||||
verify(mockLogger).debug(contains(msg));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDebug_withParams_logsFormattedMessage() {
|
||||
when(mockLogger.isDebugEnabled()).thenReturn(true);
|
||||
LogUtil.debug(mockLogger, "user={0}", "Bob");
|
||||
verify(mockLogger).debug(contains("user=Bob"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInfo_levelOff_doesNotLog() {
|
||||
when(mockLogger.isInfoEnabled()).thenReturn(false);
|
||||
LogUtil.info(mockLogger, "should-not-log");
|
||||
verify(mockLogger, never()).info(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWarn_withException_logsMessageAndException() {
|
||||
when(mockLogger.isWarnEnabled()).thenReturn(true);
|
||||
RuntimeException ex = new RuntimeException("warn-ex");
|
||||
LogUtil.warn(mockLogger, ex, "warning {0}", "occurred");
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
verify(mockLogger).warn(captor.capture(), eq(ex));
|
||||
assertTrue(captor.getValue().contains("warning occurred"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testError_withExceptionAndParams_logsError() {
|
||||
when(mockLogger.isErrorEnabled()).thenReturn(true);
|
||||
RuntimeException ex = new RuntimeException("err");
|
||||
LogUtil.error(mockLogger, ex, "fail code {0}", 500);
|
||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||
verify(mockLogger).error(captor.capture(), eq(ex));
|
||||
assertTrue(captor.getValue().contains("fail code 500"));
|
||||
}
|
||||
}
|
||||
-8
@@ -121,14 +121,6 @@ public class MonitorsController {
|
||||
monitorService.export(ids, type, res);
|
||||
}
|
||||
|
||||
@GetMapping("/export/all")
|
||||
@Operation(summary = "export all monitor config", description = "export all monitor config")
|
||||
public void exportAll(
|
||||
@Parameter(description = "Export Type:JSON,EXCEL,YAML") @RequestParam(defaultValue = "JSON") String type,
|
||||
HttpServletResponse res) throws Exception {
|
||||
monitorService.exportAll(type, res);
|
||||
}
|
||||
|
||||
@PostMapping("/import")
|
||||
@Operation(summary = "import monitor config", description = "import monitor config")
|
||||
public ResponseEntity<Message<Void>> export(MultipartFile file) throws Exception {
|
||||
|
||||
-9
@@ -173,15 +173,6 @@ public interface MonitorService {
|
||||
*/
|
||||
void export(List<Long> ids, String type, HttpServletResponse res) throws Exception;
|
||||
|
||||
/**
|
||||
* Export All Monitoring Configuration
|
||||
*
|
||||
* @param type file type
|
||||
* @param res response
|
||||
* @throws Exception This exception will be thrown if the export fails
|
||||
*/
|
||||
void exportAll(String type, HttpServletResponse res) throws Exception;
|
||||
|
||||
/**
|
||||
* Import Monitoring Configuration
|
||||
*
|
||||
|
||||
-12
@@ -235,18 +235,6 @@ public class MonitorServiceImpl implements MonitorService {
|
||||
imExportService.exportConfig(res.getOutputStream(), ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportAll(String type, HttpServletResponse res) throws Exception {
|
||||
// Get all monitor IDs from the database
|
||||
List<Long> allMonitorIds = monitorDao.findAll()
|
||||
.stream()
|
||||
.map(Monitor::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Use the existing export method to export all monitors
|
||||
export(allMonitorIds, type, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importConfig(MultipartFile file) throws Exception {
|
||||
var fileName = FileUtil.getFileName(file);
|
||||
|
||||
@@ -21,13 +21,11 @@ app: jvm
|
||||
name:
|
||||
zh-CN: JVM虚拟机
|
||||
en-US: JVM
|
||||
ja-JP: Java仮想マシン
|
||||
# The description and help of this monitoring type
|
||||
help:
|
||||
zh-CN: HertzBeat 使用 <a href="https://hertzbeat.apache.org/docs/advanced/extend-jmx">JMX 协议</a> 对 JVM 虚拟机的通用性能指标(基础信息,内存池,类加载,线程信息等)进行采集监控。<br>⚠️注意:您需要在 JVM 应用中开启 JMX 服务,应用启动时添加 JMX 参数, 可自定义暴露端口,对外IP。<a href="https://docs.oracle.com/javase/1.5.0/docs/guide/management/agent.html#remote">点击查看开启步骤</a>。
|
||||
en-US: HertzBeat uses <a href='https://hertzbeat.apache.org/docs/advanced/extend-jmx'>JMX Protocol</a> to monitoring and collect general performance metric of jvm application. <br>⚠️Note:You need to enable JMX services in JVM application, and add the JXM parameters when the application start. You can also customize external IP address and exposed port.<a href='https://docs.oracle.com/javase/1.5.0/docs/guide/management/agent.html#remote'>Click here to view the activation steps.</a>"
|
||||
zh-TW: HertzBeat 使用 <a href="https://hertzbeat.apache.org/docs/advanced/extend-jmx">JMX 協議</a> 對 JVM 虛擬機的通用性能指標(基礎信息,內存池,類加載,線程信息等)進行采集監控。<br>⚠️注意:您需要在 JVM 應用中開啓 JMX 服務,應用啓動時添加 JMX 參數, 可自定義暴露端口,對外IP。<a href="https://docs.oracle.com/javase/1.5.0/docs/guide/management/agent.html#remote">點擊查看開啓步驟</a>。
|
||||
ja-JP: HertzBeat は <a href='https://hertzbeat.apache.org/docs/advanced/extend-jmx'> JMXプロトコルを介して</a> Java仮想マシンの一般的なパフォーマンスのメトリクスを監視します。<br>⚠️注意:Java仮想マシンの応用 で JMX サービスを有効にする必要があります。<a href='https://docs.oracle.com/javase/1.5.0/docs/guide/management/agent.html#remote'>クリックしてガイドを見ます</a>。
|
||||
helpLink:
|
||||
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/jvm/
|
||||
en-US: https://hertzbeat.apache.org/docs/help/jvm/
|
||||
@@ -39,7 +37,6 @@ params:
|
||||
name:
|
||||
zh-CN: 目标Host
|
||||
en-US: Target Host
|
||||
ja-JP: 目標ホスト
|
||||
# type-param field type(most mapping the html input type)
|
||||
type: host
|
||||
# required-true or false
|
||||
@@ -50,7 +47,6 @@ params:
|
||||
name:
|
||||
zh-CN: 端口
|
||||
en-US: Port
|
||||
ja-JP: ポート
|
||||
# type-param field type(most mapping the html input type)
|
||||
type: number
|
||||
# when type is number, range is required
|
||||
@@ -65,7 +61,6 @@ params:
|
||||
name:
|
||||
zh-CN: JMX URL
|
||||
en-US: JMX URL
|
||||
ja-JP: JMX URL
|
||||
# type-param field type(most mapping the html input type)
|
||||
type: text
|
||||
# required-true or false
|
||||
@@ -80,7 +75,6 @@ params:
|
||||
name:
|
||||
zh-CN: 用户名
|
||||
en-US: Username
|
||||
ja-JP: ユーザー名
|
||||
# type-param field type(most mapping the html input type)
|
||||
type: text
|
||||
# when type is text, use limit to limit string length
|
||||
@@ -95,7 +89,6 @@ params:
|
||||
name:
|
||||
zh-CN: 密码
|
||||
en-US: Password
|
||||
ja-JP: パスワード
|
||||
# type-param field type(most mapping the html input tag)
|
||||
type: password
|
||||
# required-true or false
|
||||
@@ -112,7 +105,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 虚拟机基础信息
|
||||
en-US: JVM Basic
|
||||
ja-JP: Java仮想マシン基礎情報
|
||||
# collect metrics content
|
||||
fields:
|
||||
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
|
||||
@@ -121,26 +113,22 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 名称
|
||||
en-US: Vm Name
|
||||
ja-JP: 仮想マシン名
|
||||
- field: VmVendor
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 厂商
|
||||
en-US: Vm Vendor
|
||||
ja-JP: 仮想マシンベンダー
|
||||
- field: VmVersion
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 版本
|
||||
en-US: Vm Version
|
||||
ja-JP: 仮想マシンバージョン
|
||||
- field: Uptime
|
||||
type: 0
|
||||
unit: ms
|
||||
i18n:
|
||||
zh-CN: 运行时长
|
||||
en-US: Up time
|
||||
ja-JP: アップタイム
|
||||
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
|
||||
protocol: jmx
|
||||
# the config content when protocol is jmx
|
||||
@@ -160,7 +148,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 内存池
|
||||
en-US: Memory Pool
|
||||
ja-JP: メモリプール
|
||||
fields:
|
||||
- field: name
|
||||
type: 1
|
||||
@@ -168,35 +155,30 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 指标名称
|
||||
en-US: Name
|
||||
ja-JP: メトリクス名
|
||||
- field: committed
|
||||
type: 0
|
||||
unit: MB
|
||||
i18n:
|
||||
zh-CN: 已分配内存
|
||||
en-US: Committed
|
||||
ja-JP: コミットされたメモリ
|
||||
- field: init
|
||||
type: 0
|
||||
unit: MB
|
||||
i18n:
|
||||
zh-CN: 初始化内存
|
||||
en-US: Init
|
||||
ja-JP: イニシャルメモリ
|
||||
- field: max
|
||||
type: 0
|
||||
unit: MB
|
||||
i18n:
|
||||
zh-CN: 最大内存
|
||||
en-US: Max
|
||||
ja-JP: 最大メモリ
|
||||
- field: used
|
||||
type: 0
|
||||
unit: MB
|
||||
i18n:
|
||||
zh-CN: 已使用内存
|
||||
en-US: Used
|
||||
ja-JP: 使用したメモリ
|
||||
units:
|
||||
- committed=B->MB
|
||||
- init=B->MB
|
||||
@@ -233,32 +215,27 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 本地代码缓冲区
|
||||
en-US: Code Cache
|
||||
ja-JP: コードキャッシュ
|
||||
fields:
|
||||
- field: committed
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 已分配内存
|
||||
en-US: Committed
|
||||
ja-JP: コミットされたメモリ
|
||||
- field: init
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 初始化内存
|
||||
en-US: Init
|
||||
ja-JP: イニシャルメモリ
|
||||
- field: max
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 最大内存
|
||||
en-US: Max
|
||||
ja-JP: 最大メモリ
|
||||
- field: used
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 已使用内存
|
||||
en-US: Used
|
||||
ja-JP: 使用したメモリ
|
||||
aliasFields:
|
||||
- Usage->committed
|
||||
- Usage->init
|
||||
@@ -285,7 +262,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 类加载信息
|
||||
en-US: Class Loading
|
||||
ja-JP: クラスローディング情報
|
||||
# collect metrics content
|
||||
fields:
|
||||
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
|
||||
@@ -294,19 +270,16 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 当前已加载类数量
|
||||
en-US: Loaded Class Count
|
||||
ja-JP: ロードされたクラス数
|
||||
- field: TotalLoadedClassCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 已加载类总数量
|
||||
en-US: Total Loaded Class Count
|
||||
ja-JP: ロードされたクラス総数
|
||||
- field: UnloadedClassCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 未加载类总数量
|
||||
en-US: Unloaded Class Count
|
||||
ja-JP: アンロードされたクラス総数
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -321,7 +294,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 线程信息
|
||||
en-US: Thread
|
||||
ja-JP: スレッド情報
|
||||
# collect metrics content
|
||||
fields:
|
||||
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
|
||||
@@ -330,39 +302,33 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 已启动线程总数
|
||||
en-US: Total Started Thread Count
|
||||
ja-JP: スレッド総数
|
||||
- field: ThreadCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 活跃线程数
|
||||
en-US: Thread Count
|
||||
ja-JP: 活躍スレッド数
|
||||
- field: PeakThreadCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 最大峰值线程数
|
||||
en-US: Peak Thread Count
|
||||
ja-JP: 最大スレッド数
|
||||
- field: DaemonThreadCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 活跃守护线程数
|
||||
en-US: Daemon Thread Count
|
||||
ja-JP: デーモンスレッド数
|
||||
- field: CurrentThreadUserTime
|
||||
type: 0
|
||||
unit: s
|
||||
i18n:
|
||||
zh-CN: 线程占用的CPU时间(用户态)
|
||||
en-US: Current Thread User Time
|
||||
ja-JP: 現在のスレッドユーザー時間
|
||||
- field: CurrentThreadCpuTime
|
||||
type: 0
|
||||
unit: s
|
||||
i18n:
|
||||
zh-CN: 线程占用的CPU时间
|
||||
en-US: Current Thread CPU Time
|
||||
ja-JP: 現在のスレッドシステム時間
|
||||
units:
|
||||
- CurrentThreadUserTime=NS->S
|
||||
- CurrentThreadCpuTime=NS->S
|
||||
|
||||
@@ -21,13 +21,11 @@ app: kafka
|
||||
name:
|
||||
zh-CN: Kafka消息系统
|
||||
en-US: Kafka Message
|
||||
ja-JP: Kafkaメッセージングシステム
|
||||
# The description and help of this monitoring type
|
||||
help:
|
||||
zh-CN: HertzBeat 使用 <a href="https://hertzbeat.apache.org/docs/advanced/extend-jmx">JMX 协议</a> 对 Kafka 的通用性能指标 (server info、code cache、active controller count、broker partition count、broker leader count、broker handler avg percent etc) 进行采集监控。<br><span class='help_module_span'>注意⚠️:您需要在 Kafka 开启 JMX 服务,应用启动时添加 JMX 参数,暴露端口,对外IP。下方配置的端口即为JMX暴露的端口,而非Kafka的server端口。<a class='help_module_content' href='https://hertzbeat.apache.org/zh-cn/docs/help/kafka'>点击查看开启步骤</a>。</span>
|
||||
en-US: HertzBeat uses <a href='https://hertzbeat.apache.org/docs/advanced/extend-jmx'>JMX Protocol</a> to monitoring kafka general performance metrics (server info、code cache、active controller count、broker partition count、broker leader count、broker handler avg percent etc). <br><span class='help_module_span'>Note⚠️:You need to enable JMX service in Kafka, export JMX port and config params.The port configured below is the JMX exposed port, not the Kafka server port. <a class='help_module_content' href='https://hertzbeat.apache.org/docs/help/kafka'>Click here to view the specific steps.</a></span>
|
||||
zh-TW: HertzBeat 使用 <a href="https://hertzbeat.apache.org/docs/advanced/extend-jmx">JMX 協議</a> 對 Kafka 的通用性能指標 (server info、code cache、active controller count、broker partition count、broker leader count、broker handler avg percent etc) 進行采集監控。<br><span class='help_module_span'>注意⚠️:您需要在 Kafka 開啓 JMX 服務,應用啓動時添加 JMX 參數,暴露端口,對外IP。下方配置的端口即為 JMX 暴露的端口,而非 Kafka 的伺服器端口。<a class='help_module_content' href='https://hertzbeat.apache.org/zh-cn/docs/help/kafka'>點擊查看開啓步驟</a>。</span>
|
||||
ja-JP: HertzBeat は <a href='https://hertzbeat.apache.org/docs/advanced/extend-jmx'> JMXプロトコルを介して</a> Kafkaの一般的なパフォーマンスのメトリクスを監視します。<br><span class='help_module_span'>⚠️注意:Kafka で JMX サービスを有効にする必要があります。<a class='help_module_content' href='https://hertzbeat.apache.org/docs/help/kafka'>クリックしてガイドを見ます</a>。</span>
|
||||
helpLink:
|
||||
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/kafka
|
||||
en-US: https://hertzbeat.apache.org/docs/help/kafka
|
||||
@@ -39,7 +37,6 @@ params:
|
||||
name:
|
||||
zh-CN: 目标Host
|
||||
en-US: Target Host
|
||||
ja-JP: 目標ホスト
|
||||
# type-param field type(most mapping the html input type)
|
||||
type: host
|
||||
# required-true or false
|
||||
@@ -48,7 +45,6 @@ params:
|
||||
name:
|
||||
zh-CN: 端口
|
||||
en-US: Port
|
||||
ja-JP: ポート
|
||||
type: number
|
||||
# when type is number, range is required
|
||||
range: '[0,65535]'
|
||||
@@ -58,7 +54,6 @@ params:
|
||||
name:
|
||||
zh-CN: JMX URL
|
||||
en-US: JMX URL
|
||||
ja-JP: JMX URL
|
||||
type: text
|
||||
required: false
|
||||
hide: true
|
||||
@@ -67,7 +62,6 @@ params:
|
||||
name:
|
||||
zh-CN: 用户名
|
||||
en-US: Username
|
||||
ja-JP: ユーザー名
|
||||
type: text
|
||||
limit: 50
|
||||
required: false
|
||||
@@ -76,7 +70,6 @@ params:
|
||||
name:
|
||||
zh-CN: 密码
|
||||
en-US: Password
|
||||
ja-JP: パスワード
|
||||
type: password
|
||||
required: false
|
||||
hide: true
|
||||
@@ -87,7 +80,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 服务器信息
|
||||
en-US: Server Info
|
||||
ja-JP: サーバー情報
|
||||
# metrics scheduling priority(0->127)->(high->low), metrics with the same priority will be scheduled in parallel
|
||||
# priority 0's metrics is availability metrics, it will be scheduled first, only availability metrics collect success will the scheduling continue
|
||||
priority: 0
|
||||
@@ -99,19 +91,16 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 版本
|
||||
en-US: Version
|
||||
ja-JP: バージョン
|
||||
- field: StartTimeMs
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 启动时间
|
||||
en-US: Start Time
|
||||
ja-JP: 起動時間
|
||||
- field: CommitId
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: CommitId
|
||||
en-US: CommitId
|
||||
ja-JP: CommitId
|
||||
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
|
||||
protocol: jmx
|
||||
# the config content when protocol is jmx
|
||||
@@ -129,7 +118,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 虚拟机基础信息
|
||||
en-US: JVM Basic
|
||||
ja-JP: Java仮想マシン基礎情報
|
||||
priority: 1
|
||||
fields:
|
||||
- field: VmName
|
||||
@@ -137,26 +125,22 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 名称
|
||||
en-US: Vm Name
|
||||
ja-JP: 仮想マシン名
|
||||
- field: VmVendor
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 厂商
|
||||
en-US: Vm Vendor
|
||||
ja-JP: 仮想マシンベンダー
|
||||
- field: VmVersion
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 版本
|
||||
en-US: Vm Version
|
||||
ja-JP: 仮想マシンバージョン
|
||||
- field: Uptime
|
||||
type: 0
|
||||
unit: ms
|
||||
i18n:
|
||||
zh-CN: 运行时长
|
||||
en-US: Up time
|
||||
ja-JP: アップタイム
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -171,7 +155,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 内存池
|
||||
en-US: Memory Pool
|
||||
ja-JP: メモリプール
|
||||
priority: 2
|
||||
fields:
|
||||
- field: name
|
||||
@@ -180,31 +163,26 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 指标名称
|
||||
en-US: Name
|
||||
ja-JP: メトリクス名
|
||||
- field: committed
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 已分配内存
|
||||
en-US: Committed
|
||||
ja-JP: コミットされたメモリ
|
||||
- field: init
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 初始化内存
|
||||
en-US: Init
|
||||
ja-JP: イニシャルメモリ
|
||||
- field: max
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 最大内存
|
||||
en-US: Max
|
||||
ja-JP: 最大メモリ
|
||||
- field: used
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 已使用内存
|
||||
en-US: Used
|
||||
ja-JP: 使用したメモリ
|
||||
aliasFields:
|
||||
- Name
|
||||
- Usage->committed
|
||||
@@ -230,7 +208,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: Kafka控制器指标
|
||||
en-US: Kafka Controller Metrics
|
||||
ja-JP: Kafkaコントローラーのメトリクス
|
||||
priority: 3
|
||||
fields:
|
||||
- field: ActiveBrokerCount
|
||||
@@ -238,79 +215,66 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 活跃代理数量
|
||||
en-US: Active Broker Count
|
||||
ja-JP: 活動中のブローカー数
|
||||
- field: ActiveControllerCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 活跃控制器数量
|
||||
en-US: Active Controller Count
|
||||
ja-JP: 活動中のコントローラー数
|
||||
- field: ControllerState
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 控制器状态
|
||||
en-US: Controller State
|
||||
ja-JP: コントローラー状態
|
||||
- field: FencedBrokerCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 被隔离代理数量
|
||||
en-US: Fenced Broker Count
|
||||
ja-JP: フェンスのブローカー数
|
||||
- field: GlobalPartitionCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 全局分区数量
|
||||
en-US: Global Partition Count
|
||||
ja-JP: パーティション数
|
||||
- field: GlobalTopicCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 全局主题数量
|
||||
en-US: Global Topic Count
|
||||
ja-JP: トピック数
|
||||
- field: OfflinePartitionsCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 离线分区数量
|
||||
en-US: Offline Partitions Count
|
||||
ja-JP: オフラインのパーティション数
|
||||
- field: PreferredReplicaImbalanceCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 首选副本不平衡数量
|
||||
en-US: Preferred Replica Imbalance Count
|
||||
ja-JP: 優先レプリカ不均衡数
|
||||
- field: ReplicasIneligibleToDeleteCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 不能删除的副本数量
|
||||
en-US: Replicas Ineligible To Delete Count
|
||||
ja-JP: 削除できないレプリカ数
|
||||
- field: ReplicasToDeleteCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 待删除副本数量
|
||||
en-US: Replicas To Delete Count
|
||||
ja-JP: 削除待ちのレプリカ数
|
||||
- field: TopicsIneligibleToDeleteCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 不能删除的主题数量
|
||||
en-US: Topics Ineligible To Delete Count
|
||||
ja-JP: 削除できないトピック数
|
||||
- field: TopicsToDeleteCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 待删除主题数量
|
||||
en-US: Topics To Delete Count
|
||||
ja-JP: 削除待ちのトピック数
|
||||
- field: ZkMigrationState
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: ZooKeeper迁移状态
|
||||
en-US: Zk Migration State
|
||||
ja-JP: ZooKeeperマイグレーション状態
|
||||
aliasFields:
|
||||
- Value->ActiveBrokerCount
|
||||
- Value->ActiveControllerCount
|
||||
@@ -354,7 +318,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: Broker处理器平均百分比
|
||||
en-US: Broker Handler Avg Percent
|
||||
ja-JP: ブローカーハンドラの平均パーセント
|
||||
priority: 6
|
||||
fields:
|
||||
- field: EventType
|
||||
@@ -362,43 +325,36 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 事件类型
|
||||
en-US: Event Type
|
||||
ja-JP: イベントタイプ
|
||||
- field: RateUnit
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 速率单位
|
||||
en-US: Rate Unit
|
||||
ja-JP: レート単位
|
||||
- field: Count
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 计数
|
||||
en-US: Count
|
||||
ja-JP: カウント
|
||||
- field: MeanRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 平均速率
|
||||
en-US: Mean Rate
|
||||
ja-JP: 平均レート
|
||||
- field: OneMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 一分钟速率
|
||||
en-US: One Minute Rate
|
||||
ja-JP: 1分間のレート
|
||||
- field: FiveMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 五分钟速率
|
||||
en-US: Five Minute Rate
|
||||
ja-JP: 5分間のレート
|
||||
- field: FifteenMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 十五分钟速率
|
||||
en-US: Fifteen Minute Rate
|
||||
ja-JP: 15分間のレート
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -413,7 +369,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: Kafka副本管理器指标
|
||||
en-US: Kafka Replica Manager Metrics
|
||||
ja-JP: Kafkaレプリカマネジャーのメトリクス
|
||||
priority: 6
|
||||
fields:
|
||||
- field: AtMinIsrPartitionCount
|
||||
@@ -421,73 +376,61 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 达到最小ISR的分区数
|
||||
en-US: At Min ISR Partition Count
|
||||
ja-JP: 最小ISRパーティション数
|
||||
- field: FailedIsrUpdatesPerSec
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 每秒失败ISR更新数
|
||||
en-US: Failed ISR Updates Per Sec
|
||||
ja-JP: 1秒あたりのISR更新失敗数
|
||||
- field: IsrExpandsPerSec
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 每秒ISR扩展数
|
||||
en-US: ISR Expands Per Sec
|
||||
ja-JP: 1秒あたりのISR拡張数
|
||||
- field: IsrShrinksPerSec
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 每秒ISR收缩数
|
||||
en-US: ISR Shrinks Per Sec
|
||||
ja-JP: 1秒あたりのISR収縮数
|
||||
- field: LeaderCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 领导者数量
|
||||
en-US: Leader Count
|
||||
ja-JP: リーダー数
|
||||
- field: OfflineReplicaCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 离线副本数量
|
||||
en-US: Offline Replica Count
|
||||
ja-JP: オフラインのレプリカ数
|
||||
- field: PartitionCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 分区总数
|
||||
en-US: Partition Count
|
||||
ja-JP: パーティション数
|
||||
- field: PartitionsWithLateTransactionsCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 含有延迟交易的分区数
|
||||
en-US: Partitions With Late Transactions Count
|
||||
ja-JP: 遅いトランザクションのあるパーティション数
|
||||
- field: ProducerIdCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 生产者ID数量
|
||||
en-US: Producer ID Count
|
||||
ja-JP: 生産者ID数
|
||||
- field: ReassigningPartitions
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 正在重新分配的分区数
|
||||
en-US: Reassigning Partitions
|
||||
ja-JP: 再割り当てのパーティション数
|
||||
- field: UnderMinIsrPartitionCount
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 低于最小ISR的分区数
|
||||
en-US: Under Min ISR Partition Count
|
||||
ja-JP: 最小ISR未満のパーティション数
|
||||
- field: UnderReplicatedPartitions
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 副本数低于预期的分区数量
|
||||
en-US: Under Replicated Partitions
|
||||
ja-JP: レプリカ未満のパーティション数
|
||||
aliasFields:
|
||||
- Value->LeaderCount
|
||||
- Value->AtMinIsrPartitionCount
|
||||
@@ -529,7 +472,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 每秒主题流入字节
|
||||
en-US: Total Bytes In Per Second
|
||||
ja-JP: 1秒あたりのトピック合計受信されたバイト
|
||||
priority: 7
|
||||
fields:
|
||||
- field: EventType
|
||||
@@ -537,43 +479,36 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 事件类型
|
||||
en-US: Event Type
|
||||
ja-JP: イベントタイプ
|
||||
- field: RateUnit
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 速率单位
|
||||
en-US: Rate Unit
|
||||
ja-JP: レート単位
|
||||
- field: MeanRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 平均速率
|
||||
en-US: Mean Rate
|
||||
ja-JP: 平均レート
|
||||
- field: OneMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 一分钟速率
|
||||
en-US: One Minute Rate
|
||||
ja-JP: 1分間のレート
|
||||
- field: FiveMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 五分钟速率
|
||||
en-US: Five Minute Rate
|
||||
ja-JP: 5分間のレート
|
||||
- field: FifteenMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 十五分钟速率
|
||||
en-US: Fifteen Minute Rate
|
||||
ja-JP: 15分間のレート
|
||||
- field: Count
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 计数
|
||||
en-US: Count
|
||||
ja-JP: カウント
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -588,7 +523,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 各主题每秒流入字节
|
||||
en-US: Bytes In Per Topic Per Second
|
||||
ja-JP: 各トピックの1秒あたりの受信されたバイト
|
||||
priority: 7
|
||||
fields:
|
||||
- field: topic
|
||||
@@ -596,49 +530,41 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题名称
|
||||
en-US: Topic Name
|
||||
ja-JP: トピック名
|
||||
- field: EventType
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 事件类型
|
||||
en-US: Event Type
|
||||
ja-JP: イベントタイプ
|
||||
- field: RateUnit
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 速率单位
|
||||
en-US: Rate Unit
|
||||
ja-JP: レート単位
|
||||
- field: MeanRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 平均速率
|
||||
en-US: Mean Rate
|
||||
ja-JP: 平均レート
|
||||
- field: OneMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 一分钟速率
|
||||
en-US: One Minute Rate
|
||||
ja-JP: 1分間のレート
|
||||
- field: FiveMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 五分钟速率
|
||||
en-US: Five Minute Rate
|
||||
ja-JP: 5分間のレート
|
||||
- field: FifteenMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 十五分钟速率
|
||||
en-US: Fifteen Minute Rate
|
||||
ja-JP: 15分間のレート
|
||||
- field: Count
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 计数
|
||||
en-US: Count
|
||||
ja-JP: カウント
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -653,7 +579,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题每秒流出字节
|
||||
en-US: Total Bytes Out Per Second
|
||||
ja-JP: 1秒あたりのトピック合計転送されたバイト
|
||||
priority: 8
|
||||
fields:
|
||||
- field: EventType
|
||||
@@ -661,43 +586,36 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 事件类型
|
||||
en-US: Event Type
|
||||
ja-JP: イベントタイプ
|
||||
- field: RateUnit
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 速率单位
|
||||
en-US: Rate Unit
|
||||
ja-JP: レート単位
|
||||
- field: MeanRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 平均速率
|
||||
en-US: Mean Rate
|
||||
ja-JP: 平均レート
|
||||
- field: OneMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 一分钟速率
|
||||
en-US: One Minute Rate
|
||||
ja-JP: 1分間のレート
|
||||
- field: FiveMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 五分钟速率
|
||||
en-US: Five Minute Rate
|
||||
ja-JP: 5分間のレート
|
||||
- field: FifteenMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 十五分钟速率
|
||||
en-US: Fifteen Minute Rate
|
||||
ja-JP: 15分間のレート
|
||||
- field: Count
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 计数
|
||||
en-US: Count
|
||||
ja-JP: カウント
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -712,7 +630,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 各主题每秒流出字节
|
||||
en-US: Bytes Out Per Topic Per Second
|
||||
ja-JP: 各トピックの1秒あたりの転送されたバイト
|
||||
priority: 9
|
||||
fields:
|
||||
- field: topic
|
||||
@@ -720,49 +637,41 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题名称
|
||||
en-US: Topic Name
|
||||
ja-JP: トピック名
|
||||
- field: EventType
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 事件类型
|
||||
en-US: Event Type
|
||||
ja-JP: イベントタイプ
|
||||
- field: RateUnit
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 速率单位
|
||||
en-US: Rate Unit
|
||||
ja-JP: レート単位
|
||||
- field: MeanRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 平均速率
|
||||
en-US: Mean Rate
|
||||
ja-JP: 平均レート
|
||||
- field: OneMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 一分钟速率
|
||||
en-US: One Minute Rate
|
||||
ja-JP: 1分間のレート
|
||||
- field: FiveMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 五分钟速率
|
||||
en-US: Five Minute Rate
|
||||
ja-JP: 5分間のレート
|
||||
- field: FifteenMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 十五分钟速率
|
||||
en-US: Fifteen Minute Rate
|
||||
ja-JP: 15分間のレート
|
||||
- field: Count
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 计数
|
||||
en-US: Count
|
||||
ja-JP: カウント
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -777,7 +686,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 每秒生产消息转换
|
||||
en-US: Produce Message Conversions PerSec
|
||||
ja-JP: 1秒あたりのメッセージ変換数
|
||||
priority: 9
|
||||
fields:
|
||||
- field: EventType
|
||||
@@ -785,43 +693,36 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 事件类型
|
||||
en-US: Event Type
|
||||
ja-JP: イベントタイプ
|
||||
- field: RateUnit
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 速率单位
|
||||
en-US: Rate Unit
|
||||
ja-JP: レート単位
|
||||
- field: MeanRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 平均速率
|
||||
en-US: Mean Rate
|
||||
ja-JP: 平均レート
|
||||
- field: OneMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 一分钟速率
|
||||
en-US: One Minute Rate
|
||||
ja-JP: 1分間のレート
|
||||
- field: FiveMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 五分钟速率
|
||||
en-US: Five Minute Rate
|
||||
ja-JP: 5分間のレート
|
||||
- field: FifteenMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 十五分钟速率
|
||||
en-US: Fifteen Minute Rate
|
||||
ja-JP: 15分間のレート
|
||||
- field: Count
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 计数
|
||||
en-US: Count
|
||||
ja-JP: カウント
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -836,7 +737,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 每秒生产总请求数
|
||||
en-US: Produce Total Requests PerSec
|
||||
ja-JP: 1秒あたりの合計リクエスト数
|
||||
priority: 10
|
||||
fields:
|
||||
- field: EventType
|
||||
@@ -844,43 +744,36 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 事件类型
|
||||
en-US: Event Type
|
||||
ja-JP: イベントタイプ
|
||||
- field: RateUnit
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 速率单位
|
||||
en-US: Rate Unit
|
||||
ja-JP: レート単位
|
||||
- field: MeanRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 平均速率
|
||||
en-US: Mean Rate
|
||||
ja-JP: 平均レート
|
||||
- field: OneMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 一分钟速率
|
||||
en-US: One Minute Rate
|
||||
ja-JP: 1分間のレート
|
||||
- field: FiveMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 五分钟速率
|
||||
en-US: Five Minute Rate
|
||||
ja-JP: 5分間のレート
|
||||
- field: FifteenMinuteRate
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 十五分钟速率
|
||||
en-US: Fifteen Minute Rate
|
||||
ja-JP: 15分間のレート
|
||||
- field: Count
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 计数
|
||||
en-US: Count
|
||||
ja-JP: カウント
|
||||
protocol: jmx
|
||||
jmx:
|
||||
host: ^_^host^_^
|
||||
@@ -895,7 +788,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: Kafka消费者组指标
|
||||
en-US: Kafka Group Metrics
|
||||
ja-JP: Kafka消費者グループメトリクス
|
||||
priority: 11
|
||||
fields:
|
||||
- field: NumGroups
|
||||
@@ -903,43 +795,36 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 群组数量
|
||||
en-US: Num Groups
|
||||
ja-JP: 消費者グループ総数
|
||||
- field: NumGroupsCompletingRebalance
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 正在完成重新平衡的群组数量
|
||||
en-US: Num Groups Completing Rebalance
|
||||
ja-JP: リバランス中の消費者グループ数
|
||||
- field: NumGroupsDead
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 死亡群组数量
|
||||
en-US: Num Groups Dead
|
||||
ja-JP: デッドの消費者グループ数
|
||||
- field: NumGroupsEmpty
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 空群组数量
|
||||
en-US: Num Groups Empty
|
||||
ja-JP: 空の消費者グループ数
|
||||
- field: NumGroupsPreparingRebalance
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 正在准备重新平衡的群组数量
|
||||
en-US: Num Groups Preparing Rebalance
|
||||
ja-JP: リバランス準備中の消費者グループ数
|
||||
- field: NumGroupsStable
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 稳定群组数量
|
||||
en-US: Num Groups Stable
|
||||
ja-JP: 安定した消費者グループ数
|
||||
- field: NumOffsets
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 偏移量数量
|
||||
en-US: Num Offsets
|
||||
ja-JP: オフセット数
|
||||
aliasFields:
|
||||
- Value->NumGroups
|
||||
- Value->NumGroupsCompletingRebalance
|
||||
|
||||
@@ -18,13 +18,11 @@ app: kafka_client
|
||||
name:
|
||||
zh-CN: Kafka消息系统(客户端)
|
||||
en-US: Kafka Message(Client)
|
||||
ja-JP: Kafkaメッセージングシステム(クライアント)
|
||||
|
||||
help:
|
||||
zh-CN: HertzBeat 使用 <a href="https://hertzbeat.apache.org/zh-cn/docs/help/kafka_client">Kafka Admin Client</a> 对 Kafka 的通用指标进行采集监控。</span>
|
||||
en-US: HertzBeat uses <a href='https://hertzbeat.apache.org/docs/help/kafka_client'>Kafka Admin Client</a> to monitoring kafka general metrics. </span>
|
||||
zh-TW: HertzBeat 使用 <a href="https://hertzbeat.apache.org/zh-cn/docs/help/kafka_client">Kafka Admin Client</a> 對 Kafka 的通用指標進行采集監控。</span>
|
||||
ja-JP: HertzBeat は <a href="https://hertzbeat.apache.org/docs/help/kafka_client">Kafka Admin Clientを介して</a> Kafkaの一般的なパフォーマンスのメトリクスを監視します。</span>
|
||||
|
||||
helpLink:
|
||||
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/kafka_client
|
||||
@@ -35,14 +33,12 @@ params:
|
||||
name:
|
||||
zh-CN: 目标Host
|
||||
en-US: Target Host
|
||||
ja-JP: 目標ホスト
|
||||
type: host
|
||||
required: true
|
||||
- field: port
|
||||
name:
|
||||
zh-CN: 端口
|
||||
en-US: Port
|
||||
ja-JP: ポート
|
||||
type: number
|
||||
range: '[0,65535]'
|
||||
required: true
|
||||
@@ -51,7 +47,6 @@ params:
|
||||
name:
|
||||
zh-CN: 是否监控内部主题
|
||||
en-US: Monitor Internal Topic
|
||||
ja-JP: 内部トピックを監視するかどうか
|
||||
type: boolean
|
||||
required: true
|
||||
defaultValue: false
|
||||
@@ -61,7 +56,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题列表
|
||||
en-US: Topic List
|
||||
ja-JP: トピック一覧
|
||||
priority: 0
|
||||
fields:
|
||||
- field: TopicName
|
||||
@@ -69,7 +63,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题名称
|
||||
en-US: Topic Name
|
||||
ja-JP: トピック名
|
||||
protocol: kclient
|
||||
kclient:
|
||||
host: ^_^host^_^
|
||||
@@ -80,7 +73,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题详细信息
|
||||
en-US: Topic Detail Info
|
||||
ja-JP: トピック詳細情報
|
||||
priority: 1
|
||||
fields:
|
||||
- field: TopicName
|
||||
@@ -88,43 +80,36 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题名称
|
||||
en-US: Topic Name
|
||||
ja-JP: トピック名
|
||||
- field: PartitionNum
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 分区数量
|
||||
en-US: Partition Num
|
||||
ja-JP: パーティション数
|
||||
- field: PartitionLeader
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 分区领导者
|
||||
en-US: Partition Leader
|
||||
ja-JP: パーティションリーダー
|
||||
- field: BrokerHost
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: Broker主机
|
||||
en-US: Broker Host
|
||||
ja-JP: ブローカーホスト
|
||||
- field: BrokerPort
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: Broker端口
|
||||
en-US: Broker Port
|
||||
ja-JP: ブローカーポート
|
||||
- field: ReplicationFactorSize
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 复制因子大小
|
||||
en-US: Replication Factor Size
|
||||
ja-JP: レプリカファクターのサイズ
|
||||
- field: ReplicationFactor
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 复制因子
|
||||
en-US: Replication Factor
|
||||
ja-JP: レプリカファクター
|
||||
protocol: kclient
|
||||
kclient:
|
||||
host: ^_^host^_^
|
||||
@@ -135,7 +120,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题偏移量
|
||||
en-US: Topic Offset
|
||||
ja-JP: トピックオフセット
|
||||
priority: 2
|
||||
# Kafka offset does not need to be obtained frequently, as getting it too quickly will affect performance
|
||||
interval: 300
|
||||
@@ -146,26 +130,22 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 主题名称
|
||||
en-US: Topic Name
|
||||
ja-JP: トピック名
|
||||
- field: PartitionNum
|
||||
label: true
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 分区号
|
||||
en-US: Partition Num
|
||||
ja-JP: パーティション数
|
||||
- field: earliest
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 最早偏移量
|
||||
en-US: Earliest Offset
|
||||
ja-JP: 最早オフセット
|
||||
- field: latest
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 最新偏移量
|
||||
en-US: Latest Offset
|
||||
ja-JP: 最新オフセット
|
||||
protocol: kclient
|
||||
kclient:
|
||||
host: ^_^host^_^
|
||||
@@ -176,7 +156,6 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 消费者组情况
|
||||
en-US: Consumer Detail Info
|
||||
ja-JP: 消費者グループ詳細情報
|
||||
priority: 3
|
||||
# Kafka offset does not need to be obtained frequently, as getting it too quickly will affect performance
|
||||
interval: 300
|
||||
@@ -187,32 +166,27 @@ metrics:
|
||||
i18n:
|
||||
zh-CN: 消费者组ID
|
||||
en-US: Consumer Group ID
|
||||
ja-JP: 消費者グループID
|
||||
- field: Group Member Num
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 消费者实例数量
|
||||
en-US: Group Member Num
|
||||
ja-JP: 消費者グループのメンバー数
|
||||
- field: Topic
|
||||
label: true
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 订阅主题名称
|
||||
en-US: Subscribed Topic Name
|
||||
ja-JP: 購読されたトピック名
|
||||
- field: Offset of Each Partition
|
||||
type: 1
|
||||
i18n:
|
||||
zh-CN: 各分区偏移量
|
||||
en-US: Offset of Each Partition
|
||||
ja-JP: 各パーティションのオフセット
|
||||
- field: Lag
|
||||
type: 0
|
||||
i18n:
|
||||
zh-CN: 落后偏移量
|
||||
en-US: Total Lag
|
||||
ja-JP: ラグオフセット
|
||||
protocol: kclient
|
||||
kclient:
|
||||
host: ^_^host^_^
|
||||
|
||||
-14
@@ -145,18 +145,4 @@ class MonitorsControllerTest {
|
||||
.andExpect(jsonPath("$.code").value("0"))
|
||||
.andExpect(jsonPath("$.msg").value("Import success"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportAll() throws Exception {
|
||||
String type = "JSON";
|
||||
|
||||
// Mock the behavior of monitorService.exportAll
|
||||
doNothing().when(monitorService).exportAll(Mockito.anyString(), Mockito.any());
|
||||
|
||||
// Perform the request and verify the response
|
||||
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/monitors/export/all")
|
||||
.param("type", type))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
}
|
||||
}
|
||||
|
||||
-27
@@ -745,33 +745,6 @@ class MonitorServiceTest {
|
||||
when(monitorDao.findById(1L)).thenReturn(Optional.of(monitor));
|
||||
when(paramDao.findParamsByMonitorId(1L)).thenReturn(params);
|
||||
assertDoesNotThrow(() -> monitorService.copyMonitor(1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportAll() throws Exception {
|
||||
// Create some test monitors
|
||||
Monitor monitor1 = Monitor.builder().id(1L).name("test1").app("app1").build();
|
||||
Monitor monitor2 = Monitor.builder().id(2L).name("test2").app("app2").build();
|
||||
List<Monitor> allMonitors = List.of(monitor1, monitor2);
|
||||
|
||||
// Mock the behavior of monitorDao.findAll
|
||||
when(monitorDao.findAll()).thenReturn(allMonitors);
|
||||
|
||||
// Create a mock HttpServletResponse
|
||||
jakarta.servlet.http.HttpServletResponse mockResponse = org.mockito.Mockito.mock(jakarta.servlet.http.HttpServletResponse.class);
|
||||
|
||||
// Mock the ImExportService
|
||||
org.apache.hertzbeat.manager.service.ImExportService mockImExportService = org.mockito.Mockito.mock(org.apache.hertzbeat.manager.service.ImExportService.class);
|
||||
// Mock the getFileName method
|
||||
when(mockImExportService.getFileName()).thenReturn("test.json");
|
||||
// Set the field using reflection
|
||||
java.lang.reflect.Field field = MonitorServiceImpl.class.getDeclaredField("imExportServiceMap");
|
||||
field.setAccessible(true);
|
||||
java.util.Map<String, org.apache.hertzbeat.manager.service.ImExportService> imExportServiceMap = new java.util.HashMap<>();
|
||||
imExportServiceMap.put("JSON", mockImExportService);
|
||||
field.set(monitorService, imExportServiceMap);
|
||||
|
||||
// Test the exportAll method
|
||||
assertDoesNotThrow(() -> monitorService.exportAll("JSON", mockResponse));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ Previous releases of HertzBeat may be affected by security issues, please use th
|
||||
:::
|
||||
|
||||
| Version | Date | Download | Release |
|
||||
|---------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------|
|
||||
| v1.7.2 | 2025.07.05 | [apache-hertzbeat-1.7.2-incubating-bin.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-bin.tar.gz) (Server) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-bin.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-bin.tar.gz.sha512) ) <br/> [apache-hertzbeat-collector-1.7.2-incubating-bin.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.2/apache-hertzbeat-collector-1.7.2-incubating-bin.tar.gz) (Collector) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-collector-1.7.2-incubating-bin.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-collector-1.7.2-incubating-bin.tar.gz.sha512) ) <br/> [apache-hertzbeat-1.7.2-incubating-src.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-src.tar.gz) (Source Code) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-src.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-src.tar.gz.sha512) ) <br/> [apache-hertzbeat-1.7.2-incubating-docker-compose.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-docker-compose.tar.gz) (Docker Compose) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-docker-compose.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-docker-compose.tar.gz.sha512) ) | [note](https://github.com/apache/hertzbeat/releases/tag/v1.7.2) |
|
||||
| ------- |------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------|
|
||||
| v1.7.1 | 2025.05.29 | [apache-hertzbeat-1.7.1-incubating-bin.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-bin.tar.gz) (Server) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-bin.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-bin.tar.gz.sha512) ) <br/> [apache-hertzbeat-collector-1.7.1-incubating-bin.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.1/apache-hertzbeat-collector-1.7.1-incubating-bin.tar.gz) (Collector) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-collector-1.7.1-incubating-bin.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-collector-1.7.1-incubating-bin.tar.gz.sha512) ) <br/> [apache-hertzbeat-1.7.1-incubating-src.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-src.tar.gz) (Source Code) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-src.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-src.tar.gz.sha512) ) <br/> [apache-hertzbeat-1.7.1-incubating-docker-compose.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-docker-compose.tar.gz) (Docker Compose) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-docker-compose.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-docker-compose.tar.gz.sha512) ) | [note](https://github.com/apache/hertzbeat/releases/tag/v1.7.1) |
|
||||
|
||||
## Release Docker Image
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ sidebar_label: Download
|
||||
|
||||
| 版本 | 日期 | 下载 | Release |
|
||||
|--------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------|
|
||||
| v1.7.2 | 2025.07.05 | [apache-hertzbeat-1.7.2-incubating-bin.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-bin.tar.gz) (Server) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-bin.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-bin.tar.gz.sha512) ) <br/> [apache-hertzbeat-collector-1.7.2-incubating-bin.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.2/apache-hertzbeat-collector-1.7.2-incubating-bin.tar.gz) (Collector) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-collector-1.7.2-incubating-bin.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-collector-1.7.2-incubating-bin.tar.gz.sha512) ) <br/> [apache-hertzbeat-1.7.2-incubating-src.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-src.tar.gz) (Source Code) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-src.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-src.tar.gz.sha512) ) <br/> [apache-hertzbeat-1.7.2-incubating-docker-compose.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-docker-compose.tar.gz) (Docker Compose) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-docker-compose.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.2/apache-hertzbeat-1.7.2-incubating-docker-compose.tar.gz.sha512) ) | [note](https://github.com/apache/hertzbeat/releases/tag/v1.7.2) |
|
||||
| v1.7.1 | 2025.05.29 | [apache-hertzbeat-1.7.1-incubating-bin.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-bin.tar.gz) (主程序) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-bin.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-bin.tar.gz.sha512) ) <br/> [apache-hertzbeat-collector-1.7.1-incubating-bin.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.1/apache-hertzbeat-collector-1.7.1-incubating-bin.tar.gz) (采集器) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-collector-1.7.1-incubating-bin.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-collector-1.7.1-incubating-bin.tar.gz.sha512) ) <br/> [apache-hertzbeat-1.7.1-incubating-src.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-src.tar.gz) (源代码) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-src.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-src.tar.gz.sha512) ) <br/> [apache-hertzbeat-1.7.1-incubating-docker-compose.tar.gz](https://www.apache.org/dyn/closer.lua/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-docker-compose.tar.gz) (Docker Compose) ( [signature](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-docker-compose.tar.gz.asc) , [sha512](https://downloads.apache.org/incubator/hertzbeat/1.7.1/apache-hertzbeat-1.7.1-incubating-docker-compose.tar.gz.sha512) ) | [note](https://github.com/apache/hertzbeat/releases/tag/v1.7.1) |
|
||||
|
||||
## Docker 镜像版本
|
||||
|
||||
|
||||
@@ -77,12 +77,6 @@
|
||||
{{ 'monitor.export' | i18n }}
|
||||
</button>
|
||||
</li>
|
||||
<li nz-menu-item>
|
||||
<button nz-button (click)="onExportAllMonitors()">
|
||||
<i nz-icon nzType="export" nzTheme="outline"></i>
|
||||
{{ 'monitor.export-all' | i18n }}
|
||||
</button>
|
||||
</li>
|
||||
<li nz-menu-item>
|
||||
<nz-upload nzAction="/monitors/import" [nzLimit]="1" [nzShowUploadList]="false" (nzChange)="onImportMonitors($event)">
|
||||
<button nz-button>
|
||||
@@ -293,12 +287,7 @@
|
||||
>
|
||||
<ng-container *nzModalContent>
|
||||
<div class="export-type-container">
|
||||
<div
|
||||
class="export-type-card"
|
||||
(click)="exportMonitors('JSON')"
|
||||
[class.loading]="exportJsonButtonLoading"
|
||||
*ngIf="checkedMonitorIds.size > 0"
|
||||
>
|
||||
<div class="export-type-card" (click)="exportMonitors('JSON')" [class.loading]="exportJsonButtonLoading">
|
||||
<div class="export-type-icon">
|
||||
<i nz-icon nzType="code" nzTheme="outline"></i>
|
||||
</div>
|
||||
@@ -307,12 +296,7 @@
|
||||
<p>{{ 'monitor.export.use-type' | i18n : { type: 'JSON' } }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="export-type-card"
|
||||
(click)="exportMonitors('EXCEL')"
|
||||
[class.loading]="exportExcelButtonLoading"
|
||||
*ngIf="checkedMonitorIds.size > 0"
|
||||
>
|
||||
<div class="export-type-card" (click)="exportMonitors('EXCEL')" [class.loading]="exportExcelButtonLoading">
|
||||
<div class="export-type-icon">
|
||||
<i nz-icon nzType="file-excel" nzTheme="outline"></i>
|
||||
</div>
|
||||
@@ -321,34 +305,6 @@
|
||||
<p>{{ 'monitor.export.use-type' | i18n : { type: 'EXCEL' } }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="export-type-card"
|
||||
(click)="exportAllMonitors('JSON')"
|
||||
[class.loading]="exportJsonButtonLoading"
|
||||
*ngIf="checkedMonitorIds.size === 0"
|
||||
>
|
||||
<div class="export-type-icon">
|
||||
<i nz-icon nzType="code" nzTheme="outline"></i>
|
||||
</div>
|
||||
<div class="export-type-info">
|
||||
<h3>JSON</h3>
|
||||
<p>{{ 'monitor.export-all.use-type' | i18n : { type: 'JSON' } }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="export-type-card"
|
||||
(click)="exportAllMonitors('EXCEL')"
|
||||
[class.loading]="exportExcelButtonLoading"
|
||||
*ngIf="checkedMonitorIds.size === 0"
|
||||
>
|
||||
<div class="export-type-icon">
|
||||
<i nz-icon nzType="file-excel" nzTheme="outline"></i>
|
||||
</div>
|
||||
<div class="export-type-info">
|
||||
<h3>EXCEL</h3>
|
||||
<p>{{ 'monitor.export-all.use-type' | i18n : { type: 'EXCEL' } }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</nz-modal>
|
||||
|
||||
@@ -264,10 +264,6 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
this.isSwitchExportTypeModalVisible = true;
|
||||
}
|
||||
|
||||
onExportAllMonitors() {
|
||||
this.isSwitchExportTypeModalVisible = true;
|
||||
}
|
||||
|
||||
onImportMonitors(info: NzUploadChangeParam): void {
|
||||
console.log(info.type);
|
||||
if (info.type === 'start') {
|
||||
@@ -366,46 +362,6 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
}
|
||||
|
||||
exportAllMonitors(type: string) {
|
||||
switch (type) {
|
||||
case 'JSON':
|
||||
this.exportJsonButtonLoading = true;
|
||||
break;
|
||||
case 'EXCEL':
|
||||
this.exportExcelButtonLoading = true;
|
||||
break;
|
||||
}
|
||||
const exportAllMonitors$ = this.monitorSvc
|
||||
.exportAllMonitors(type)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
this.exportExcelButtonLoading = false;
|
||||
this.exportJsonButtonLoading = false;
|
||||
exportAllMonitors$.unsubscribe();
|
||||
})
|
||||
)
|
||||
.subscribe(
|
||||
response => {
|
||||
const message = response.body!;
|
||||
if (message.type == 'application/json') {
|
||||
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.export-fail'), '');
|
||||
} else {
|
||||
const blob = new Blob([message], { type: response.headers.get('Content-Type')! });
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.download = response.headers.get('Content-Disposition')!.split(';')[1].split('filename=')[1];
|
||||
a.href = url;
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
this.isSwitchExportTypeModalVisible = false;
|
||||
}
|
||||
},
|
||||
error => {
|
||||
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.export-fail'), error.msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onCancelManageMonitors() {
|
||||
if (this.checkedMonitorIds == null || this.checkedMonitorIds.size === 0) {
|
||||
this.notifySvc.warning(this.i18nSvc.fanyi('common.notify.no-select-cancel'), '');
|
||||
|
||||
@@ -30,7 +30,6 @@ const monitors_uri = '/monitors';
|
||||
const detect_monitor_uri = '/monitor/detect';
|
||||
const manage_monitors_uri = '/monitors/manage';
|
||||
const export_monitors_uri = '/monitors/export';
|
||||
const export_all_monitors_uri = '/monitors/export/all';
|
||||
const summary_uri = '/summary';
|
||||
const warehouse_storage_status_uri = '/warehouse/storage/status';
|
||||
const grafana_dashboard_uri = '/grafana/dashboard';
|
||||
@@ -75,16 +74,6 @@ export class MonitorService {
|
||||
});
|
||||
}
|
||||
|
||||
public exportAllMonitors(type: string): Observable<HttpResponse<Blob>> {
|
||||
let httpParams = new HttpParams();
|
||||
httpParams = httpParams.append('type', type);
|
||||
return this.http.get(export_all_monitors_uri, {
|
||||
params: httpParams,
|
||||
observe: 'response',
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
public cancelManageMonitors(monitorIds: Set<number>): Observable<Message<any>> {
|
||||
let httpParams = new HttpParams();
|
||||
monitorIds.forEach(monitorId => {
|
||||
|
||||
@@ -70,11 +70,11 @@
|
||||
"alert.help.inhibit.link": "https://hertzbeat.apache.org/docs/help/alert_inhibit",
|
||||
"alert.help.integration": "Unified management of alerts from different third-party platforms, integrating and receiving alert messages from third-party monitoring and observability systems, and performing actions such as grouping, aggregation, inhibition, silencing, and notification distribution.",
|
||||
"alert.help.integration.link": "https://hertzbeat.apache.org",
|
||||
"alert.help.notice": "Notification is used to config the receiver of alarm message and receiving method. The alarm message will be sent to the receiver by specified way(support email, discord, webhook etc). <a href='https://hertzbeat.apache.org/zh-cn/docs/help/alert_webhook'>Click here to see configuration steps.</a>.<br>\"<i>Notice Template</i>\" is message content structure template. The built-in template is used by default or you can customize the template to customize the message notification structure.<br><span class='help_module_span'>Note⚠️: After configuring the \"<i>Receiver</i>\", you also need to config the\"<i>Notice Policy</i>\"to specify which messages are sent to which receivers.</span><a href='https://hertzbeat.apache.org/docs/help/alert_email'> Click here to see potential issues</a>.",
|
||||
"alert.help.notice": "Notification is used to config the receiver of alarm message and receiving method. The alarm message will be sent to the receiver by specified way(support email, discord, webhook etc). <a href='https://hertzbeat.apache.org/zh-cn/docs/help/alert_webhook'>Click here to see configuration steps.</a>.<br>“<i>Notice Template</i>” is message content structure template. The built-in template is used by default or you can customize the template to customize the message notification structure.<br><span class='help_module_span'>Note⚠️: After configuring the “<i>Receiver</i>”, you also need to config the“<i>Notice Policy</i>”to specify which messages are sent to which receivers.</span><a href='https://hertzbeat.apache.org/docs/help/alert_email'> Click here to see potential issues</a>.",
|
||||
"alert.help.notice.link": "https://hertzbeat.apache.org/docs/help/alert_email",
|
||||
"alert.help.setting": "Threshold Rules are used for metrics alarm threshold rule management. Click the \"<i>New Threshold</i>\" to configure the alarm threshold for monitoring metrics. Hertzbeat will trigger alarms based on the threshold and metrics data.<br>Note⚠️: The alarm message that has been triggered can be checked in [Alter Center], and you can also set the notification method and personnel in [Notification].",
|
||||
"alert.help.setting.link": "https://hertzbeat.apache.org/docs/help/alert_threshold",
|
||||
"alert.help.silence": "Alarm Silence management is used when you don't want to be disturbed during system maintenance or on nights weekend. <br> Click \"<i>New Silence Strategy</i>\" and configure the time period to block messages so you would not get disturbed during breaks.",
|
||||
"alert.help.silence": "Alarm Silence management is used when you don’t want to be disturbed during system maintenance or on nights weekend. <br> Click \"<i>New Silence Strategy</i>\" and configure the time period to block messages so you would not get disturbed during breaks.",
|
||||
"alert.help.silence.link": "https://hertzbeat.apache.org/docs",
|
||||
"alert.inhibit.delete": "Delete Inhibit Rule",
|
||||
"alert.inhibit.edit": "Edit Inhibit Rule",
|
||||
@@ -702,12 +702,10 @@
|
||||
"monitor.edit-monitor": "Edit Monitor",
|
||||
"monitor.edit.failed": "Update Monitor Failed",
|
||||
"monitor.edit.success": "Update Monitor Success",
|
||||
"monitor.enable": "Enable",
|
||||
"monitor.export": "Export Selected",
|
||||
"monitor.export-all": "Export All",
|
||||
"monitor.export.switch-type": "Please select the export file format",
|
||||
"monitor.export.use-type": "Export selected monitors in {{type}} format",
|
||||
"monitor.export-all.use-type": "Export all monitors in {{type}} format",
|
||||
"monitor.enable": "Resume Monitor",
|
||||
"monitor.export": "Export Monitor",
|
||||
"monitor.export.switch-type": "Please select the export file format!",
|
||||
"monitor.export.use-type": "Export monitors in {{type}} file format",
|
||||
"monitor.grafana.enabled.label": "Enable Grafana",
|
||||
"monitor.grafana.enabled.tip": "is enabled, the monitoring data will be displayed in Grafana",
|
||||
"monitor.grafana.upload.label": "Upload Grafana Template",
|
||||
@@ -915,6 +913,5 @@
|
||||
"ai.bot.greeting": "Hello! I am an AI assistant. How can I help you?",
|
||||
"ai.bot.input.placeholder": "Please enter a question...",
|
||||
"ai.bot.send": "Send",
|
||||
"ai.bot.connect-fail": "Sorry, there was an issue connecting to the AI assistant. Please try again later.",
|
||||
"monitor.help": "Monitoring and management page, you can check the metric data and manage monitoring tasks here. The status of normal service is"
|
||||
"ai.bot.connect-fail": "Sorry, there was an issue connecting to the AI assistant. Please try again later."
|
||||
}
|
||||
|
||||
@@ -703,11 +703,9 @@
|
||||
"monitor.edit.failed": "修改监控失败",
|
||||
"monitor.edit.success": "修改监控成功",
|
||||
"monitor.enable": "恢复监控",
|
||||
"monitor.export": "导出所选",
|
||||
"monitor.export-all": "导出全部",
|
||||
"monitor.export": "导出监控",
|
||||
"monitor.export.switch-type": "请选择导出文件格式!",
|
||||
"monitor.export.use-type": "以 {{type}} 文件格式导出所选监控",
|
||||
"monitor.export-all.use-type": "以 {{type}} 文件格式导出全部监控",
|
||||
"monitor.export.use-type": "以 {{type}} 文件格式导出监控",
|
||||
"monitor.grafana.enabled.label": "启用Grafana",
|
||||
"monitor.grafana.enabled.tip": "是否启用Grafana",
|
||||
"monitor.grafana.upload.label": "上传Grafana模板",
|
||||
@@ -915,6 +913,5 @@
|
||||
"ai.bot.greeting": "你好!我是AI助手,有什么可以帮助你的吗?",
|
||||
"ai.bot.input.placeholder": "请输入问题...",
|
||||
"ai.bot.send": "发送",
|
||||
"ai.bot.connect-fail": "抱歉,连接AI助手时出现问题,请稍后再试。",
|
||||
"monitor.help": "监控管理页面,您可以在此查看指标数据并管理监控任务。正常服务的状态为"
|
||||
"ai.bot.connect-fail": "抱歉,连接AI助手时出现问题,请稍后再试。"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user