Compare commits

..
Author SHA1 Message Date
tomsun28 c33aa86ba2 [webapp] update ui
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-07-06 15:26:03 +08:00
tomsun28 b6bca5a10d [improve] make jackson serialize field all visibility
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-07-06 15:08:21 +08:00
108 changed files with 2190 additions and 2646 deletions
-9
View File
@@ -48,15 +48,6 @@ jobs:
- name: Build with Maven
run: mvnd clean -B package -Prelease -Dmaven.test.skip=false --file pom.xml
- name: Upload test reports
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-reports-${{ github.run_id }}
path: |
**/target/surefire-reports
**/target/failsafe-reports
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1
with:
+2 -2
View File
@@ -37,7 +37,7 @@
-`Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 提供强大的状态页构建能力,轻松向用户传达您产品服务的实时状态。
@@ -126,7 +126,7 @@
- `-e IDENTITY=custom-collector-name` : 配置此采集器的唯一性标识符名称,多个采集器名称不能相同,建议自定义英文名称。
- `-e MODE=public` : 配置运行模式(public or private), 公共集群模式或私有云边模式。
- `-e MANAGER_HOST=127.0.0.1` : 配置连接主 HertzBeat 服务的对外 IP。
- `-e MANAGER_HOST=127.0.0.1` : 配置连接主 HertaBeat 服务的对外 IP。
- `-e MANAGER_PORT=1158` : 配置连接主 HertzBeat 服务的对外端口,默认1158。
@@ -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);
}
}
@@ -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);
}
}
@@ -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());
}
}
@@ -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);
@@ -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);
}
}
@@ -75,7 +75,7 @@ public class DataSourceServiceImpl implements DataSourceService {
throw new IllegalArgumentException("Empty expression");
}
if (executors == null || executors.isEmpty()) {
throw new IllegalArgumentException(bundle.getString("alerter.datasource.executor.not.found"));
throw new IllegalArgumentException("No query executor found");
}
QueryExecutor executor = executors.stream().filter(e -> e.support(datasource)).findFirst().orElse(null);
@@ -33,4 +33,3 @@ alerter.priority.0 = Emergency Alert
alerter.priority.1 = Critical Alert
alerter.priority.2 = Warning Alert
alerter.calculate.parse.error = Expression is not fully parsed, may have syntax errors or incomplete inputs
alerter.datasource.executor.not.found = No query executor found
@@ -33,4 +33,3 @@ alerter.priority.0 = 紧急告警
alerter.priority.1 = 严重告警
alerter.priority.2 = 警告告警
alerter.calculate.parse.error = 表达式未完全解析,可能存在语法错误或输入不完整
alerter.datasource.executor.not.found = 未找到查询执行器
@@ -33,4 +33,3 @@ alerter.priority.0 = 緊急警報
alerter.priority.1 = 嚴重警報
alerter.priority.2 = 警告警報
alerter.calculate.parse.error = 表達式未完全解析,可能存在語法錯誤或輸入不完整
alerter.datasource.executor.not.found = 未找到查詢執行器
@@ -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);
}
}
@@ -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);
@@ -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());
}
@@ -33,7 +33,7 @@
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mqtt.version>1.2.5</mqtt.version>
<mqtt.version>1.3.3</mqtt.version>
</properties>
<dependencies>
@@ -140,19 +140,10 @@
</dependency>
<!-- mqtt -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<groupId>com.hivemq</groupId>
<artifactId>hivemq-mqtt-client</artifactId>
<version>${mqtt.version}</version>
</dependency>
<!--Bouncy Castle-->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<!--plc-->
<dependency>
<groupId>org.apache.plc4x</groupId>
@@ -68,7 +68,6 @@ import org.apache.hertzbeat.common.util.Base64Util;
import org.apache.hertzbeat.common.util.CommonUtil;
import org.apache.hertzbeat.common.util.IpDomainUtil;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
@@ -145,46 +144,37 @@ public class HttpCollectImpl extends AbstractCollect {
builder.setMsg(NetworkConstants.STATUS_CODE + SignConstants.BLANK + statusCode);
return;
}
long responseTime = System.currentTimeMillis() - startTime;
/*
this could create large objects, potentially impacting JVM memory space significantly.
Option 1: Parse using InputStream, but this requires significant code changes;
Option 2: Manually trigger garbage collection, similar to how it's done in Dubbo for large inputs.
*/
String resp = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
if (!StringUtils.hasText(resp)) {
log.info("http response entity is empty, status: {}.", statusCode);
}
Long responseTime = System.currentTimeMillis() - startTime;
String parseType = metrics.getHttp().getParseType();
HttpEntity entity = response.getEntity();
try {
if (DispatchConstants.PARSE_PROMETHEUS.equals(parseType)) {
if (entity != null) {
parseResponseByPrometheusExporter(entity.getContent(), metrics.getAliasFields(), builder);
}
} else if (DispatchConstants.PARSE_HEADER.equals(parseType)) {
parseResponseByHeader(builder, metrics.getAliasFields(), response);
// Consume entity to release connection
EntityUtils.consumeQuietly(entity);
} else {
/*
this could create large objects, potentially impacting JVM memory space significantly.
Option 1: Parse using InputStream, but this requires significant code changes;
Option 2: Manually trigger garbage collection, similar to how it's done in Dubbo for large inputs.
*/
String resp = entity == null ? "" : EntityUtils.toString(entity, StandardCharsets.UTF_8);
if (!StringUtils.hasText(resp)) {
log.info("http response entity is empty, status: {}.", statusCode);
}
switch (parseType) {
case DispatchConstants.PARSE_JSON_PATH ->
parseResponseByJsonPath(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
case DispatchConstants.PARSE_PROM_QL ->
parseResponseByPromQl(resp, metrics.getAliasFields(), metrics.getHttp(), builder);
case DispatchConstants.PARSE_XML_PATH ->
parseResponseByXmlPath(resp, metrics, builder, responseTime);
case DispatchConstants.PARSE_WEBSITE ->
parseResponseByWebsite(resp, metrics, metrics.getHttp(), builder, responseTime, statusCode);
case DispatchConstants.PARSE_SITE_MAP ->
parseResponseBySiteMap(resp, metrics.getAliasFields(), builder);
case DispatchConstants.PARSE_CONFIG ->
parseResponseByConfig(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
default ->
parseResponseByDefault(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
}
switch (parseType) {
case DispatchConstants.PARSE_JSON_PATH ->
parseResponseByJsonPath(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
case DispatchConstants.PARSE_PROM_QL ->
parseResponseByPromQl(resp, metrics.getAliasFields(), metrics.getHttp(), builder);
case DispatchConstants.PARSE_PROMETHEUS ->
parseResponseByPrometheusExporter(response.getEntity().getContent(), metrics.getAliasFields(), builder);
case DispatchConstants.PARSE_XML_PATH ->
parseResponseByXmlPath(resp, metrics, builder, responseTime);
case DispatchConstants.PARSE_WEBSITE ->
parseResponseByWebsite(resp, metrics, metrics.getHttp(), builder, responseTime, statusCode);
case DispatchConstants.PARSE_SITE_MAP ->
parseResponseBySiteMap(resp, metrics.getAliasFields(), builder);
case DispatchConstants.PARSE_HEADER ->
parseResponseByHeader(builder, metrics.getAliasFields(), response);
case DispatchConstants.PARSE_CONFIG ->
parseResponseByConfig(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
default ->
parseResponseByDefault(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
}
} catch (Exception e) {
log.info("parse error: {}.", e.getMessage(), e);
@@ -866,4 +856,4 @@ public class HttpCollectImpl extends AbstractCollect {
}
return successCodeSet.contains(statusCode);
}
}
}
@@ -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);
}
}
@@ -1,195 +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.collector.collect.mqtt;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Formats the private key and certificate, supporting concatenation of multiple certificates in PEM format.
*/
public class CertificateFormatter {
public static String formatCertificateChain(String input) {
if (input == null || input.trim().isEmpty()) {
return input;
}
String normalized = normalizeInput(input);
List<String> certificates = extractCertificates(normalized);
if (certificates.isEmpty()) {
return formatAsSingleCertificate(normalized);
}
StringBuilder formattedChain = new StringBuilder();
for (String cert : certificates) {
if (cert.trim().isEmpty()) continue;
String formatted = formatPemBlock(cert);
formattedChain.append(formatted).append("\n");
}
return formattedChain.toString().trim();
}
private static String normalizeInput(String input) {
return input
.replace("\r\n", "\n")
.replace("\r", "\n")
.replaceAll("\\s*\\\\n\\s*", "\n")
.replaceAll("(?m)^\\s+|\\s+$", "")
.trim();
}
private static List<String> extractCertificates(String input) {
List<String> certificates = new ArrayList<>();
String regex = "(-----BEGIN\\s+[\\w\\s]+?-----)[\\s\\S]*?(-----END\\s+[\\w\\s]+?-----)";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(input);
int lastEnd = 0;
while (matcher.find()) {
if (matcher.start() > lastEnd) {
String gap = input.substring(lastEnd, matcher.start());
if (!gap.trim().isEmpty()) {
certificates.add(gap);
}
}
certificates.add(matcher.group());
lastEnd = matcher.end();
}
if (lastEnd < input.length()) {
certificates.add(input.substring(lastEnd));
}
return certificates;
}
private static String formatPemBlock(String block) {
try {
Pattern pattern = Pattern.compile(
"(-----BEGIN\\s+[\\w\\s]+?-----)(.*?)(-----END\\s+[\\w\\s]+?-----)",
Pattern.DOTALL | Pattern.CASE_INSENSITIVE
);
Matcher matcher = pattern.matcher(block);
if (matcher.find()) {
String header = matcher.group(1).trim();
String body = matcher.group(2);
String footer = matcher.group(3).trim();
if (body == null) body = "";
String cleanBody = body
.replaceAll("\\s", "")
.replaceAll("\"", "")
.trim();
if (cleanBody.isEmpty() && body != null && !body.trim().isEmpty()) {
cleanBody = body.replaceAll("[^a-zA-Z0-9+/=]", "").trim();
}
String formattedBody = formatBase64Body(cleanBody);
return header + "\n" + formattedBody + "\n" + footer;
} else {
return formatAsCertificate(block);
}
} catch (Exception e) {
return block;
}
}
private static String formatAsCertificate(String content) {
String cleanContent = content.replaceAll("[^a-zA-Z0-9+/=]", "").trim();
if (cleanContent.isEmpty()) {
return content;
}
String formattedBody = formatBase64Body(cleanContent);
if (cleanContent.toLowerCase().contains("private")) {
if (cleanContent.startsWith("MII") || cleanContent.length() > 1000) {
return "-----BEGIN PRIVATE KEY-----\n" + formattedBody + "\n-----END PRIVATE KEY-----";
} else {
return "-----BEGIN RSA PRIVATE KEY-----\n" + formattedBody + "\n-----END RSA PRIVATE KEY-----";
}
} else {
return "-----BEGIN CERTIFICATE-----\n" + formattedBody + "\n-----END CERTIFICATE-----";
}
}
private static String formatAsSingleCertificate(String input) {
String cleanContent = input.replaceAll("[^a-zA-Z0-9+/=]", "").trim();
return formatAsCertificate(cleanContent);
}
private static String formatBase64Body(String body) {
StringBuilder formatted = new StringBuilder();
int index = 0;
while (index < body.length()) {
int end = Math.min(index + 64, body.length());
formatted.append(body.substring(index, end));
if (end < body.length()) {
formatted.append("\n");
}
index = end;
}
return formatted.toString().trim();
}
public static String formatPrivateKey(String input) {
if (input == null || input.trim().isEmpty()) {
return input;
}
String normalized = normalizeInput(input);
if (isPemEncapsulated(normalized)) {
return formatPemBlock(normalized);
}
return formatAsCertificate(normalized);
}
private static boolean isPemEncapsulated(String block) {
return block.contains("-----BEGIN") && block.contains("-----END");
}
}
@@ -17,7 +17,26 @@
package org.apache.hertzbeat.collector.collect.mqtt;
import com.hivemq.client.mqtt.MqttVersion;
import com.hivemq.client.mqtt.datatypes.MqttQos;
import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient;
import com.hivemq.client.mqtt.mqtt3.Mqtt3Client;
import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientBuilder;
import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck;
import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
import com.hivemq.client.mqtt.mqtt5.Mqtt5ClientBuilder;
import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.hertzbeat.collector.collect.AbstractCollect;
import org.apache.hertzbeat.collector.constants.CollectorConstants;
@@ -27,27 +46,13 @@ import org.apache.hertzbeat.common.entity.job.Metrics;
import org.apache.hertzbeat.common.entity.job.protocol.MqttProtocol;
import org.apache.hertzbeat.common.entity.message.CollectRep;
import org.apache.hertzbeat.common.entity.message.CollectRep.MetricsData.Builder;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
import org.eclipse.paho.client.mqttv3.MqttClientPersistence;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.StopWatch;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* collect mqtt metrics using Eclipse Paho
* collect mqtt metrics
*/
public class MqttCollectImpl extends AbstractCollect {
@@ -56,224 +61,138 @@ public class MqttCollectImpl extends AbstractCollect {
private static final Logger logger = LoggerFactory.getLogger(MqttCollectImpl.class);
@Override
public String supportProtocol() {
return DispatchConstants.PROTOCOL_MQTT;
}
@Override
public void preCheck(Metrics metrics) throws IllegalArgumentException {
MqttProtocol mqttProtocol = metrics.getMqtt();
Assert.hasText(mqttProtocol.getHost(), "MQTT protocol host is required");
Assert.hasText(mqttProtocol.getPort(), "MQTT protocol port is required");
if ("mqtts".equalsIgnoreCase(mqttProtocol.getProtocol())) {
if (Boolean.parseBoolean(mqttProtocol.getEnableMutualAuth())) {
Assert.hasText(mqttProtocol.getCaCert(), "CA certificate is required for mutual auth");
Assert.hasText(mqttProtocol.getClientCert(), "Client certificate is required for mutual auth");
Assert.hasText(mqttProtocol.getClientKey(), "Client private key is required for mutual auth");
}
}
Assert.hasText(mqttProtocol.getProtocolVersion(), "MQTT protocol version is required");
}
@Override
public void collect(Builder builder, Metrics metrics) {
MqttProtocol mqtt = metrics.getMqtt();
String protocolVersion = mqtt.getProtocolVersion();
MqttVersion mqttVersion = MqttVersion.valueOf(protocolVersion);
if (mqttVersion == MqttVersion.MQTT_3_1_1) {
collectWithVersion3(metrics, builder);
} else if (mqttVersion == MqttVersion.MQTT_5_0) {
collectWithVersion5(metrics, builder);
}
}
@Override
public String supportProtocol() {
return DispatchConstants.PROTOCOL_MQTT;
}
/**
* collecting data of MQTT 5
*/
private void collectWithVersion5(Metrics metrics, Builder builder) {
MqttProtocol mqttProtocol = metrics.getMqtt();
Map<Object, String> data = new HashMap<>();
try {
MqttAsyncClient client = buildMqttClient(mqttProtocol);
long responseTime = connectClient(client, mqttProtocol);
testSubscribeAndPublish(client, mqttProtocol, data);
convertToMetricsData(builder, metrics, responseTime, data);
client.disconnect();
} catch (Exception e) {
logger.error("MQTT collection error: {}", e.getMessage(), e);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("Collection failed: " + e.getMessage());
}
}
private MqttAsyncClient buildMqttClient(MqttProtocol protocol) throws Exception {
String clientId = protocol.getClientId();
String serverUri = String.format("%s://%s:%s",
StringUtils.equals(protocol.getProtocol(), "MQTT") ? "tcp" : "ssl",
protocol.getHost(),
protocol.getPort());
MqttClientPersistence persistence = new MemoryPersistence();
return new MqttAsyncClient(serverUri, clientId, persistence);
}
private long connectClient(MqttAsyncClient client, MqttProtocol protocol) throws Exception {
MqttConnectOptions connOpts = new MqttConnectOptions();
if (protocol.hasAuth()) {
connOpts.setUserName(protocol.getUsername());
connOpts.setPassword(protocol.getPassword().toCharArray());
}
connOpts.setKeepAliveInterval(Integer.parseInt(protocol.getKeepalive()));
connOpts.setConnectionTimeout(Integer.parseInt(protocol.getTimeout()) / 1000);
connOpts.setCleanSession(true);
connOpts.setAutomaticReconnect(false);
if ("mqtts".equalsIgnoreCase(protocol.getProtocol())) {
boolean insecureSkipVerify = Boolean.parseBoolean(protocol.getInsecureSkipVerify());
if (insecureSkipVerify) {
connOpts.setHttpsHostnameVerificationEnabled(false);
}
if (Boolean.parseBoolean(protocol.getEnableMutualAuth())) {
connOpts.setSocketFactory(MqttSslFactory.getMslSocketFactory(protocol, insecureSkipVerify));
} else {
connOpts.setSocketFactory(MqttSslFactory.getSslSocketFactory(protocol, insecureSkipVerify));
}
}
StopWatch connectWatch = new StopWatch();
connectWatch.start();
client.connect(connOpts).waitForCompletion(Long.parseLong(protocol.getTimeout()));
connectWatch.stop();
return connectWatch.getTotalTimeMillis();
}
/**
* Test MQTT subscribe and publish capabilities
*/
private void testSubscribeAndPublish(MqttAsyncClient client, MqttProtocol protocol, Map<Object, String> data) {
// 1 test subscribe
if (StringUtils.isNotBlank(protocol.getTopic())) {
String subscribe = testSubscribe(client, protocol.getTopic());
if (StringUtils.isBlank(subscribe)) {
data.put("canSubscribe", "Subscription successful");
} else {
data.put("canSubscribe", String.format("Subscription failed: %s", subscribe));
}
} else {
data.put("canSubscribe", "No topic, subscription test skipped");
}
// 2 test publish
if (StringUtils.isNotBlank(protocol.getTestMessage())) {
String publish = testPublish(client, protocol.getTopic(), protocol.getTestMessage());
if (StringUtils.isBlank(publish)) {
data.put("canPublish", "Message published successfully");
// 3 test receive message
String receivedData = getReceivedData(client, protocol.getTopic());
data.put("canReceive", receivedData);
} else {
data.put("canPublish", String.format("Message publishing failed: %s", publish));
data.put("canReceive", "Message reception skipped due to failed publish");
}
} else {
data.put("canPublish", "No test message, publish test skipped");
data.put("canReceive", "No test message, receive test skipped");
}
// 4 test unsubscribe
if (StringUtils.isNotBlank(protocol.getTopic())) {
String subscribe = testUnSubscribe(client, protocol.getTopic());
if (StringUtils.isBlank(subscribe)) {
data.put("canUnSubscribe", "Unsubscription successful");
} else {
data.put("canUnSubscribe", String.format("Unsubscription failed: %s", subscribe));
}
} else {
data.put("canUnSubscribe", "No topic, unsubscription test skipped");
}
}
private String getReceivedData(MqttAsyncClient client, String topic) {
final CountDownLatch latch = new CountDownLatch(1);
final StringBuilder messageHolder = new StringBuilder();
client.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
latch.countDown();
}
@Override
public void messageArrived(String arrivedTopic, MqttMessage message) {
if (topic.equals(arrivedTopic)) {
messageHolder.append(new String(message.getPayload()));
latch.countDown();
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
Mqtt5AsyncClient client = buildMqtt5Client(mqttProtocol);
long responseTime = connectClient(client, mqtt5AsyncClient -> {
CompletableFuture<Mqtt5ConnAck> connectFuture = mqtt5AsyncClient.connect();
try {
connectFuture.get(Long.parseLong(mqttProtocol.getTimeout()), TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(getErrorMessage(e.getMessage()));
}
});
try {
boolean received = latch.await(5, TimeUnit.SECONDS);
if (messageHolder.length() > 0) {
return messageHolder.toString();
} else if (!received) {
return "Message reception timed out after 5 seconds";
} else {
return "No valid message received";
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return e.getMessage();
} finally {
client.setCallback(null);
}
}
private String testSubscribe(MqttAsyncClient client, String topic) {
try {
IMqttToken subToken = client.subscribe(topic, 1);
subToken.waitForCompletion(5000);
return "";
} catch (MqttException e) {
logger.warn("MQTT subscribe test failed: {}", e.getMessage());
return e.getMessage();
}
}
private String testPublish(MqttAsyncClient client, String topic, String message) {
try {
MqttMessage mqttMessage = new MqttMessage(message.getBytes());
mqttMessage.setQos(1);
IMqttToken pubToken = client.publish(topic, mqttMessage);
pubToken.waitForCompletion(5000);
return "";
} catch (MqttException e) {
logger.warn("MQTT publish test failed: {}", e.getMessage());
return e.getMessage();
}
}
private String testUnSubscribe(MqttAsyncClient client, String topic) {
try {
IMqttToken unsubToken = client.unsubscribe(topic);
unsubToken.waitForCompletion(5000);
return "";
} catch (MqttException e) {
logger.warn("MQTT unsubscribe test failed: {}", e.getMessage());
return e.getMessage();
}
testDescribeAndPublish5(client, mqttProtocol, data);
convertToMetricsData(builder, metrics, responseTime, data);
client.disconnect();
}
/**
* Convert collected data to MetricsData
* collecting data of MQTT 3.1.1
*/
private void collectWithVersion3(Metrics metrics, Builder builder) {
MqttProtocol mqttProtocol = metrics.getMqtt();
Map<Object, String> data = new HashMap<>();
Mqtt3AsyncClient client = buildMqtt3Client(mqttProtocol);
long responseTime = connectClient(client, mqtt3AsyncClient -> {
CompletableFuture<Mqtt3ConnAck> connectFuture = mqtt3AsyncClient.connect();
try {
connectFuture.get(Long.parseLong(mqttProtocol.getTimeout()), TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(getErrorMessage(e.getMessage()));
}
});
testDescribeAndPublish3(client, mqttProtocol, data);
convertToMetricsData(builder, metrics, responseTime, data);
client.disconnect();
}
private void testDescribeAndPublish3(Mqtt3AsyncClient client, MqttProtocol mqttProtocol, Map<Object, String> data) {
data.put("canDescribe", test(() -> {
client.subscribeWith().topicFilter(mqttProtocol.getTopic()).qos(MqttQos.AT_LEAST_ONCE).send();
client.unsubscribeWith().topicFilter(mqttProtocol.getTopic()).send();
}, "subscribe").toString());
data.put("canPublish", !mqttProtocol.testPublish() ? Boolean.FALSE.toString() : test(() -> {
client.publishWith().topic(mqttProtocol.getTopic())
.payload(mqttProtocol.getTestMessage().getBytes(StandardCharsets.UTF_8))
.qos(MqttQos.AT_LEAST_ONCE).send();
data.put("canPublish", Boolean.TRUE.toString());
}, "publish").toString());
}
private void testDescribeAndPublish5(Mqtt5AsyncClient client, MqttProtocol mqttProtocol, Map<Object, String> data) {
data.put("canDescribe", test(() -> {
client.subscribeWith().topicFilter(mqttProtocol.getTopic()).qos(MqttQos.AT_LEAST_ONCE).send();
client.unsubscribeWith().topicFilter(mqttProtocol.getTopic()).send();
}, "subscribe").toString());
data.put("canPublish", !mqttProtocol.testPublish() ? Boolean.FALSE.toString() : test(() -> {
client.publishWith().topic(mqttProtocol.getTopic())
.payload(mqttProtocol.getTestMessage().getBytes(StandardCharsets.UTF_8))
.qos(MqttQos.AT_LEAST_ONCE).send();
data.put("canPublish", Boolean.TRUE.toString());
}, "publish").toString());
}
private Mqtt5AsyncClient buildMqtt5Client(MqttProtocol mqttProtocol) {
Mqtt5ClientBuilder mqtt5ClientBuilder = Mqtt5Client.builder()
.serverHost(mqttProtocol.getHost())
.identifier(mqttProtocol.getClientId())
.serverPort(Integer.parseInt(mqttProtocol.getPort()));
if (mqttProtocol.hasAuth()) {
mqtt5ClientBuilder.simpleAuth().username(mqttProtocol.getUsername())
.password(mqttProtocol.getPassword().getBytes(StandardCharsets.UTF_8))
.applySimpleAuth();
}
return mqtt5ClientBuilder.buildAsync();
}
private Mqtt3AsyncClient buildMqtt3Client(MqttProtocol mqttProtocol) {
Mqtt3ClientBuilder mqtt3ClientBuilder = Mqtt3Client.builder()
.serverHost(mqttProtocol.getHost())
.identifier(mqttProtocol.getClientId())
.serverPort(Integer.parseInt(mqttProtocol.getPort()));
if (mqttProtocol.hasAuth()) {
mqtt3ClientBuilder.simpleAuth().username(mqttProtocol.getUsername())
.password(mqttProtocol.getPassword().getBytes(StandardCharsets.UTF_8))
.applySimpleAuth();
}
return mqtt3ClientBuilder.buildAsync();
}
public <T> long connectClient(T client, Consumer<T> connect) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
connect.accept(client);
stopWatch.stop();
return stopWatch.getTotalTimeMillis();
}
private void convertToMetricsData(Builder builder, Metrics metrics, long responseTime, Map<Object, String> data) {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String column : metrics.getAliasFields()) {
@@ -288,4 +207,25 @@ public class MqttCollectImpl extends AbstractCollect {
builder.addValueRow(valueRowBuilder.build());
}
private Boolean test(Runnable runnable, String operationName) {
try {
runnable.run();
return true;
} catch (Exception e) {
logger.error("{} fail", operationName, e);
}
return false;
}
private String getErrorMessage(String errorMessage) {
if (StringUtils.isBlank(errorMessage)) {
return "connect failed";
}
String[] split = errorMessage.split(":");
if (split.length > 1) {
return Arrays.stream(split).skip(1).collect(Collectors.joining(":"));
}
return errorMessage;
}
}
@@ -1,186 +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.collector.collect.mqtt;
import org.apache.hertzbeat.common.entity.job.protocol.MqttProtocol;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collection;
/**
* Support MQTT SSL Factory
*/
public class MqttSslFactory {
/**
* Get MSL Socket Factory
*/
public static SSLSocketFactory getMslSocketFactory(MqttProtocol mqttProtocol, boolean insecureSkipVerify) {
try {
Security.addProvider(new BouncyCastleProvider());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
Certificate[] chain = null;
if (mqttProtocol.getClientCert() != null && !mqttProtocol.getClientCert().isEmpty()) {
String formatClientCert = CertificateFormatter.formatCertificateChain(mqttProtocol.getClientCert());
try (InputStream certIn = new ByteArrayInputStream(formatClientCert.getBytes())) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection<? extends Certificate> certs = cf.generateCertificates(certIn);
chain = certs.toArray(new Certificate[0]);
}
}
PrivateKey privateKey;
if (mqttProtocol.getClientKey() != null && !mqttProtocol.getClientKey().isEmpty()) {
String formatClientKey = CertificateFormatter.formatPrivateKey(mqttProtocol.getClientKey());
try (PEMParser pemParser = new PEMParser(new StringReader(formatClientKey))) {
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
Object object = pemParser.readObject();
if (object instanceof PEMKeyPair) {
privateKey = converter.getPrivateKey(((PEMKeyPair) object).getPrivateKeyInfo());
} else if (object instanceof PrivateKeyInfo) {
privateKey = converter.getPrivateKey((PrivateKeyInfo) object);
} else {
throw new IllegalArgumentException("Unsupported private key type");
}
ks.setKeyEntry("private-key", privateKey, "".toCharArray(), chain);
}
}
TrustManager[] trustManagers;
if (insecureSkipVerify) {
trustManagers = createInsecureTrustManager();
} else {
String formatCaCert = CertificateFormatter.formatCertificateChain(mqttProtocol.getCaCert());
KeyStore trustStore = createMergedTrustStore(formatCaCert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
trustManagers = tmf.getTrustManagers();
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, "".toCharArray());
SSLContext context = SSLContext.getInstance(mqttProtocol.getTlsVersion());
context.init(kmf.getKeyManagers(), trustManagers, null);
return context.getSocketFactory();
} catch (Exception e) {
throw new RuntimeException("Fails to SSL initialize: " + e.getMessage(), e);
}
}
/**
* Get SSL Socket Factory
*/
public static SSLSocketFactory getSslSocketFactory(MqttProtocol mqttProtocol, boolean insecureSkipVerify) {
try {
Security.addProvider(new BouncyCastleProvider());
TrustManager[] trustManagers;
if (insecureSkipVerify) {
trustManagers = createInsecureTrustManager();
} else {
String formatCaCert = CertificateFormatter.formatCertificateChain(mqttProtocol.getCaCert());
KeyStore trustStore = createMergedTrustStore(formatCaCert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
trustManagers = tmf.getTrustManagers();
}
SSLContext sslContext = SSLContext.getInstance(mqttProtocol.getTlsVersion());
sslContext.init(null, trustManagers, null);
return sslContext.getSocketFactory();
} catch (Exception e) {
throw new RuntimeException("Fails to SSL initialize: " + e.getMessage(), e);
}
}
private static TrustManager[] createInsecureTrustManager() {
return new TrustManager[]{
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
};
}
private static KeyStore createMergedTrustStore(String caCertPem) throws Exception {
KeyStore mergedKs = KeyStore.getInstance(KeyStore.getDefaultType());
mergedKs.load(null, null);
TrustManagerFactory systemTmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
systemTmf.init((KeyStore) null);
X509TrustManager systemTm = (X509TrustManager) systemTmf.getTrustManagers()[0];
int systemIndex = 1;
for (X509Certificate cert : systemTm.getAcceptedIssuers()) {
mergedKs.setCertificateEntry("system-ca-" + systemIndex++, cert);
}
if (caCertPem != null && !caCertPem.isEmpty()) {
try (InputStream caIn = new ByteArrayInputStream(caCertPem.getBytes())) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection<? extends Certificate> customCerts = cf.generateCertificates(caIn);
int customIndex = 1;
for (Certificate cert : customCerts) {
mergedKs.setCertificateEntry("custom-ca-" + customIndex++, cert);
}
}
}
return mergedKs;
}
}
@@ -17,91 +17,108 @@
package org.apache.hertzbeat.collector.collect.mqtt;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.hivemq.client.mqtt.MqttVersion;
import org.apache.hertzbeat.collector.dispatch.DispatchConstants;
import org.apache.hertzbeat.common.entity.job.Metrics;
import org.apache.hertzbeat.common.entity.job.protocol.MqttProtocol;
import org.apache.hertzbeat.common.entity.message.CollectRep;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* Test case for {@link MqttCollectImpl}
*/
class MqttCollectTest {
public class MqttCollectTest {
private MqttCollectImpl mqttCollect;
private Metrics metrics;
private MqttProtocol.MqttProtocolBuilder mqttBuilder;
private CollectRep.MetricsData.Builder builder;
@BeforeEach
void setup() {
public void setup() {
mqttCollect = new MqttCollectImpl();
metrics = new Metrics();
// Initialize base MQTT parameters for test cases
mqttBuilder = MqttProtocol.builder()
.host("example.com")
.port("1883")
.protocol("mqtt")
.timeout("5000")
.keepalive("60");
}
// Region: preCheck validation tests
@Test
// Verify preCheck throws exception when host is missing
void preCheckShouldThrowWhenHostMissing() {
metrics.setMqtt(mqttBuilder.host("").build());
assertThrows(IllegalArgumentException.class, () -> mqttCollect.preCheck(metrics));
MqttProtocol mqtt = MqttProtocol.builder().build();
metrics = Metrics.builder()
.mqtt(mqtt)
.build();
builder = CollectRep.MetricsData.newBuilder();
}
@Test
// Verify preCheck throws exception when port is missing
void preCheckShouldThrowWhenPortMissing() {
metrics.setMqtt(mqttBuilder.port("").build());
assertThrows(IllegalArgumentException.class, () -> mqttCollect.preCheck(metrics));
void preCheck() {
// host is empty
assertThrows(IllegalArgumentException.class, () -> {
mqttCollect.preCheck(metrics);
});
// port is empty
assertThrows(IllegalArgumentException.class, () -> {
MqttProtocol mqtt = MqttProtocol.builder().build();
mqtt.setHost("example.com");
metrics.setMqtt(mqtt);
mqttCollect.preCheck(metrics);
});
// protocol version is empty
assertThrows(IllegalArgumentException.class, () -> {
MqttProtocol mqtt = MqttProtocol.builder().build();
mqtt.setHost("example.com");
mqtt.setPort("1883");
metrics.setMqtt(mqtt);
mqttCollect.preCheck(metrics);
});
// everything is ok
assertDoesNotThrow(() -> {
MqttProtocol mqtt = MqttProtocol.builder().build();
mqtt.setHost("example.com");
mqtt.setPort("1883");
metrics.setMqtt(mqtt);
mqtt.setProtocolVersion("3.1.1");
mqttCollect.preCheck(metrics);
});
}
@Test
// Verify preCheck throws exception when MQTTS mutual auth is enabled but CA cert is missing
void preCheckShouldThrowWhenMqttsMutualAuthMissingCerts() {
metrics.setMqtt(mqttBuilder
.protocol("mqtts")
.enableMutualAuth("true")
.caCert("")
.clientCert("client.crt")
.clientKey("client.key")
.build());
assertThrows(IllegalArgumentException.class, () -> mqttCollect.preCheck(metrics));
void supportProtocol() {
Assertions.assertEquals(DispatchConstants.PROTOCOL_MQTT, mqttCollect.supportProtocol());
}
@Test
// Verify preCheck succeeds with valid standard MQTT parameters
void preCheckShouldSucceedWithValidMqttParams() {
metrics.setMqtt(mqttBuilder.build());
assertDoesNotThrow(() -> mqttCollect.preCheck(metrics));
}
void collect() {
// with version 3.1.1
assertDoesNotThrow(() -> {
MqttProtocol mqtt = MqttProtocol.builder().build();
mqtt.setHost("example.com");
mqtt.setPort("1883");
mqtt.setClientId("clientid");
mqtt.setTimeout("1");
mqtt.setProtocolVersion(MqttVersion.MQTT_3_1_1.name());
@Test
// Verify preCheck succeeds with valid MQTTS parameters including mutual authentication
void preCheckShouldSucceedWithValidMqttsMutualAuth() {
metrics.setMqtt(mqttBuilder
.protocol("mqtts")
.enableMutualAuth("true")
.caCert("ca.pem")
.clientCert("client.crt")
.clientKey("client.key")
.build());
assertDoesNotThrow(() -> mqttCollect.preCheck(metrics));
}
// End region
metrics.setMqtt(mqtt);
metrics.setAliasFields(new ArrayList<>());
@Test
// Verify supportProtocol method returns correct MQTT constant
void supportProtocolShouldReturnMqttConstant() {
assertEquals(DispatchConstants.PROTOCOL_MQTT, mqttCollect.supportProtocol());
mqttCollect.collect(builder, metrics);
});
assertDoesNotThrow(() -> {
MqttProtocol mqtt = MqttProtocol.builder().build();
mqtt.setHost("example.com");
mqtt.setPort("1883");
mqtt.setClientId("clientid");
mqtt.setTimeout("1");
mqtt.setProtocolVersion(MqttVersion.MQTT_5_0.name());
metrics.setMqtt(mqtt);
metrics.setAliasFields(new ArrayList<>());
mqttCollect.collect(builder, metrics);
});
}
}
@@ -87,11 +87,6 @@ public interface CommonConstants {
*/
String LABEL_INSTANCE = "instance";
/**
* label key: defineid
*/
String LABEL_DEFINE_ID = "defineid";
/**
* label key: alert name
*/
@@ -33,73 +33,49 @@ import org.apache.commons.lang3.StringUtils;
public class MqttProtocol implements CommonRequestProtocol, Protocol {
/**
* mqtt client id
*/
private String clientId;
/**
* mqtt username
*/
private String username;
/**
* mqtt password
*/
private String password;
/**
* mqtt host
* ip address or domain name of the peer host
*/
private String host;
/**
* mqtt port
* peer host port
*/
private String port;
/**
* mqtt protocol version
* MQTT,MQTTS
* username
*/
private String protocol;
private String username;
/**
* mqtt connect timeout
* the maximum time to wait for a connection to be established
* password
*/
private String password;
/**
* time out period
*/
private String timeout;
/**
* mqtt keepalive
* between ping requests to the broker to keep the connection alive
* client id
*/
private String keepalive;
private String clientId;
/**
* mqtt topic name
*/
private String topic;
/**
* mqtt publish message
* message used to test whether the mqtt connection can be pushed normally
*/
private String testMessage;
/**
* mqtt tls version
* TLSv1.2, TLSv1.3
* protocol version of mqtt
*/
private String tlsVersion;
private String protocolVersion;
/**
* mqtt tls insecure skip verify server certificate
* monitor topic
*/
private String insecureSkipVerify;
/**
* mqtt tls ca cert
*/
private String caCert;
/**
* mqtt tls enable mutual auth
*/
private String enableMutualAuth;
/**
* mqtt tls client cert
*/
private String clientCert;
/**
* mqtt tls client key
*/
private String clientKey;
private String topic;
/**
* Determine whether authentication is required
@@ -109,4 +85,11 @@ public class MqttProtocol implements CommonRequestProtocol, Protocol {
return StringUtils.isNotBlank(this.username) && StringUtils.isNotBlank(this.password);
}
/**
* Determine whether you need to test whether messages can be pushed normally
* @return turn if it has test message
*/
public boolean testPublish(){
return StringUtils.isNotBlank(this.testMessage);
}
}
@@ -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"));
}
}
@@ -43,12 +43,12 @@ public class SwaggerConfig {
.info(new Info()
.title("HertzBeat")
.description("An Open-Source Real-time Monitoring Tool.")
.termsOfService("https://hertzbeat.apache.org/")
.termsOfService("https://hertzbeat.com/")
.contact(new Contact().name("tom").url("https://github.com/tomsun28").email("tomsun28@outlook.com"))
.version("v1.0")
.license(new License().name("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0")))
.externalDocs(new ExternalDocumentation()
.description("HertzBeat Docs").url("https://hertzbeat.apache.org/docs/"))
.description("HertzBeat Docs").url("https://hertzbeat.com/docs/"))
.addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME))
.components(new Components().addSecuritySchemes(SECURITY_SCHEME_NAME,
new SecurityScheme()
@@ -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 {
@@ -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
*
@@ -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);
@@ -138,7 +138,7 @@ warehouse:
username: root
password: root
insert:
buffer-size: 100
buffer-size: 1000
flush-interval: 3
cluster:
enabled: false
@@ -29,8 +29,8 @@ help:
zh-TW: HertzBeat 對 GreptimeDB 時序資料庫進行監控。<br><span class='help_module_span'><a class='help_module_content' https://docs.greptime.com/user-guide/operations/monitoring'>點擊查看開啓步驟</a>。</span>
ja-JP: HertzBeat は GreptimeDB 時系列データベースを監視します。<br><span class='help_module_span'><a class='help_module_content' https://docs.greptime.com/user-guide/operations/monitoring'>クリックしてガイドを見ます</a>。</span>
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/greptimedb
en-US: https://hertzbeat.apache.org/docs/help/greptimedb
zh-CN: https://hertzbeat.com/zh-cn/docs/help/greptimedb
en-US: https://hertzbeat.com/docs/help/greptimedb
# Input params define for monitoring(render web ui by the definition)
params:
# field-param field key
@@ -29,8 +29,8 @@ help:
zh-TW: HertzBeat 對 InfluxDB 時序資料庫進行監控。<br><span class='help_module_span'><a class='help_module_content' href='https://docs.influxdata.com/platform/monitoring/influxdata-platform/tools/measurements-internal'>點擊查看開啓步驟</a>。</span>
ja-JP: HertzBeat は InfluxDB 時系列データベースを監視します。<br><span class='help_module_span'><a class='help_module_content' href='https://docs.influxdata.com/platform/monitoring/influxdata-platform/tools/measurements-internal'>クリックしてガイドを見ます</a>。</span>
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/influxdb/
en-US: https://hertzbeat.apache.org/docs/help/influxdb/
zh-CN: https://hertzbeat.com/zh-cn/docs/help/influxdb/
en-US: https://hertzbeat.com/docs/help/influxdb/
# Input params define for monitoring(render web ui by the definition)
params:
# field-param field key
@@ -18,13 +18,11 @@ app: kafka_client
name:
zh-CN: Kafka消息系统(客户端)
en-US: Kafka MessageClient
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^_^
@@ -20,13 +20,11 @@ app: kafka_promql
name:
zh-CN: Kafka-PromQL
en-US: Kafka-PromQL
ja-JP: Kafka-PromQL
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 使用 Prometheus PromQL 从 Prometheus 服务器中查询到 Kafka 的通用指标数据来进行监控。此方案适用于 Prometheus 已监控 Kafka,需要从 Prometheus 服务器抓取 Kafka 的监控数据。<br>您可以点击 “<i>新建 Kafka-PromQL</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: HertzBeat uses Prometheus PromQL query metrics data from Prometheus Server to monitoring Kafka. This solution is suitable for Prometheus to monitor Kafka, and it need to capture Kafka monitoring data from the Prometheus server. <br>You could click the "<i>New Kafka-PromQL</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat 使用 Prometheus PromQL 從 Prometheus 服務器中查詢到 Kafka 的通用指標數據來進行監控。此方案適用于 Prometheus 已監控 Kafka,需要從 Prometheus 服務器抓取 Kafka 的監控數據。<br>您可以點擊 “<i>新建 Kafka-PromQL</i>” 並進行配置,或者選擇“<i>更多操作</i>”,導入已有配置。
ja-JP: Hertzbeat は Prometheus PromQL を介して Prometheus サーバーに Kafka の一般的なパフォーマンスのメトリクスをクエリして監視します。このシナリオは、PrometheusがすでにKafkaを監視しており、PrometheusサーバーからKafkaの監視データを取得する必要がある場合に適用されます。。<br>「<i>新規 Kafka-PromQL</i>」をクリックして設定しましょう。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/kafka_promql
en-US: https://hertzbeat.apache.org/docs/help/kafka_promql
@@ -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: Method
ja-JP: リクエストメソッド
type: radio
required: true
options:
@@ -68,7 +63,6 @@ params:
name:
zh-CN: 相对路径
en-US: URI
ja-JP: URI
type: text
limit: 200
required: true
@@ -78,14 +72,12 @@ params:
name:
zh-CN: 启动SSL
en-US: SSL
ja-JP: SSL
type: boolean
required: false
- field: headers
name:
zh-CN: 请求Headers
en-US: Headers
ja-JP: ヘッダ
type: key-value
required: false
keyAlias: Header Name
@@ -94,7 +86,6 @@ params:
name:
zh-CN: 查询Params
en-US: Params
ja-JP: パラメータ
type: key-value
required: false
keyAlias: Param Key
@@ -103,7 +94,6 @@ params:
name:
zh-CN: Content-Type
en-US: Content-Type
ja-JP: コンテンツタイプ
type: text
placeholder: '请求BODY资源类型'
required: false
@@ -112,7 +102,6 @@ params:
name:
zh-CN: 请求BODY
en-US: BODY
ja-JP: ボディ
type: textarea
placeholder: 'POST PUT请求时有效'
required: false
@@ -121,7 +110,6 @@ params:
name:
zh-CN: 认证方式
en-US: Auth Type
ja-JP: 認証方法
type: radio
required: false
hide: true
@@ -134,7 +122,6 @@ params:
name:
zh-CN: 用户名
en-US: Username
ja-JP: ユーザー名
type: text
limit: 50
required: false
@@ -143,7 +130,6 @@ params:
name:
zh-CN: 密码
en-US: Password
ja-JP: パスワード
type: password
required: false
hide: true
@@ -153,7 +139,6 @@ metrics:
i18n:
zh-CN: Kafka Broker 数量
en-US: Kafka Broker Count
ja-JP: Kafkaブローカー数量
# 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
@@ -165,25 +150,21 @@ metrics:
i18n:
zh-CN: 名称
en-US: Name
ja-JP: 名前
- field: instance
type: 1
i18n:
zh-CN: 实例
en-US: Instance
ja-JP: インスタンス
- field: timestamp
type: 1
i18n:
zh-CN: 时间戳
en-US: Timestamp
ja-JP: タイムスタンプ
- field: value
type: 1
i18n:
zh-CN: 数值
en-US: Value
ja-JP:
# The protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: http
# The config content when protocol is http
@@ -220,7 +201,6 @@ metrics:
i18n:
zh-CN: Kafka Topic 分区数量
en-US: Kafka Topic Partitions
ja-JP: Kafkaトピックのパーティション数量
# 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: 1
@@ -232,25 +212,21 @@ metrics:
i18n:
zh-CN: 名称
en-US: Name
ja-JP: 名前
- field: topic
type: 1
i18n:
zh-CN: 主题
en-US: Topic
ja-JP: トピック
- field: timestamp
type: 1
i18n:
zh-CN: 时间戳
en-US: Timestamp
ja-JP: タイムスタンプ
- field: value
type: 1
i18n:
zh-CN: 数值
en-US: Value
ja-JP:
# The protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: http
# The config content when protocol is http
@@ -288,7 +264,6 @@ metrics:
i18n:
zh-CN: Kafka Server Broker Topic 每秒字节入
en-US: Kafka Server Broker Topic Bytes In Per Second
ja-JP: Kafkaサーバーブローカーの1秒あたりのトピック合計受信されたバイト
# 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: 1
@@ -300,31 +275,26 @@ metrics:
i18n:
zh-CN: 实例
en-US: Instance
ja-JP: インスタンス
- field: job
type: 1
i18n:
zh-CN: 任务
en-US: Job
ja-JP: タスク
- field: topic
type: 1
i18n:
zh-CN: 主题
en-US: Topic
ja-JP: トピック
- field: timestamp
type: 1
i18n:
zh-CN: 时间戳
en-US: Timestamp
ja-JP: タイムスタンプ
- field: value
type: 1
i18n:
zh-CN: 数值
en-US: Value
ja-JP:
# The protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: http
# The specific collection configuration when the protocol is http
@@ -21,13 +21,11 @@ app: kingbase
name:
zh-CN: Kingbase数据库
en-US: Kingbase DB
ja-JP: Kingbaseデータベース
# The description and help of this monitoring type
help:
zh-CN: HertzBeat 使用 <a class='help_module_content' href='https://hertzbeat.apache.org/docs/advanced/extend-jdbc'> JDBC 协议</a> 通过配置 SQL 对 Kingbase 数据库的通用性能指标 (basic、state、activity etc) 进行采集监控,支持版本为 KingbaseV8r6+。<br>您可以点击“<i>新建 Kingbase 数据库</i>”并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: HertzBeat uses <a class='help_module_content' href='https://hertzbeat.apache.org/docs/advanced/extend-jdbc'> JDBC Protocol</a> to configure SQL for collecting general metrics of Kingbase database (basic、state、activity etc). Supported version is KingbaseV8r6+. <br>You can click "<i>New Kingbase Database</i>" and configure it, or select "<i>More Action</i>" to import the existing configuration.
zh-TW: HertzBeat 使用 <a class='help_module_content' href='https://hertzbeat.apache.org/docs/advanced/extend-jdbc'> JDBC 協議</a> 通過配置 SQL 對 Kingbase 數據庫的通用性能指標 (basic、state、activity etc)進行采集監控,支持版本爲 KingbaseV8r6+。<br>您可以點擊“<i>新建 Kingbase 數據庫</i>”並進行配置,或者選擇“<i>更多操作</i>”,導入已有配置。
ja-JP: Hertzbeat は <a class='help_module_content' href='https://hertzbeat.apache.org/docs/advanced/extend-jdbc'> JDBCプロトコルを介して</a> Kingbase データベース(V8r6+)の一般的なパフォーマンスのメトリクスを監視します。<br>「<i>新規 Kingbase データベース</i>」をクリックしてパラメタを設定した後、新規することができます。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/kingbase
en-US: https://hertzbeat.apache.org/docs/help/kingbase
@@ -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
@@ -63,7 +59,6 @@ params:
name:
zh-CN: 查询超时时间(ms)
en-US: Query Timeout(ms)
ja-JP: クエリタイムアウト(ms)
type: number
range: '[400,200000]'
required: false
@@ -73,7 +68,6 @@ params:
name:
zh-CN: 数据库名称
en-US: Database Name
ja-JP: データベース名
type: text
defaultValue: kingbase
required: false
@@ -81,7 +75,6 @@ params:
name:
zh-CN: 用户名
en-US: Username
ja-JP: ユーザー名
type: text
limit: 50
required: false
@@ -89,14 +82,12 @@ params:
name:
zh-CN: 密码
en-US: Password
ja-JP: パスワード
type: password
required: false
- field: url
name:
zh-CN: URL
en-US: URL
ja-JP: URL
type: text
required: false
hide: true
@@ -108,7 +99,6 @@ metrics:
i18n:
zh-CN: 基本信息
en-US: Basic 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
@@ -121,31 +111,26 @@ metrics:
i18n:
zh-CN: 服务器版本
en-US: Server Version
ja-JP: バージョン
- field: port
type: 1
i18n:
zh-CN: 端口
en-US: Port
ja-JP: ポート
- field: server_encoding
type: 1
i18n:
zh-CN: 服务器编码
en-US: Server Encoding
ja-JP: サーバーのエンコード
- field: data_directory
type: 1
i18n:
zh-CN: 数据目录
en-US: Data Directory
ja-JP: データディレクトリ
- field: max_connections
type: 0
i18n:
zh-CN: 最大连接数
en-US: Max Connections
ja-JP: 最大接続数
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: jdbc
# the config content when protocol is jdbc
@@ -170,7 +155,6 @@ metrics:
i18n:
zh-CN: 状态信息
en-US: State Info
ja-JP: 状態情報
priority: 1
fields:
- field: db_name
@@ -179,55 +163,47 @@ metrics:
i18n:
zh-CN: 数据库名称
en-US: Database Name
ja-JP: データベース名
- field: conflicts
type: 0
unit: times
i18n:
zh-CN: 冲突次数
en-US: Conflicts
ja-JP: コンフリクト回数
- field: deadlocks
type: 0
unit: times
i18n:
zh-CN: 死锁次数
en-US: Deadlocks
ja-JP: デッドロック回数
- field: blks_read
type: 0
unit: blocks per second
i18n:
zh-CN: 读取块
en-US: Blocks Read
ja-JP: 読み取られたブロック
- field: blks_hit
type: 0
unit: blocks per second
i18n:
zh-CN: 命中块
en-US: Blocks Hit
ja-JP: ヒットブロック
- field: blk_read_time
type: 0
unit: ms
i18n:
zh-CN: 读取时间
en-US: Read Time
ja-JP: 読み取られタイム
- field: blk_write_time
type: 0
unit: ms
i18n:
zh-CN: 写入时间
en-US: Write Time
ja-JP: 書き込まれ時間
- field: stats_reset
type: 1
i18n:
zh-CN: 统计重置
en-US: Stats Reset
ja-JP: 統計リセット
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -245,7 +221,6 @@ metrics:
i18n:
zh-CN: 活动信息
en-US: Activity Info
ja-JP: 活動情報
priority: 2
fields:
- field: running
@@ -254,7 +229,6 @@ metrics:
i18n:
zh-CN: 运行中
en-US: Running
ja-JP: 実行中
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -272,7 +246,6 @@ metrics:
i18n:
zh-CN: 资源配置
en-US: Resource Config
ja-JP: リソース設定
priority: 3
fields:
- field: work_mem
@@ -281,40 +254,34 @@ metrics:
i18n:
zh-CN: 工作内存
en-US: Work Memory
ja-JP: ワークメモリ
- field: shared_buffers
type: 0
unit: MB
i18n:
zh-CN: 共享缓冲区
en-US: Shared Buffers
ja-JP: 共有バッファ
- field: autovacuum
type: 1
i18n:
zh-CN: 自动清理
en-US: Auto Vacuum
ja-JP: オートバキューム
- field: max_connections
type: 0
i18n:
zh-CN: 最大连接数
en-US: Max Connections
ja-JP: 最大接続数
- field: effective_cache_size
type: 0
unit: MB
i18n:
zh-CN: 有效缓存大小
en-US: Effective Cache Size
ja-JP: キャッシュサイズ
- field: wal_buffers
type: 0
unit: MB
i18n:
zh-CN: WAL缓冲区
en-US: WAL Buffers
ja-JP: WALバッファ
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -332,7 +299,6 @@ metrics:
i18n:
zh-CN: 连接信息
en-US: Connection Info
ja-JP: 接続情報
priority: 4
fields:
- field: active
@@ -340,7 +306,6 @@ metrics:
i18n:
zh-CN: 活动连接
en-US: Active Connection
ja-JP: 活躍的な接続
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -358,7 +323,6 @@ metrics:
i18n:
zh-CN: 连接状态
en-US: Connection State
ja-JP: 接続状態
priority: 5
fields:
- field: state
@@ -367,13 +331,11 @@ metrics:
i18n:
zh-CN: 状态
en-US: State
ja-JP: 状態
- field: num
type: 0
i18n:
zh-CN: 数量
en-US: Num
ja-JP: 数量
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -391,7 +353,6 @@ metrics:
i18n:
zh-CN: 连接数据库
en-US: Connection Db
ja-JP: 接続データベース
priority: 6
fields:
- field: db_name
@@ -400,13 +361,11 @@ metrics:
i18n:
zh-CN: 数据库名称
en-US: Database Name
ja-JP: データベース名
- field: active
type: 0
i18n:
zh-CN: 活动连接
en-US: Active Connection
ja-JP: 活躍的な接続
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -424,7 +383,6 @@ metrics:
i18n:
zh-CN: 元组信息
en-US: Tuple Info
ja-JP: 組情報
priority: 7
fields:
- field: fetched
@@ -432,31 +390,26 @@ metrics:
i18n:
zh-CN: 获取次数
en-US: Fetched
ja-JP: フェッチ回数
- field: returned
type: 0
i18n:
zh-CN: 返回次数
en-US: Returned
ja-JP: 戻る回数
- field: inserted
type: 0
i18n:
zh-CN: 插入次数
en-US: Inserted
ja-JP: インサート回数
- field: updated
type: 0
i18n:
zh-CN: 更新次数
en-US: Updated
ja-JP: 更新回数
- field: deleted
type: 0
i18n:
zh-CN: 删除次数
en-US: Deleted
ja-JP: 削除回数
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -474,7 +427,6 @@ metrics:
i18n:
zh-CN: 临时文件
en-US: Temp File
ja-JP: 一時ファイル
priority: 8
fields:
- field: db_name
@@ -483,20 +435,17 @@ metrics:
i18n:
zh-CN: 数据库名称
en-US: Database Name
ja-JP: データベース名
- field: num
type: 0
i18n:
zh-CN: 次数
en-US: Num
ja-JP: 数量
- field: size
type: 0
unit: B
i18n:
zh-CN: 大小
en-US: Size
ja-JP: サイズ
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -514,7 +463,6 @@ metrics:
i18n:
zh-CN: 锁信息
en-US: Lock Info
ja-JP: ロック情報
priority: 9
fields:
- field: db_name
@@ -523,21 +471,18 @@ metrics:
i18n:
zh-CN: 数据库名称
en-US: Database Name
ja-JP: データベース名
- field: conflicts
type: 0
unit: times
i18n:
zh-CN: 冲突次数
en-US: Conflicts
ja-JP: コンフリクト回数
- field: deadlocks
type: 0
unit: times
i18n:
zh-CN: 死锁次数
en-US: Deadlocks
ja-JP: デッドロック回数
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -555,7 +500,6 @@ metrics:
i18n:
zh-CN: 慢查询
en-US: Slow Sql
ja-JP: スローSQL
priority: 10
fields:
- field: sql_text
@@ -564,33 +508,28 @@ metrics:
i18n:
zh-CN: SQL语句
en-US: SQL Text
ja-JP: SQL文のテキスト
- field: calls
type: 0
i18n:
zh-CN: 调用次数
en-US: Calls
ja-JP: コール回数
- field: rows
type: 0
i18n:
zh-CN: 行数
en-US: Rows
ja-JP:
- field: avg_time
type: 0
unit: ms
i18n:
zh-CN: 平均时间
en-US: Avg Time
ja-JP: 平均時間
- field: total_time
type: 0
unit: ms
i18n:
zh-CN: 总时间
en-US: Total Time
ja-JP: 合計時間
aliasFields:
- query
- calls
@@ -618,7 +557,6 @@ metrics:
i18n:
zh-CN: 事务信息
en-US: Transaction Info
ja-JP: トランザクション情報
priority: 12
fields:
- field: db_name
@@ -627,21 +565,18 @@ metrics:
i18n:
zh-CN: 数据库名称
en-US: Database Name
ja-JP: データベース名
- field: commits
type: 0
unit: times
i18n:
zh-CN: 提交次数
en-US: Commits
ja-JP: コミット回数
- field: rollbacks
type: 0
unit: times
i18n:
zh-CN: 回滚次数
en-US: Rollbacks
ja-JP: ロールバック回数
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -659,7 +594,6 @@ metrics:
i18n:
zh-CN: 冲突信息
en-US: Conflicts Info
ja-JP: コンフリクト情報
priority: 13
fields:
- field: db_name
@@ -668,37 +602,31 @@ metrics:
i18n:
zh-CN: 数据库名称
en-US: Database Name
ja-JP: データベース名
- field: tablespace
type: 0
i18n:
zh-CN: 表空间
en-US: Tablespace
ja-JP: 表領域
- field: lock
type: 0
i18n:
zh-CN:
en-US: Lock
ja-JP: ロック
- field: snapshot
type: 0
i18n:
zh-CN: 快照
en-US: Snapshot
ja-JP: スナップショット
- field: bufferpin
type: 0
i18n:
zh-CN: 缓冲区
en-US: Bufferpin
ja-JP: バッファ
- field: deadlock
type: 0
i18n:
zh-CN: 死锁
en-US: Deadlock
ja-JP: デッドロック
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -716,7 +644,6 @@ metrics:
i18n:
zh-CN: 缓存命中率
en-US: Cache Hit Ratio
ja-JP: キャッシュ命中率
priority: 14
fields:
- field: db_name
@@ -725,14 +652,12 @@ metrics:
i18n:
zh-CN: 数据库名称
en-US: Database Name
ja-JP: データベース名
- field: ratio
type: 0
unit: '%'
i18n:
zh-CN: 命中率
en-US: Hit Ratio
ja-JP: 命中率
aliasFields:
- blks_hit
- blks_read
@@ -756,7 +681,6 @@ metrics:
i18n:
zh-CN: Checkpoint信息
en-US: Checkpoint Info
ja-JP: チェックポイント情報
priority: 15
fields:
- field: checkpoint_sync_time
@@ -765,14 +689,12 @@ metrics:
i18n:
zh-CN: Checkpoint同步时间
en-US: Checkpoint Sync Time
ja-JP: チェックポイント同期時間
- field: checkpoint_write_time
type: 0
unit: ms
i18n:
zh-CN: Checkpoint写入时间
en-US: Checkpoint Write Time
ja-JP: Checkpoint書き込まれた時間
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -790,7 +712,6 @@ metrics:
i18n:
zh-CN: Buffer信息
en-US: Buffer Info
ja-JP: バッファ情報
priority: 16
fields:
- field: allocated
@@ -798,31 +719,26 @@ metrics:
i18n:
zh-CN: 已分配
en-US: Allocated
ja-JP: 割り当てバッファ
- field: fsync_calls_by_backend
type: 0
i18n:
zh-CN: 后端进程直接执行的文件同步调用次数
en-US: Fsync Calls By Backend
ja-JP: バックエンド同期コール回数
- field: written_directly_by_backend
type: 0
i18n:
zh-CN: 后台写入到数据文件
en-US: Written Directly By Backend
ja-JP: バックエンドによる直接書き込まれたファイル
- field: written_by_background_writer
type: 0
i18n:
zh-CN: 后台写入
en-US: Written By Background Writer
ja-JP: バックグラウンドライターに書き込まれた
- field: written_during_checkpoints
type: 0
i18n:
zh-CN: 检查点期间写入
en-US: Written During Checkpoints
ja-JP: チェックポイント中の書き込み
protocol: jdbc
jdbc:
host: ^_^host^_^
@@ -21,13 +21,11 @@ app: kubernetes
name:
zh-CN: Kubernetes
en-US: Kubernetes
ja-JP: Kubernetes
# The description and help of this monitoring type
help:
zh-CN: HertzBeat 通过查询 Kubernetes ApiServer api 来对 kubernetes 的通用性能指标(nodes、namespaces、pods、services)进行采集监控。<br><span class='help_module_span'>注意⚠️:为了监控 Kubernetes 中的信息,则需要获取到可访问 Api Server 的授权 TOKEN,让采集请求获取到对应的信息,<a class='help_module_content' href='https://hertzbeat.apache.org/zh-cn/docs/help/kubernetes'>点击查看获取步骤</a>。</span>
en-US: HertzBeat monitoring Kubernetes general metrics such as nodes, namespaces and pods through querying data from Kubernetes ApiServer api. <br><span class='help_module_span'>Note⚠️:In order to monitor the information of Kubernetes, Hertzbeat need to obtain the authorized TOKEN that can access Api Server. <a class='help_module_content' href='https://hertzbeat.apache.org/docs/help/kubernetes'>Click here to view the specific steps.</a></span>
zh-TW: HertzBeat 通過查詢 Kubernetes ApiServer api 來對 kubernetes 的通用性能指標(nodes、namespaces、pods、services)進行采集監控。<br><span class='help_module_span'>注意⚠️:爲了監控 Kubernetes 中的信息,則需要獲取到可訪問 Api Server 的授權 TOKEN,讓采集請求獲取到對應的信息,<a class='help_module_content' href='https://hertzbeat.apache.org/zh-cn/docs/help/kubernetes'>點擊查看獲取步驟</a>。</span>
ja-JP: HertzBeat は Kubernetes ApiServer api を呼び出し、kubernetes の一般的なパフォーマンスのメトリクスを収集して監視します。<br><span class='help_module_span'>注意⚠️Kubernetesでメトリクスを監視するためには、Api Serverにアクセスするための認可されたTOKENを取得する必要があります。<a class='help_module_content' href='https://hertzbeat.apache.org/docs/help/kubernetes'>クリックしてガイドを見ます</a>。</span>
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/kubernetes
en-US: https://hertzbeat.apache.org/docs/help/kubernetes
@@ -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: ApiServer端口
en-US: ApiServer Port
ja-JP: ApiServerポート
# 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: 认证方式
en-US: Auth Type
ja-JP: 認証方法
# type-param field type(radio mapping the html radio tag)
type: radio
# required-true or false
@@ -79,7 +74,6 @@ params:
name:
zh-CN: 认证Token
en-US: Access Token
ja-JP: アクセストークン
type: text
required: true
# collect metrics config list
@@ -97,45 +91,38 @@ metrics:
i18n:
zh-CN: 节点名称
en-US: Node Name
ja-JP: ノード名
- field: is_ready
type: 1
i18n:
zh-CN: 节点就绪状态
en-US: Node Ready Status
ja-JP: ノード準備完了
- field: capacity_cpu
type: 0
i18n:
zh-CN: CPU 容量
en-US: CPU Capacity
ja-JP: CPU 容量
- field: allocatable_cpu
type: 0
i18n:
zh-CN: 可分配 CPU
en-US: Allocatable CPU
ja-JP: 割り当て可能CPU
- field: capacity_memory
type: 0
unit: Mi
i18n:
zh-CN: 内存容量
en-US: Memory Capacity
ja-JP: メモリ容量
- field: allocatable_memory
type: 0
unit: Mi
i18n:
zh-CN: 可分配内存
en-US: Allocatable Memory
ja-JP: 割り当て可能CPUメモリ
- field: creation_time
type: 1
i18n:
zh-CN: 创建时间
en-US: Creation Time
ja-JP: 作成時間
# (optional)metrics field alias name, it is used as an alias field to map and convert the collected data and metrics field
aliasFields:
- $.metadata.name
@@ -180,19 +167,16 @@ metrics:
i18n:
zh-CN: 命名空间
en-US: Namespace
ja-JP: 名前空間
- field: status
type: 1
i18n:
zh-CN: 状态
en-US: Status
ja-JP: ステータス
- field: creation_time
type: 1
i18n:
zh-CN: 创建时间
en-US: Creation Time
ja-JP: 作成時間
aliasFields:
- $.metadata.name
- $.status.phase
@@ -222,49 +206,41 @@ metrics:
i18n:
zh-CN: Pod名称
en-US: Pod Name
ja-JP: ポッド名
- field: namespace
type: 1
i18n:
zh-CN: 命名空间
en-US: Namespace
ja-JP: 名前空間
- field: status
type: 1
i18n:
zh-CN: 状态
en-US: Status
ja-JP: ステータス
- field: restart
type: 1
i18n:
zh-CN: 重启次数
en-US: Restart Count
ja-JP: リスタート回数
- field: host_ip
type: 1
i18n:
zh-CN: 主机IP
en-US: Host IP
ja-JP: ホストIP
- field: pod_ip
type: 1
i18n:
zh-CN: Pod IP
en-US: Pod IP
ja-JP: ポッドIP
- field: creation_time
type: 1
i18n:
zh-CN: 创建时间
en-US: Creation Time
ja-JP: 作成時間
- field: start_time
type: 1
i18n:
zh-CN: 启动时间
en-US: Start Time
ja-JP: 起動時間
aliasFields:
- $.metadata.name
- $.metadata.namespace
@@ -304,37 +280,31 @@ metrics:
i18n:
zh-CN: 服务
en-US: Service
ja-JP: サービス
- field: namespace
type: 1
i18n:
zh-CN: 命名空间
en-US: Namespace
ja-JP: 名前空間
- field: type
type: 1
i18n:
zh-CN: 类型
en-US: Type
ja-JP: タイプ
- field: cluster_ip
type: 1
i18n:
zh-CN: 集群IP
en-US: Cluster IP
ja-JP: クラスタIP
- field: selector
type: 1
i18n:
zh-CN: 选择器
en-US: Selector
ja-JP: セレクター
- field: creation_time
type: 1
i18n:
zh-CN: 创建时间
en-US: Creation Time
ja-JP: 作成時間
aliasFields:
- $.metadata.name
- $.metadata.namespace
@@ -21,13 +21,11 @@ app: kvrocks
name:
zh-CN: Kvrocks 数据库
en-US: Kvrocks
ja-JP: Kvrocksデータベース
# The description and help of this monitoring type
help:
zh-CN: HertzBeat 对 Apache Kvrocks 数据库的通用性能指标进行采集监控(server、clients、memory、persistence、stats、replication、cpu、cluster、commandstats),支持版本为 Apache Kvrocks 2.9.0+。<br>您可以点击“<i>新建 Kvrocks 数据库</i>”并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: HertzBeat monitors Apache Kvrocks database of general performance metrics such as memory, persistence, replication and so on. The versions we support is Apache Kvrocks 2.9.0+. <br>You could click the "<i>New Kvrocks</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: HertzBeat 對 Apache Kvrocks 數據庫的通用性能指標進行采集監控(server、clients、memory、persistence、stats、replication、cpu、cluster、commandstats),支持版本爲 Apache Kvrocks 2.9.0+。<br>您可以點擊“<i>新建 Kvrocks 數據庫</i>”並進行配置,或者選擇“<i>更多操作</i>”,導入已有配置。
ja-JP: Hertzbeat は Apache Kvrocks データベース(2.9.0+)の一般的なパフォーマンスのメトリクスを監視します。<br>「<i>新規 Kvrocks データベース</i>」をクリックしてパラメタを設定した後、新規することができます。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/kvrocks
en-US: https://hertzbeat.apache.org/docs/help/kvrocks
@@ -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: 超时时间
en-US: Timeout
ja-JP: タイムアウト
# type-param field type(most mapping the html input type)
type: number
# when type is number, range is required
@@ -79,7 +74,6 @@ params:
name:
zh-CN: 用户名
en-US: Username
ja-JP: ユーザー名
type: text
limit: 50
required: false
@@ -88,7 +82,6 @@ params:
name:
zh-CN: 密码
en-US: Password
ja-JP: パスワード
type: password
required: false
@@ -102,7 +95,6 @@ metrics:
i18n:
zh-CN: 服务器信息
en-US: Server
ja-JP: サーバー情報
fields:
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: kvrocks_version
@@ -110,121 +102,101 @@ metrics:
i18n:
zh-CN: Kvrocks 服务版本
en-US: Kvrocks Version
ja-JP: Kvrocks バージョン
- field: redis_version
type: 1
i18n:
zh-CN: Redis 服务版本
en-US: Redis Version
ja-JP: Redis バージョン
- field: git_sha1
type: 0
i18n:
zh-CN: Kvrocks Git SHA1
en-US: Kvrocks Git SHA1
ja-JP: Kvrocks Git SHA1
- field: kvrocks_mode
type: 1
i18n:
zh-CN: 运行模式
en-US: Server Mode
ja-JP: サーバーモード
- field: os
type: 1
i18n:
zh-CN: 操作系统
en-US: Operating System
ja-JP: オーエス
- field: arch_bits
type: 0
i18n:
zh-CN: 架构
en-US: Architecture Bits
ja-JP: アーキテクチャ
- field: multiplexing_api
type: 1
i18n:
zh-CN: IO多路复用器API
en-US: Multiplexing API
ja-JP: IO多重化API
- field: atomicvar_api
type: 1
i18n:
zh-CN: 原子操作处理API
en-US: Atomicvar API
ja-JP: 原子操作API
- field: gcc_version
type: 1
i18n:
zh-CN: GCC版本
en-US: GCC Version
ja-JP: GCC バージョン
- field: process_id
type: 0
i18n:
zh-CN: 进程ID
en-US: PID
ja-JP: プロセスID
- field: tcp_port
type: 0
i18n:
zh-CN: TCP/IP监听端口
en-US: TCP Port
ja-JP: TCP ポート
- field: server_time_usec
type: 0
i18n:
zh-CN: 服务器时间戳
en-US: Server Time Usec
ja-JP: サーバー時間
- field: uptime_in_seconds
type: 0
i18n:
zh-CN: 运行时长(秒)
en-US: Uptime(Seconds)
ja-JP: アップタイム(秒)
- field: uptime_in_days
type: 0
i18n:
zh-CN: 运行时长(天)
en-US: Uptime(Days)
ja-JP: アップタイム(日)
- field: hz
type: 0
i18n:
zh-CN: 事件循环频率
en-US: hz
ja-JP: hz
- field: configured_hz
type: 0
i18n:
zh-CN: 配置的事件循环频率
en-US: Configured hz
ja-JP: Configured hz
- field: lru_clock
type: 0
i18n:
zh-CN: LRU时钟
en-US: LRU Clock
ja-JP: LRUクロック
- field: executable
type: 1
i18n:
zh-CN: 服务器执行路径
en-US: Server's Executable Path
ja-JP: サーバーの実行パス
- field: config_file
type: 1
i18n:
zh-CN: 配置文件路径
en-US: Config File Path
ja-JP: 配置ファイルのパス
- field: io_threads_active
type: 0
i18n:
zh-CN: 活跃IO线程数
en-US: Active IO Threads
ja-JP: 活動中のI/Oスレッド数
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -247,7 +219,6 @@ metrics:
i18n:
zh-CN: 客户端信息
en-US: Clients
ja-JP: クライアント情報
# collect metrics content
fields:
- field: connected_clients
@@ -255,25 +226,21 @@ metrics:
i18n:
zh-CN: 已连接客户端数量
en-US: Connected Clients
ja-JP: 接続クライアント数
- field: maxclients
type: 0
i18n:
zh-CN: 最大客户端连接数
en-US: Max Clients
ja-JP: 最大クライアント数
- field: blocked_clients
type: 0
i18n:
zh-CN: 阻塞客户端数量
en-US: Blocked Clients
ja-JP: ブロックされたクライアント数
- field: monitor_clients
type: 0
i18n:
zh-CN: 监控的客户端数量
en-US: monitor Clients
ja-JP: モニタークライアント数
protocol: redis
redis:
host: ^_^host^_^
@@ -289,7 +256,6 @@ metrics:
i18n:
zh-CN: 内存信息
en-US: Memory
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
@@ -298,33 +264,28 @@ metrics:
i18n:
zh-CN: 已使用内存(字节)
en-US: Used Memory RSS
ja-JP: 使用した物理メモリ(バイト)
- field: used_memory_rss_human
type: 0
unit: MB
i18n:
zh-CN: 已使用物理内存
en-US: Used Memory RSS Human
ja-JP: 使用した物理メモリ
- field: used_memory_lua
type: 0
i18n:
zh-CN: LUA脚本占用的内存(字节)
en-US: Used Memory LUA
ja-JP: LUAが使用するメモリ(バイト)
- field: used_memory_lua_human
type: 0
unit: KB
i18n:
zh-CN: LUA脚本占用的内存
en-US: Used Memory LUA Human
ja-JP: LUAが使用するメモリ
- field: used_memory_startup
type: 0
i18n:
zh-CN: 启动占用内存
en-US: Used Memory Startup
ja-JP: 起動時の使用メモリ
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -348,7 +309,6 @@ metrics:
i18n:
zh-CN: 持久化信息
en-US: Persistence
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
@@ -357,31 +317,26 @@ metrics:
i18n:
zh-CN: 是否正在加载持久化文件
en-US: Loading
ja-JP: 読み込み中
- field: bgsave_in_progress
type: 0
i18n:
zh-CN: 是否正在进行bgsave
en-US: bgsave In Progress
ja-JP: bgsaveである
- field: last_bgsave_time
type: 0
i18n:
zh-CN: 最近一次bgsave命令执行时间
en-US: Last Save Time
ja-JP: 最後のbgsave実行時間
- field: last_bgsave_status
type: 1
i18n:
zh-CN: 最近一次bgsave命令执行状态
en-US: Last bgsave Status
ja-JP: 最後のbgsaveの実行状況
- field: last_bgsave_time_sec
type: 0
i18n:
zh-CN: 最近一次bgsave命令执行时间(秒)
en-US: Last bgsave Time Sec
ja-JP: 最後のbgsave実行時間(秒)
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -405,7 +360,6 @@ metrics:
i18n:
zh-CN: 全局统计信息
en-US: Stats
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
@@ -414,73 +368,61 @@ metrics:
i18n:
zh-CN: 已接受的总连接数
en-US: Total Connections Received
ja-JP: 受信された接続数
- field: total_commands_processed
type: 0
i18n:
zh-CN: 执行过的命令总数
en-US: Total Commands Processed
ja-JP: 処理済みのコマンド数
- field: instantaneous_ops_per_sec
type: 0
i18n:
zh-CN: 命令处理条数/秒
en-US: Instantaneous Ops Per Sec
ja-JP: 処理されたコマンド数/秒
- field: total_net_input_bytes
type: 0
i18n:
zh-CN: 输入总网络流量(字节)
en-US: Total Net Input Bytes
ja-JP: 受信されたネットワークトラフィック(バイト)
- field: total_net_output_bytes
type: 0
i18n:
zh-CN: 输出总网络流量(字节)
en-US: Total Net Output Bytes
ja-JP: 転送されたネットワークトラフィック(バイト)
- field: instantaneous_input_kbps
type: 0
i18n:
zh-CN: 输入字节数/秒
en-US: Instantaneous Input Kbps
ja-JP: 受信されたバイト/秒
- field: instantaneous_output_kbps
type: 0
i18n:
zh-CN: 输出字节数/秒
en-US: Instantaneous Output Kbps
ja-JP: 転送されたバイト/秒
- field: sync_full
type: 0
i18n:
zh-CN: 主从完全同步成功次数
en-US: Sync Full
ja-JP: Full Sync回数
- field: sync_partial_ok
type: 0
i18n:
zh-CN: 主从部分同步成功次数
en-US: Sync Partial OK
ja-JP: Partial Sync成功回数
- field: sync_partial_err
type: 0
i18n:
zh-CN: 主从部分同步失败次数
en-US: Sync Partial Error
ja-JP: Partial Sync失敗回数
- field: pubsub_channels
type: 0
i18n:
zh-CN: 订阅的频道数量
en-US: Pubsub Channels
ja-JP: 購読されたチャンネル数
- field: pubsub_patterns
type: 0
i18n:
zh-CN: 订阅的模式数量
en-US: Pubsub Patterns
ja-JP: 購読されたパターン数
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -504,7 +446,6 @@ metrics:
i18n:
zh-CN: 主从同步信息
en-US: Replication
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
@@ -513,19 +454,16 @@ metrics:
i18n:
zh-CN: 节点角色
en-US: Role
ja-JP: 役割
- field: connected_slaves
type: 0
i18n:
zh-CN: 已连接的从节点个数
en-US: Connected Slaves
ja-JP: 接続スレーブ数
- field: master_repl_offset
type: 0
i18n:
zh-CN: 主节点偏移量
en-US: Master Repl Offset
ja-JP: マスターのログオフセット
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -549,7 +487,6 @@ metrics:
i18n:
zh-CN: CPU消耗信息
en-US: CPU
ja-JP: CPU情報
# 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
@@ -558,13 +495,11 @@ metrics:
i18n:
zh-CN: Kvrocks进程使用的CPU时钟总和(内核态)
en-US: Used CPU Sys
ja-JP: Kvrocksが使用するシステム時間
- field: used_cpu_user
type: 0
i18n:
zh-CN: Kvrocks进程使用的CPU时钟总和(用户态)
en-US: Used CPU User
ja-JP: Kvrocksが使用するユーザー時間
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -588,7 +523,6 @@ metrics:
i18n:
zh-CN: 命令信息
en-US: Command Stats
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
@@ -597,13 +531,11 @@ metrics:
i18n:
zh-CN: 命令
en-US: Command Stat Command
ja-JP: コマンド
- field: cmdstat_info
type: 1
i18n:
zh-CN: 命令监控信息
en-US: Command Stat Info
ja-JP: コマンドの統計情報
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -626,7 +558,6 @@ metrics:
i18n:
zh-CN: 集群信息
en-US: Cluster
ja-JP: クラスター情報
fields:
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: cluster_enabled
@@ -634,7 +565,6 @@ metrics:
i18n:
zh-CN: 节点是否开启集群模式
en-US: Cluster Enabled
ja-JP: 有効
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -658,7 +588,6 @@ metrics:
i18n:
zh-CN: 命令统计信息
en-US: Command Stats
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
@@ -667,55 +596,46 @@ metrics:
i18n:
zh-CN: 客户端命令统计
en-US: cmdstat client
ja-JP: クライエントのコマンド
- field: cmdstat_config
type: 1
i18n:
zh-CN: 配置命令统计
en-US: cmdstat config
ja-JP: 配置のコマンド
- field: cmdstat_get
type: 1
i18n:
zh-CN: get
en-US: get
ja-JP: get
- field: cmdstat_hello
type: 1
i18n:
zh-CN: hello
en-US: hello
ja-JP: hello
- field: cmdstat_info
type: 1
i18n:
zh-CN: info
en-US: info
ja-JP: info
- field: cmdstat_keys
type: 1
i18n:
zh-CN: keys
en-US: keys
ja-JP: keys
- field: cmdstat_ping
type: 1
i18n:
zh-CN: ping
en-US: ping
ja-JP: ping
- field: cmdstat_select
type: 1
i18n:
zh-CN: select
en-US: select
ja-JP: select
- field: cmdstat_set
type: 1
i18n:
zh-CN: set
en-US: set
ja-JP: set
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -739,7 +659,6 @@ metrics:
i18n:
zh-CN: 数据库统计信息
en-US: Keyspace
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
@@ -748,49 +667,41 @@ metrics:
i18n:
zh-CN: db0
en-US: db0
ja-JP: db0
- field: sequence
type: 1
i18n:
zh-CN: 序列
en-US: sequence
ja-JP: シーケンス
- field: used_db_size
type: 1
i18n:
zh-CN: 数据库使用大小
en-US: used_db_size
ja-JP: 使用したサイズ
- field: max_db_size
type: 1
i18n:
zh-CN: 数据库最大使用大小
en-US: max_db_size
ja-JP: 最大サイズ
- field: used_percent
type: 1
i18n:
zh-CN: 数据库使用百分比
en-US: used_percent
ja-JP: パーセント
- field: disk_capacity
type: 1
i18n:
zh-CN: 磁盘容量
en-US: disk_capacity
ja-JP: ディスク容量
- field: used_disk_size
type: 1
i18n:
zh-CN: 占用磁盘大小
en-US: used_disk_size
ja-JP: 使用したディスクサイズ
- field: used_disk_percent
type: 1
i18n:
zh-CN: 占用磁盘百分比
en-US: used_disk_percent
ja-JP: 使用したディスク率
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: redis
# the config content when protocol is redis
@@ -21,13 +21,11 @@ app: linux
name:
zh-CN: Linux操作系统
en-US: OS Linux
ja-JP: OS Linux
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 使用 <a class='help_module_content' href='https://hertzbeat.apache.org/docs/advanced/extend-ssh'> SSH 协议</a> 对 Linux 操作系统的通用性能指标 (系统信息、CPU、内存、磁盘、网卡、文件系统、TOP资源进程等) 进行采集监控。<br>您可以点击“<i>新建 Linux</i>”并配置HOST端口账户等相关参数进行添加,支持SSH账户密码或密钥认证。或者选择“<i>更多操作</i>”,导入已有配置。
en-US: HertzBeat uses <a class='help_module_content' href='https://hertzbeat.apache.org/docs/advanced/extend-ssh'> SSH protocol</a> to monitors Linux operating system's general performance metrics such as cpu, memory, disk, basic, interface, disk_free, top_process etc. <br>You can click the "<i>New Linux</i>" and config host port and other related params to add, auth support password or secretKey. Or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat 使用 <a class='help_module_content' href='https://hertzbeat.apache.org/docs/advanced/extend-ssh'> SSH 协议</a> 對 Linux 操作系统的通用性能指標 (系統信息、CPU、內存、磁盤、網卡、文件系統、TOP資源進程等) 進行採集監控。<br>您可以點擊“<i>新建 Linux</i>”並配置HOST端口賬戶等相關參數進行添加,支持SSH賬戶密碼或密鑰認證。或者選擇“<i>更多操作</i>”,導入已有配寘。
ja-JP: Hertzbeat は <a class='help_module_content' href='https://hertzbeat.apache.org/docs/advanced/extend-ssh'> SSHプロトコルを介して</a> Linuxシステムの一般的なパフォーマンスのメトリクスを監視します。<br>「<i>新規 Linux</i>」をクリックしてホストなどのパラメタを設定した後、新規することができます。SSHまたはキー認証をサポートします。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/linux
en-US: https://hertzbeat.apache.org/docs/help/linux
@@ -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: 超时时间(ms)
en-US: Timeout(ms)
ja-JP: タイムアウト(ms)
# type-param field type(most mapping the html input type)
type: number
# when type is number, range is required
@@ -80,7 +75,6 @@ params:
name:
zh-CN: 复用连接
en-US: Reuse Connection
ja-JP: 接続再利用
# type-param field type(most mapping the html input type)
type: boolean
# required-true or false
@@ -92,7 +86,6 @@ params:
name:
zh-CN: 使用代理
en-US: Use Proxy Connection
ja-JP: プロキシ接続利用
# type-param field type(most mapping the html input type)
type: boolean
# required-true or false
@@ -104,7 +97,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
@@ -117,7 +109,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
@@ -128,7 +119,6 @@ params:
name:
zh-CN: 私钥
en-US: PrivateKey
ja-JP: 秘密鍵
# type-param field type(most mapping the html input type)
type: textarea
placeholder: -----BEGIN RSA PRIVATE KEY-----
@@ -141,7 +131,6 @@ params:
name:
zh-CN: 密钥短语
en-US: PrivateKey PassPhrase
ja-JP: 秘密鍵フレーズ
# type-param field type(most mapping the html input type)
type: password
# required-true or false
@@ -154,7 +143,6 @@ params:
name:
zh-CN: 代理主机
en-US: Proxy Host
ja-JP: プロキシホスト
# type-param field type(most mapping the html input type)
type: text
# required-true or false
@@ -166,7 +154,6 @@ params:
name:
zh-CN: 代理端口
en-US: Proxy Port
ja-JP: プロキシポート
# type-param field type(most mapping the html input type)
type: number
# when type is number, range is required
@@ -183,7 +170,6 @@ params:
name:
zh-CN: 代理用户名
en-US: Proxy 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
@@ -198,7 +184,6 @@ params:
name:
zh-CN: 代理密码
en-US: Proxy Password
ja-JP: プロキシパスワード
# type-param field type(most mapping the html input tag)
type: password
# required-true or false
@@ -211,7 +196,6 @@ params:
name:
zh-CN: 代理主机私钥
en-US: proxyPrivateKey
ja-JP: プロキシ秘密鍵
# type-param field type(most mapping the html input type)
type: textarea
placeholder: -----BEGIN RSA PRIVATE KEY-----
@@ -226,7 +210,6 @@ metrics:
i18n:
zh-CN: 系统基本信息
en-US: Basic 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
@@ -239,19 +222,16 @@ metrics:
i18n:
zh-CN: 主机名称
en-US: Host Name
ja-JP: ホスト名
- field: version
type: 1
i18n:
zh-CN: 操作系统版本
en-US: System Version
ja-JP: オーエスバージョン
- field: uptime
type: 1
i18n:
zh-CN: 启动时间
en-US: Uptime
ja-JP: アップタイム
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# the config content when protocol is ssh
@@ -291,7 +271,6 @@ metrics:
i18n:
zh-CN: CPU 信息
en-US: CPU Info
ja-JP: CPU情報
priority: 1
fields:
- field: info
@@ -299,38 +278,32 @@ metrics:
i18n:
zh-CN: 型号
en-US: Info
ja-JP: バージョン
- field: cores
type: 1
i18n:
zh-CN: 核数
en-US: Cores
ja-JP: コア数
- field: interrupt
type: 0
i18n:
zh-CN: 中断数
en-US: Interrupt
ja-JP: 割り込み数
- field: load
type: 1
i18n:
zh-CN: 负载
en-US: Load
ja-JP: ロード
- field: context_switch
type: 0
i18n:
zh-CN: 上下文切换
en-US: Context Switch
ja-JP: コンテキストスイッチ
- field: usage
type: 0
unit: '%'
i18n:
zh-CN: 使用率
en-US: Usage
ja-JP: 使用率
# (optional)metrics field alias name, it is used as an alias field to map and convert the collected data and metrics field
aliasFields:
- info
@@ -377,7 +350,6 @@ metrics:
i18n:
zh-CN: 内存信息
en-US: Memory Info
ja-JP: メモリ情報
priority: 2
fields:
- field: total
@@ -386,42 +358,36 @@ metrics:
i18n:
zh-CN: 总内存容量
en-US: Total Memory
ja-JP: メモリ容量
- field: used
type: 0
unit: Mb
i18n:
zh-CN: 用户程序内存量
en-US: User Program Memory
ja-JP: ユーザープログラムメモリ
- field: free
type: 0
unit: Mb
i18n:
zh-CN: 空闲内存容量
en-US: Free Memory
ja-JP: 空きメモリ
- field: buff_cache
type: 0
unit: Mb
i18n:
zh-CN: 缓存占用内存
en-US: Buff Cache Memory
ja-JP: バッファメモリ
- field: available
type: 0
unit: Mb
i18n:
zh-CN: 剩余可用内存
en-US: Available Memory
ja-JP: 使用可能のメモリ
- field: usage
type: 0
unit: '%'
i18n:
zh-CN: 内存使用率
en-US: Memory Usage
ja-JP: メモリ使用率
aliasFields:
- total
- used
@@ -464,7 +430,6 @@ metrics:
i18n:
zh-CN: 磁盘信息
en-US: Disk Info
ja-JP: ディスク情報
priority: 3
fields:
- field: disk_num
@@ -472,32 +437,27 @@ metrics:
i18n:
zh-CN: 磁盘总数
en-US: Disk Num
ja-JP: ディスク番号
- field: partition_num
type: 1
i18n:
zh-CN: 分区总数
en-US: Partition Num
ja-JP: パーティション
- field: block_write
type: 0
i18n:
zh-CN: 写磁盘块数
en-US: Block Write
ja-JP: 書き込みディスクブロック数
- field: block_read
type: 0
i18n:
zh-CN: 读磁盘块数
en-US: Block Read
ja-JP: 読み取りブロック数
- field: write_rate
type: 0
unit: iops
i18n:
zh-CN: 磁盘写速率
en-US: Write Rate
ja-JP: ディスク書き込み速度
protocol: ssh
ssh:
host: ^_^host^_^
@@ -527,7 +487,6 @@ metrics:
i18n:
zh-CN: 网卡信息
en-US: Interface Info
ja-JP: ネットワークカード情報
priority: 4
fields:
- field: interface_name
@@ -536,21 +495,18 @@ metrics:
i18n:
zh-CN: 网卡名称
en-US: Interface Name
ja-JP: ネットワークカード名
- field: receive_bytes
type: 0
unit: Mb
i18n:
zh-CN: 入站数据流量
en-US: Receive Bytes
ja-JP: 受信されたバイト数
- field: transmit_bytes
type: 0
unit: Mb
i18n:
zh-CN: 出站数据流量
en-US: Transmit Bytes
ja-JP: 転送されたバイト数
units:
- receive_bytes=B->MB
- transmit_bytes=B->MB
@@ -583,7 +539,6 @@ metrics:
i18n:
zh-CN: 文件系统
en-US: Disk Free
ja-JP: ファイルシステム
priority: 5
fields:
- field: filesystem
@@ -591,35 +546,30 @@ metrics:
i18n:
zh-CN: 文件系统
en-US: Filesystem
ja-JP: ファイルシステム
- field: used
type: 0
unit: Mb
i18n:
zh-CN: 已使用量
en-US: Used
ja-JP: 使用済み
- field: available
type: 0
unit: Mb
i18n:
zh-CN: 可用量
en-US: Available
ja-JP: 使用可能
- field: usage
type: 0
unit: '%'
i18n:
zh-CN: 使用率
en-US: Usage
ja-JP: 使用率
- field: mounted
type: 1
label: true
i18n:
zh-CN: 挂载点
en-US: Mounted
ja-JP: マウント
protocol: ssh
ssh:
host: ^_^host^_^
@@ -649,7 +599,6 @@ metrics:
i18n:
zh-CN: Top10 CPU 进程
en-US: Top10 CPU Process
ja-JP: トップ10 CPUプロセス
priority: 6
fields:
- field: pid
@@ -658,27 +607,23 @@ metrics:
i18n:
zh-CN: 进程ID
en-US: PID
ja-JP: プロセスID
- field: cpu_usage
type: 0
unit: '%'
i18n:
zh-CN: CPU占用率
en-US: CPU Usage
ja-JP: CPU使用率
- field: mem_usage
type: 0
unit: '%'
i18n:
zh-CN: 内存占用率
en-US: Memory Usage
ja-JP: メモリ使用率
- field: command
type: 1
i18n:
zh-CN: 执行命令
en-US: Command
ja-JP: コマンド
protocol: ssh
ssh:
host: ^_^host^_^
@@ -708,7 +653,6 @@ metrics:
i18n:
zh-CN: Top10 内存进程
en-US: Top10 Memory Process
ja-JP: トップ10 メモリプロセス
priority: 7
fields:
- field: pid
@@ -717,27 +661,23 @@ metrics:
i18n:
zh-CN: 进程ID
en-US: PID
ja-JP: プロセスID
- field: mem_usage
type: 0
unit: '%'
i18n:
zh-CN: 内存占用率
en-US: Memory Usage
ja-JP: メモリ使用率
- field: cpu_usage
type: 0
unit: '%'
i18n:
zh-CN: CPU占用率
en-US: CPU Usage
ja-JP: CPU使用率
- field: command
type: 1
i18n:
zh-CN: 执行命令
en-US: Command
ja-JP: コマンド
protocol: ssh
ssh:
host: ^_^host^_^
@@ -13,12 +13,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# The monitoring type categoryservice-application service monitoring db-database monitoring mid-middleware custom-custom monitoring os-operating system monitoring
category: service
# The monitoring type eg: linux windows tomcat mysql aws...
app: mqtt
# The app api i18n name
name:
zh-CN: MQTT 连接
en-US: MQTT Connection
# The description and help of this monitoring type
help:
zh-CN: HertzBeat 对 MQTT 连接进行监测。<br>您可以点击 “<i>新建 MQTT 连接</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: HertzBeat monitors MQTT connections. <br>You can click "<i>New MQTT connection</i>" and configure it, or select "<i>More actions</i>" to import an existing configuration.
@@ -26,121 +29,83 @@ help:
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/mqtt
en-US: https://hertzbeat.apache.org/docs/help/mqtt
# Input params define for monitoring(render web ui by the definition)
params:
# field-param field key
- field: host
# name-param field display i18n name
name:
zh-CN: MQTT的Host
en-US: Target Host
# type-param field type(most mapping the html input type)
type: host
# required-true or false
required: true
# field-param field key
- field: port
# name-param field display i18n name
name:
zh-CN: 端口
en-US: Port
# type-param field type(most mapping the html input type)
type: number
# when type is number, range is required
range: '[0,65535]'
# required-true or false
required: true
# default value 1883
defaultValue: 1883
- field: protocolVersion
name:
zh-CN: 协议版本
en-US: Protocol version
type: radio
options:
- label: MQTT 3.1.1
value: MQTT_3_1_1
- label: MQTT 5.0
value: MQTT_5_0
required: true
defaultValue: MQTT_3_1_1
# field-param field key
- field: timeout
# name-param field display i18n name
name:
zh-CN: 连接超时时间(ms)
en-US: Connect Timeout(ms)
# type-param field type(most mapping the html input type)
type: number
# when type is number, range is required
range: '[0,100000]'
# required-true or false
required: true
# default value 6000
defaultValue: 6000
# field-param field key
- field: username
name:
zh-CN: 用户名
en-US: Username
type: text
hide: true
# required-true or false
required: false
- field: password
name:
zh-CN: 密码
en-US: Password
type: text
hide: true
# required-true or false
required: false
- field: clientId
name:
zh-CN: 客户端ID
en-US: Client Id
type: text
defaultValue: hertzbeat-mqtt-client
# required-true or false
required: true
- field: username
name:
zh-CN: 用户名
en-US: Username
type: text
required: false
- field: password
name:
zh-CN: 密码
en-US: Password
type: password
required: false
- field: host
name:
zh-CN: MQTT的Host
en-US: Target Host
type: host
required: true
- field: port
name:
zh-CN: 端口
en-US: Port
type: number
range: '[0,65535]'
required: true
defaultValue: 1883
- field: protocol
name:
zh-CN: 连接协议
en-US: Protocol
type: radio
options:
- label: MQTT
value: MQTT
- label: MQTTS
value: MQTTS
required: true
defaultValue: MQTT
- field: timeout
name:
zh-CN: 连接超时时间(ms)
en-US: Connect Timeout(ms)
type: number
range: '[0,100000]'
required: true
defaultValue: 10000
- field: keepalive
name:
zh-CN: 心跳检测时间(s)
en-US: Keep Alive(s)
type: number
range: '[0,100000]'
required: true
defaultValue: 30
- field: tlsVersion
name:
zh-CN: TLS版本
en-US: TLS Version
type: radio
options:
- label: TLSv1.2
value: TLSv1.2
- label: TLSv1.3
value: TLSv1.3
defaultValue: TLSv1.2
required: false
hide: true
- field: insecureSkipVerify
name:
zh-CN: 跳过证书验证
en-US: Skip Certificate Verification
type: boolean
defaultValue: false
hide: true
- field: caCert
name:
zh-CN: CA证书
en-US: CA Certificate
type: text
required: false
hide: true
- field: enableMutualAuth
name:
zh-CN: 双向认证
en-US: Enable Mutual Auth
type: boolean
defaultValue: false
hide: true
- field: clientCert
name:
zh-CN: 客户端证书
en-US: Client Certificate
type: text
required: false
hide: true
- field: clientKey
name:
zh-CN: 客户端私钥
en-US: Client Private Key
type: text
required: false
hide: true
- field: topic
name:
@@ -154,12 +119,17 @@ params:
en-US: Test message
type: text
required: false
# collect metrics config list
metrics:
# metrics - summary
- name: summary
i18n:
zh-CN: 概要
en-US: Summary
# 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
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
fields:
- field: responseTime
type: 0
@@ -167,41 +137,37 @@ metrics:
i18n:
zh-CN: 响应时间
en-US: Response Time
- field: canSubscribe
- field: canDescribe
type: 1
i18n:
zh-CN: 订阅状态
en-US: Normal subscribe
zh-CN: 正常订阅
en-US: Normal subscription
- field: canPublish
type: 1
i18n:
zh-CN: 发布状态
zh-CN: 正常推送
en-US: Normal publish
- field: canReceive
type: 1
i18n:
zh-CN: 接收数据
en-US: Receive data
- field: canUnSubscribe
type: 1
i18n:
zh-CN: 取消订阅状态
en-US: Normal unsubscribe
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: mqtt
# Specific collection configuration when protocol is telnet protocol
mqtt:
clientId: ^_^clientId^_^
username: ^_^username^_^
password: ^_^password^_^
# telnet host
host: ^_^host^_^
# port
port: ^_^port^_^
protocol: ^_^protocol^_^
# timeout
timeout: ^_^timeout^_^
keepalive: ^_^keepalive^_^
tlsVersion: ^_^tlsVersion^_^
insecureSkipVerify: ^_^insecureSkipVerify^_^
caCert: ^_^caCert^_^
enableMutualAuth: ^_^enableMutualAuth^_^
clientCert: ^_^clientCert^_^
clientKey: ^_^clientKey^_^
# email
topic: ^_^topic^_^
# clientId
clientId: ^_^clientId^_^
# protocolVersion
protocolVersion: ^_^protocolVersion^_^
# username
username: ^_^username^_^
# password
password: ^_^password^_^
# testMessage
testMessage: ^_^testMessage^_^
@@ -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();
}
}
@@ -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));
}
}
@@ -182,12 +182,8 @@ public class JpaDatabaseDataStorage extends AbstractHistoryDataStorage {
.str(formatStrValue(columnValue));
case CommonConstants.TYPE_TIME -> historyBuilder.metricType(CommonConstants.TYPE_TIME)
.int32(Integer.parseInt(columnValue));
default -> {
Double v = Double.parseDouble(columnValue);
v = v.isNaN() ? null : v;
historyBuilder.metricType(CommonConstants.TYPE_NUMBER)
.dou(v);
}
default -> historyBuilder.metricType(CommonConstants.TYPE_NUMBER)
.dou(Double.parseDouble(columnValue));
}
if (cell.getMetadataAsBoolean(MetricDataConstants.LABEL)) {
@@ -100,10 +100,10 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
private final VictoriaMetricsProperties victoriaMetricsProp;
private final RestTemplate restTemplate;
private final BlockingQueue<VictoriaMetricsDataStorage.VictoriaMetricsContent> metricsBufferQueue;
private boolean isBatchImportEnabled = false;
private HashedWheelTimer metricsFlushTimer = null;
private MetricsFlushTask metricsFlushtask = null;
private final VictoriaMetricsProperties.InsertConfig insertConfig;
public VictoriaMetricsDataStorage(VictoriaMetricsProperties victoriaMetricsProperties, RestTemplate restTemplate) {
if (victoriaMetricsProperties == null) {
@@ -114,9 +114,11 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
victoriaMetricsProp = victoriaMetricsProperties;
serverAvailable = checkVictoriaMetricsDatasourceAvailable();
serverAvailable = checkVictoriaMetricsDatasourceAvailable();
insertConfig = victoriaMetricsProperties.insert() == null ? new VictoriaMetricsProperties.InsertConfig(100, 3) : victoriaMetricsProperties.insert();
metricsBufferQueue = new LinkedBlockingQueue<>(insertConfig.bufferSize());
initializeFlushTimer();
metricsBufferQueue = new LinkedBlockingQueue<>(victoriaMetricsProperties.insert().bufferSize());
isBatchImportEnabled = victoriaMetricsProperties.insert().flushInterval() != 0 && victoriaMetricsProperties.insert().bufferSize() != 0;
if (isBatchImportEnabled){
initializeFlushTimer();
}
}
private void initializeFlushTimer() {
@@ -242,6 +244,10 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
log.info("[warehouse victoria-metrics] flush metrics data {} is empty, ignore.", metricsData.getId());
return;
}
if (!isBatchImportEnabled){
doSaveData(contentList);
return;
}
sendVictoriaMetrics(contentList);
}
@@ -579,10 +585,10 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
log.error("[Victoria Metrics] Failed to save metrics directly: {}", e.getMessage(), e);
}
}
}
// Refresh in advance to avoid waiting
if (metricsBufferQueue.size() >= insertConfig.bufferSize() * 0.8) {
triggerImmediateFlush();
// Refresh in advance to avoid waiting
if (metricsBufferQueue.size() >= victoriaMetricsProp.insert().bufferSize() * 0.8) {
triggerImmediateFlush();
}
}
}
@@ -597,14 +603,14 @@ public class VictoriaMetricsDataStorage extends AbstractHistoryDataStorage {
@Override
public void run(Timeout timeout) {
try {
List<VictoriaMetricsDataStorage.VictoriaMetricsContent> batch = new ArrayList<>(insertConfig.bufferSize());
metricsBufferQueue.drainTo(batch, insertConfig.bufferSize());
List<VictoriaMetricsDataStorage.VictoriaMetricsContent> batch = new ArrayList<>(victoriaMetricsProp.insert().bufferSize());
metricsBufferQueue.drainTo(batch, victoriaMetricsProp.insert().bufferSize());
if (!batch.isEmpty()) {
doSaveData(batch);
log.debug("[Victoria Metrics] Flushed {} metrics items", batch.size());
}
if (metricsFlushTimer != null && !metricsFlushTimer.isStop()) {
metricsFlushTimer.newTimeout(this, insertConfig.flushInterval(), TimeUnit.SECONDS);
metricsFlushTimer.newTimeout(this, victoriaMetricsProp.insert().flushInterval(), TimeUnit.SECONDS);
}
} catch (Exception e) {
log.error("[VictoriaMetrics] flush task error: {}", e.getMessage(), e);
@@ -34,7 +34,7 @@ public record VictoriaMetricsProperties(@DefaultValue("false") boolean enabled,
String password,
InsertConfig insert) {
record InsertConfig(@DefaultValue("100") int bufferSize,
record InsertConfig(@DefaultValue("1000") int bufferSize,
@DefaultValue("3") int flushInterval) {
}
+1 -1
View File
@@ -9,7 +9,7 @@ tags: [opensource]
[HertzBeat](https://github.com/apache/hertzbeat), incubated by [Dromara](https://dromara.org) and open-sourced by [TanCloud](https://tancloud.cn), is an open-source monitoring and alerting project that supports various monitoring types such as websites, APIs, PING, ports, databases, entire sites, operating systems, middleware, etc. It features threshold alarms, notification alerts (email, webhook, DingTalk, WeChat Work, Lark robots), and a user-friendly visual interface.
**Official Website: [hertzbeat.com](https://hertzbeat.apache.org) | [tancloud.cn](https://tancloud.cn)**
**Official Website: [hertzbeat.com](https://hertzbeat.com) | [tancloud.cn](https://tancloud.cn)**
Hello everyone, HertzBeat v1.1.0 is released! In this version, we've added support for the SNMP protocol and implemented application monitoring for Windows operating systems using SNMP.
Another significant change is our default switch to using the H2 database instead of MYSQL for storage, making it easier for users to install and deploy. Now, you can install and experience HertzBeat with just a single Docker command: `docker run -d -p 1157:1157 --name hertzbeat apache/hertzbeat`
+1 -1
View File
@@ -9,7 +9,7 @@ tags: [opensource]
[HertzBeat](https://github.com/apache/hertzbeat), incubated by [Dromara](https://dromara.org) and open-sourced by [TanCloud](https://tancloud.cn), is an open-source monitoring and alerting project that supports website, API, PING, port, database, site-wide, operating system, middleware monitoring types, and more. It features threshold alarms, alarm notifications (email, webhook, DingTalk, WeChat Work, Feishu bot), and a user-friendly visual interface.
**Official Website: [hertzbeat.com](https://hertzbeat.apache.org) | [tancloud.cn](https://tancloud.cn)**
**Official Website: [hertzbeat.com](https://hertzbeat.com) | [tancloud.cn](https://tancloud.cn)**
Hello everyone, HertzBeat v1.1.0 is here! In this version, we've added support for the SNMP protocol and enabled application monitoring for Windows operating systems using SNMP.
Another major change is that we've switched from using MYSQL to H2 database by default for storage, making it easier for users to install and deploy. Now, you can get started with HertzBeat using just a single docker command: `docker run -d -p 1157:1157 --name hertzbeat apache/hertzbeat`
+2 -2
View File
@@ -9,7 +9,7 @@ tags: [opensource]
> Friendly Cloud Monitoring Tool.
**Home: [hertzbeat.com](https://hertzbeat.apache.org)**
**Home: [hertzbeat.com](https://hertzbeat.com)**
Hi guys! HertzBeat v1.1.1 is coming. This version brings custom monitoring enhancements, and the collected metric data can be assigned as a variable to the next collection. Fixed several bugs and improved the overall stable usability.
@@ -49,7 +49,7 @@ Have Fun!
> [HertzBeat](https://github.com/apache/hertzbeat) is an opensource monitoring and alarm project incubated by [Dromara](https://dromara.org) and open sourced by [TanCloud](https://tancloud.cn), which supports Website, API, PING, Port, Database, OS Monitor etc.
> We also provide **[Monitoring Cloud For Saas](https://console.tancloud.cn)**, people no longer need to deploy a cumbersome monitoring tool in order to monitor their website resources. **[Sign in to get started for free](https://console.tancloud.cn)**.
> HertzBeat supports more liberal threshold alarm configuration (calculation expression), supports alarm notification, alarm template, email, DingDing, WeChat FeiShu and WebHook.
> Most important is HertzBeat supports [Custom Monitoring](https://hertzbeat.apache.org/docs/advanced/extend-point), just by configuring the YML file, we can customize the monitoring types and metrics what we need.
> Most important is HertzBeat supports [Custom Monitoring](https://hertzbeat.com/docs/advanced/extend-point), just by configuring the YML file, we can customize the monitoring types and metrics what we need.
> HertzBeat is modular, `manager, collector, scheduler, warehouse, alerter` modules are decoupled for easy understanding and custom development.
> Welcome to HertzBeat's [Cloud Environment TanCloud](https://console.tancloud.cn) to try and discover more.
> Welcome to join us to build hertzbeat together.
+2 -2
View File
@@ -17,7 +17,7 @@ Today's article describes how to use hertzbeat monitoring system to detect the v
HertzBeat is a real-time monitoring tool with powerful customizable monitoring capabilities without the need for an agent. Website monitoring, PING connectivity, port availability, database, OS, middleware, API monitoring, threshold alerts, alert notifications (email weChat pinning flybook).
**Official website: <https://hertzbeat.apache.org> | <https://tancloud.cn>**
**Official website: <https://hertzbeat.com> | <https://tancloud.cn>**
github: <https://github.com/apache/hertzbeat>
gitee: <https://gitee.com/hertzbeat/hertzbeat>
@@ -87,7 +87,7 @@ gitee: <https://gitee.com/hertzbeat/hertzbeat>
You can refer to the help file for the token configuration of Nail WeChat Flying Book, etc.
<https://hertzbeat.apache.org/docs/help/alert_dingtalk>
<https://hertzbeat.com/docs/help/alert_dingtalk>
<https://tancloud.cn/docs/help/alert_dingtalk>
> Alert Notification -> Add new alert notification policy -> Enable notification for the recipients you just configured
+1 -1
View File
@@ -98,7 +98,7 @@ github[Ceilzcx (zcx) (github.com)](https://github.com/Ceilzcx)
### 如何参与Hertzbeat
+ 官网有非常完善的贡献者指南:[贡献者指南 | HertzBeat](https://hertzbeat.apache.org/docs/community/contribution)
+ 官网有非常完善的贡献者指南:[贡献者指南 | HertzBeat](https://hertzbeat.com/docs/community/contribution)
+ Github issues[Issues · apache/hertzbeat (github.com)](https://github.com/apache/hertzbeat/issues)
+3 -3
View File
@@ -25,7 +25,7 @@ tags: [opensource, practice]
#### Prerequisites, you already have IoTDB environment and HertzBeat environment
- IoTDB [deployment and installation documentation](https://iotdb.apache.org/UserGuide/V0.13.x/QuickStart/QuickStart.html)
- HertzBeat [deployment installation documentation](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [deployment installation documentation](https://hertzbeat.com/docs/start/docker-deploy)
#### 1. Enable the `metrics` function on the IoTDB side, which will provide interface data in the form of prometheus metrics
@@ -54,7 +54,7 @@ tags: [opensource, practice]
2. Configure the parameters required for monitoring IoTDB
Fill in the IoTDB **service IP** and **monitoring port** (default 9091) on the monitoring page, and finally click OK to add.
For other parameters such as **collection interval**, **timeout period**, etc., please refer to [Help Documentation](https://hertzbeat.apache.org/docs/help/iotdb/) <https://hertzbeat.apache.org/docs/help> /iotdb/
For other parameters such as **collection interval**, **timeout period**, etc., please refer to [Help Documentation](https://hertzbeat.com/docs/help/iotdb/) <https://hertzbeat.com/docs/help> /iotdb/
![HertzBeat](/img/blog/monitor-iotdb-2.png)
@@ -96,7 +96,7 @@ tags: [opensource, practice]
Message notification methods support **email, DingTalk, WeChat Work, Feishu, WebHook, SMS**, etc. Here we take the commonly used DingTalk as an example.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [Help Documentation](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the receiver parameters in HertzBeat as follows.
【Alarm Notification】->【New Recipient】->【Select DingTalk Robot Notification Method】->【Set DingTalk Robot ACCESS_TOKEN】->【OK】
+3 -3
View File
@@ -33,7 +33,7 @@ tags: [opensource, practice]
#### You must have a ShenYu environment and a HertzBeat environment
- ShenYu [Deployment and Installation Documentation](https://shenyu.apache.org/zh/docs/deployment/deployment-before)
- HertzBeat [Deployment and Installation Documentation](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [Deployment and Installation Documentation](https://hertzbeat.com/docs/start/docker-deploy)
#### i. Enable the `metrics` plugin on the ShenYu side, which will provide the metrics interface data
@@ -77,7 +77,7 @@ tags: [opensource, practice]
2. Configure the parameters required for monitoring ShenYu
On the monitor page, fill in ShenYu **service IP**, **monitor port** (default 8090), and click OK to add.
For other parameters such as **collection interval**, **timeout**, etc., you can refer to the [help file](https://hertzbeat.apache.org/docs/help/shenyu/) <https://hertzbeat.apache.org/docs/help/shenyu/>
For other parameters such as **collection interval**, **timeout**, etc., you can refer to the [help file](https://hertzbeat.com/docs/help/shenyu/) <https://hertzbeat.com/docs/help/shenyu/>
![HertzBeat](/img/blog/monitor-shenyu-1.png)
@@ -126,7 +126,7 @@ Of course, just looking at it is not perfect, monitoring is often accompanied by
Message notification methods support **Email, Nail, WeChat, Flybook, WebHook, SMS**, etc. Here we take the commonly used Nail as an example.
- Refer to this [help document](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> Configure the bot on the pinning side, set the security customization keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [help document](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> Configure the bot on the pinning side, set the security customization keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the recipient parameters in HertzBeat as follows.
[Alert Notification] -> [Add Recipient] -> [Select Nailed Bot Notification Method] -> [Set Nailed Bot ACCESS_TOKEN] -> [OK]
+3 -3
View File
@@ -30,7 +30,7 @@ tags: [opensource, practice]
#### operation, you already have a DynamicTp environment and a HertzBeat environment
- DynamicTp [Integration Access Documentation](https://dynamictp.cn/guide/use/quick-start.html)
- HertzBeat [Deployment and Installation Documentation](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [Deployment and Installation Documentation](https://hertzbeat.com/docs/start/docker-deploy)
#### i. Expose the `DynamicTp` metrics interface `/actuator/dynamic-tp` on the DynamicTp side, which will provide the metrics interface data
@@ -89,7 +89,7 @@ tags: [opensource, practice]
2. Configure the parameters required for monitoring DynamicTp.
On the monitor page, fill in DynamicTp **service IP**, **monitoring port** (default 8080), and finally click OK to add it.
For other parameters such as **collection interval**, **timeout**, etc., you can refer to [help](https://hertzbeat.apache.org/docs/help/dynamic_tp/) <https://hertzbeat.apache.org/docs/help/dynamic_tp/>
For other parameters such as **collection interval**, **timeout**, etc., you can refer to [help](https://hertzbeat.com/docs/help/dynamic_tp/) <https://hertzbeat.com/docs/help/dynamic_tp/>
![HertzBeat](/img/blog/monitor-dynamic-tp-2.png)
@@ -138,7 +138,7 @@ Of course, just watching is not perfect, monitoring is often accompanied by alar
Message notification methods support **Email, Dingtalk, WeChat, Flybook, WebHook, SMS**, etc. We take the commonly used Dingtalk as an example.
- Refer to this [help document](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> Configure the bot on Dingtalk side, set the security customization keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [help document](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> Configure the bot on Dingtalk side, set the security customization keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the recipient parameters in HertzBeat as follows.
[Alert Notification] -> [Add Recipient] -> [Choose Dingtalk bot notification method] -> [Set Dingtalk bot ACCESS_TOKEN] -> [OK]
+3 -3
View File
@@ -27,7 +27,7 @@ Keywords: [Open source monitoring tool, open source database monitoring, Mysql d
#### The premise of the operation is that you already have the Mysql environment and the HertzBeat environment
- Mysql [Installation and deployment document](https://www.runoob.com/mysql/mysql-install.html)
- HertzBeat [Installation and deployment documentation](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [Installation and deployment documentation](https://hertzbeat.com/docs/start/docker-deploy)
#### Add monitoring of Mysql database on the open source monitoring tool HertzBeat monitoring page
@@ -40,7 +40,7 @@ Keywords: [Open source monitoring tool, open source database monitoring, Mysql d
2. Configure the parameters required for the new monitoring Mysql database
On the monitoring page, fill in Mysql **service IP**, **monitoring port** (default 3306), **account password, etc.**, and finally click OK to add.
For other parameters such as **collection interval**, **timeout period**, etc., please refer to [Help Documentation](https://hertzbeat.apache.org/docs/help/mysql/) <https://hertzbeat.apache.org/docs/help> /mysql/
For other parameters such as **collection interval**, **timeout period**, etc., please refer to [Help Documentation](https://hertzbeat.com/docs/help/mysql/) <https://hertzbeat.com/docs/help> /mysql/
![HertzBeat](/img/blog/monitor-mysql-2.png)
@@ -88,7 +88,7 @@ Of course, just looking at it is definitely not perfect. Monitoring is often acc
Message notification methods support **email, DingTalk, WeChat Work, Feishu, WebHook, SMS**, etc. Here we take the commonly used DingTalk as an example.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [Help Documentation](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the receiver parameters in HertzBeat as follows.
【Alarm Notification】->【New Recipient】->【Select DingTalk Robot Notification Method】->【Set DingTalk Robot ACCESS_TOKEN】->【OK】
+3 -3
View File
@@ -24,7 +24,7 @@ Github: <https://github.com/apache/hertzbeat>
#### Prerequisites, you already have a Linux environment and a HertzBeat environment
- HertzBeat [Installation and deployment documentation](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [Installation and deployment documentation](https://hertzbeat.com/docs/start/docker-deploy)
#### Add monitoring of the Linux operating system to the monitoring page of the open source monitoring tool HertzBeat
@@ -37,7 +37,7 @@ Github: <https://github.com/apache/hertzbeat>
2. Configure the parameters required for new monitoring Linux
Fill in the Linux **peer IP**, **SSH port** (default 22), **account password, etc.** on the monitoring page, and finally click OK to add.
For other parameters such as **collection interval**, **timeout period**, etc., please refer to the help document <https://hertzbeat.apache.org/docs/help/mysql/>
For other parameters such as **collection interval**, **timeout period**, etc., please refer to the help document <https://hertzbeat.com/docs/help/mysql/>
![HertzBeat](/img/blog/monitor-linux-2.png)
@@ -89,7 +89,7 @@ Of course, just looking at it is definitely not perfect. Monitoring is often acc
Message notification methods support **email, DingTalk, WeChat Work, Feishu, WebHook, SMS**, etc. Here we take the commonly used DingTalk as an example.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [Help Documentation](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the receiver parameters in HertzBeat as follows.
【Alarm Notification】->【New Recipient】->【Select DingTalk Robot Notification Method】->【Set DingTalk Robot ACCESS_TOKEN】->【OK】
+3 -3
View File
@@ -28,7 +28,7 @@ Github: <https://github.com/apache/hertzbeat>
#### Prerequisite, you already have SpringBoot2 application environment and HertzBeat environment
- HertzBeat [Installation and deployment documentation](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [Installation and deployment documentation](https://hertzbeat.com/docs/start/docker-deploy)
#### 1. The `actuator` metric endpoint is exposed on the SpringBoot2 application side, which will provide metrics endpoints data
@@ -94,7 +94,7 @@ Github: <https://github.com/apache/hertzbeat>
2. Configure the parameters required for new monitoring SpringBoot2
Fill in the SpringBoot2 application **peer IP**, **service port** (default 8080), **account password, etc.** on the monitoring page, and finally click OK to add.
For other parameters such as **collection interval**, **timeout period**, etc., please refer to the help document <https://hertzbeat.apache.org/docs/help/>
For other parameters such as **collection interval**, **timeout period**, etc., please refer to the help document <https://hertzbeat.com/docs/help/>
![HertzBeat](/img/blog/monitor-springboot2-2.png)
@@ -142,7 +142,7 @@ Of course, it is impossible to manually check the metrics in real time. Monitori
Message notification methods support **email, DingTalk, WeChat Work, Feishu, WebHook, SMS**, etc. Here we take the commonly used DingTalk as an example.
- Refer to this [Help Documentation](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Refer to this [Help Documentation](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> to configure the robot on DingTalk and set the security custom keyword `HertzBeat`, get the corresponding `access_token` value.
- Configure the receiver parameters in HertzBeat as follows.
【Alarm Notification】->【New Recipient】->【Select DingTalk Robot Notification Method】->【Set DingTalk Robot ACCESS_TOKEN】->【OK】
+1 -1
View File
@@ -58,7 +58,7 @@ You can refer to the [official documentation](https://docs.greptime.com/getting-
#### Installing and Deploying HertzBeat
See the [official documentation](https://hertzbeat.apache.org/zh-cn/docs/start/docker-deploy) for details.
See the [official documentation](https://hertzbeat.com/zh-cn/docs/start/docker-deploy) for details.
1. Docker installs HertzBeat.
+1 -1
View File
@@ -93,7 +93,7 @@ As for open source commercialization, the premise of open source commercializati
* `-e MANAGER_IP=127.0.0.1` : set the main hertzbeat server ip.
* `-e MANAGER_PORT=1158` : set the main hertzbeat server port, default 1158.
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache.org/docs/start/docker-deploy)
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.com/docs/start/docker-deploy)
---
+1 -1
View File
@@ -76,7 +76,7 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
* `-e MANAGER_HOST=127.0.0.1` : set the main hertzbeat server ip.
* `-e MANAGER_PORT=1158` : set the main hertzbeat server port, default 1158.
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache.org/docs/start/docker-deploy)
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.com/docs/start/docker-deploy)
---
+1 -1
View File
@@ -58,7 +58,7 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
* `-e MANAGER_HOST=127.0.0.1` : set the main hertzbeat server ip.
* `-e MANAGER_PORT=1158` : set the main hertzbeat server port, default 1158.
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache.org/docs/start/docker-deploy)
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.com/docs/start/docker-deploy)
---
+1 -1
View File
@@ -64,7 +64,7 @@ Compatible with the Prometheus ecosystem, now we can monitor what Prometheus can
* `-e MANAGER_HOST=127.0.0.1` : set the main hertzbeat server ip.
* `-e MANAGER_PORT=1158` : set the main hertzbeat server port, default 1158.
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache.org/docs/start/docker-deploy)
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.com/docs/start/docker-deploy)
---
+1 -1
View File
@@ -65,7 +65,7 @@ keywords: [open source monitoring system, alerting system]
* `-e MANAGER_HOST=127.0.0.1` : set the main hertzbeat server ip.
* `-e MANAGER_PORT=1158` : set the main hertzbeat server port, default 1158.
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.apache.org/docs/start/docker-deploy)
Detailed config refer to [Install HertzBeat via Docker](https://hertzbeat.com/docs/start/docker-deploy)
---
+1 -1
View File
@@ -374,7 +374,7 @@ Upgrade Guide: <https://hertzbeat.apache.org/blog/2024/06/11/hertzbeat-v1.6.0-up
```docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat quay.io/tancloud/hertzbeat```
Detailed refer to HertzBeat Document <https://hertzbeat.apache.org/docs>
Detailed refer to HertzBeat Document <https://hertzbeat.com/docs>
---
**Github: <https://github.com/apache/hertzbeat>**
-198
View File
@@ -1,198 +0,0 @@
---
title: Announcement of Apache Hertzbeat 1.7.2 Release
author: tomsun28
author_title: tomsun28
author_url: https://github.com/zhangshenghang
author_image_url: https://avatars.githubusercontent.com/u/24788200?s=400&v=4
tags: [opensource, release]
keywords: [open source monitoring system, alerting system, Hertzbeat, release]
---
Dear Community Members,
We are thrilled to announce the official release of Apache Hertzbeat version 1.7.2!
## Downloads and Documentation
- **Apache Hertzbeat 1.7.2 Download Link**: <https://hertzbeat.apache.org/docs/download>
- **Apache Hertzbeat Documentation**: <https://hertzbeat.apache.org/docs/>
## Major Updates
### New Features and Enhancements
- **Cloud Alert Integration**: Supports Alibaba Cloud SLS Log Service alert sources (#3422), Huawei Cloud Monitor alert sources (#3443), and Volcano Engine alert sources (#3451).
- **Service Discovery Enhancements**: Added Zookeeper service discovery support (#3377), Nacos auto-discovery (#3324), and HTTP service discovery collector with authentication support (#3388).
- **AI & Data Source Expansion**: Integrated Ollama AI model (#3441), added OpenRouter AI provider support (#3439), and enabled GreptimeDB as a Grafana data source (#3403).
- **Expression & Data Processing**: Supports sql and promql expression syntax (#3410); added batch import metrics to VictoriaMetrics (#3337).
- **Platform Compatibility**: Added Darwin (macOS) platform support (#3431).
- **Monitoring Metric Enhancements**: New statusCode metric data (#3446).
- **Other new features**
### Bug Fixes
- **Alert Notification Issues**: Fixed Uptime Kuma/Zabbix/Tencent Cloud Webhook URL errors (#3351); corrected Feishu notification format (#3508).
- **Threshold Functionality**: Fixed real-time Prometheus threshold failure (#3434).
- **Monitoring Status Errors**: Resolved incorrect sub-monitor status display (#3340) and monitoring list pagination issues (#3467).
- **System Stability**: Fixed null pointer exception in custom monitoring dashboard (#3448); resolved Jacoco test report generation failure (#3455).
- **Data Parsing Issues**: Fixed ANTLR4 parsing logic (binary operators/vectors) (#3482, #3488); corrected alert expression parsing errors (#3497, #3504).
- **Data Storage Optimization**: Improved GreptimeDB storage and query logic (#3387).
- **Other bug fixes**
### Refactoring and Optimization
- **Security Validation Enhancements**: Strengthened URL validation (WeCom/Telegram/Slack/ServerChan) (#3361-3364); added JNDI security checks (#3358); verified plugin service paths (#3375).
- **Architecture & Storage Optimization**: Updated security model (#3450); optimized DB column types (commonAnnotations/alertFingerprints to TEXT) (#3463); adjusted JDBC logic (#3500).
- **Dev Toolchain**: Added Maven Wrapper (mvnw) (#3430); updated dependencies (#3359, #3498); supported mvnd and optimized backend builds (#3491).
- **Observability**: Disabled OpenTelemetry exporters by default to prevent connection errors (#3437, #3461).
- **Community Collaboration**: Updated Issue templates (#3421).
- **Other optimizations**
### Tests and Quality
- **Unit Test Coverage**: Added unit tests for HttpSdCollectImpl (#3386).
### Documentation Enhancements
- **Internationalization**: Added 30+ Japanese documentation components (API/CentOS/Cisco switches/ClickHouse, etc.) (#3352, #3376, #3389).
- **Alert Documentation**: Updated alert threshold configuration (#3399), notification templates (#3466), and Volcano Engine integration guide (#3460).
- **Deployment & Configuration**: Added Grafana anonymous auth configuration (#3407); Rainbond cloud one-click installation guide (#3440).
- **Content Refinement**: Fixed time template syntax errors (#3378); optimized Chinese terminology (#3380, #3383); updated Greptime-init docs (#3355).
- **Community**: Added contributor/committer profiles (#3357, #3391, #3395); release blogs (#3449).
- **More documentation updates**
## Acknowledgements
Special thanks to the following community members for their collaborative efforts:
> @pruidong @MasamiYui @tomsun28 @Aias00 @zhangshenghang @zqr10159 @LiuTianyou @LL-LIN @lx1229 @xiaomizhou2 @pwallk
> @bigcyy @yuluo-yx @TJxiaobao @RainBondsongyg @Duansg @Calvin979 @Cyanty
## What's Changed
```markdown
* [bugfix] Fix incorrect webhook URLs for Uptime Kuma, Zabbix, and Tencent Cloud by @bigcyy in https://github.com/apache/hertzbeat/pull/3351
* [doc] japanese api by @Calvin979 in https://github.com/apache/hertzbeat/pull/3352
* [doc] update OS monitor by @MasamiYui in https://github.com/apache/hertzbeat/pull/3353
* [doc](start): update greptime-init documentation by @zqr10159 in https://github.com/apache/hertzbeat/pull/3355
* [doc] new ppmc liutianyou and update qq num by @tomsun28 in https://github.com/apache/hertzbeat/pull/3357
* [bugfix] Incorrect SD sub-monitor status by @MasamiYui in https://github.com/apache/hertzbeat/pull/3340
* [improve] improve url validation for WeComRobotAlertNotifyHandlerImpl by @Aias00 in https://github.com/apache/hertzbeat/pull/3361
* [improve] improve url validation for TelegramBotAlertNotifyHandlerImpl by @Aias00 in https://github.com/apache/hertzbeat/pull/3362
* [improve] improve url validation for SlackAlertNotifyHandlerImpl by @Aias00 in https://github.com/apache/hertzbeat/pull/3363
* [improve] improve url validation for serverChan by @Aias00 in https://github.com/apache/hertzbeat/pull/3364
* [improve] improve jndi validation by @Aias00 in https://github.com/apache/hertzbeat/pull/3358
* update maven dep by @Aias00 in https://github.com/apache/hertzbeat/pull/3359
* [doc] japanese centos by @Calvin979 in https://github.com/apache/hertzbeat/pull/3376
* [doc] fix incorrect time template syntax usercase in doc by @LL-LIN in https://github.com/apache/hertzbeat/pull/3378
* [doc] Add blog by @LiuTianyou in https://github.com/apache/hertzbeat/pull/3379
* [improve] add path validation for pluginservice by @Aias00 in https://github.com/apache/hertzbeat/pull/3375
* [feat] Support Zookeeper Service Discovery by @bigcyy in https://github.com/apache/hertzbeat/pull/3377
* [doc] modify chinese words by @Duansg in https://github.com/apache/hertzbeat/pull/3380
* [Task] Batch import metrics data in victoria-metrics by @MasamiYui in https://github.com/apache/hertzbeat/pull/3337
* [feature] support auto nacos service discovery by @xiaomizhou2 in https://github.com/apache/hertzbeat/pull/3324
* [doc] modify supplement related documentation by @Duansg in https://github.com/apache/hertzbeat/pull/3383
* [doc] japanese cisco switch by @Calvin979 in https://github.com/apache/hertzbeat/pull/3389
* [test] Add unit tests for HttpSdCollectImpl by @xiaomizhou2 in https://github.com/apache/hertzbeat/pull/3386
* [fix](warehouse): improve GreptimeDB data storage and querying by @zqr10159 in https://github.com/apache/hertzbeat/pull/3387
* [doc] japanese clickhouse by @Calvin979 in https://github.com/apache/hertzbeat/pull/3390
* [doc] new contributor and committer, update doc by @tomsun28 in https://github.com/apache/hertzbeat/pull/3391
* [doc] japanese consul sd by @Calvin979 in https://github.com/apache/hertzbeat/pull/3392
* [doc]add new committer blog by @pwallk in https://github.com/apache/hertzbeat/pull/3395
* [doc] japanese coreos by @Calvin979 in https://github.com/apache/hertzbeat/pull/3393
* [doc] japanese dahua by @Calvin979 in https://github.com/apache/hertzbeat/pull/3396
* [doc] japanese Debian by @Calvin979 in https://github.com/apache/hertzbeat/pull/3398
* [improve] http sd collector adds authentication by @Cyanty in https://github.com/apache/hertzbeat/pull/3388
* [doc] japanese deepseek & dm by @Calvin979 in https://github.com/apache/hertzbeat/pull/3400
* [docs] update alert threshold doc by @bigcyy in https://github.com/apache/hertzbeat/pull/3399
* [doc] japanese dns by @Calvin979 in https://github.com/apache/hertzbeat/pull/3404
* [doc] japanese dns sd by @Calvin979 in https://github.com/apache/hertzbeat/pull/3405
* [doc] japanese docker by @Calvin979 in https://github.com/apache/hertzbeat/pull/3408
* [doc] japanese doris_be by @Calvin979 in https://github.com/apache/hertzbeat/pull/3409
* [Doc] Update 1.7.1 by @zhangshenghang in https://github.com/apache/hertzbeat/pull/3411
* [doc] update home doc by @tomsun28 in https://github.com/apache/hertzbeat/pull/3418
* [doc] Update anonymous user auth configuration of the grafana dashboard document by @Cyanty in https://github.com/apache/hertzbeat/pull/3407
* [doc] japanese doris_fe by @Calvin979 in https://github.com/apache/hertzbeat/pull/3416
* [infra]: Update issue tmpl by @yuluo-yx in https://github.com/apache/hertzbeat/pull/3421
* [feature]Make GreptimeDB as a grafana data source by @zqr10159 in https://github.com/apache/hertzbeat/pull/3403
* [feat] support sql("...") and promql("...") expressions including SQL condition parsing by @bigcyy in https://github.com/apache/hertzbeat/pull/3410
* [doc] japanese dynamic_tp by @Calvin979 in https://github.com/apache/hertzbeat/pull/3419
* [doc] japanese elasticsearch by @Calvin979 in https://github.com/apache/hertzbeat/pull/3423
* [feature]Support Alibaba Cloud 'Simple Log Service(SLS)' alert source by @Duansg in https://github.com/apache/hertzbeat/pull/3422
* [Improve] add mvnw by @zhangshenghang in https://github.com/apache/hertzbeat/pull/3430
* [doc] japanese emqx by @Calvin979 in https://github.com/apache/hertzbeat/pull/3433
* [improvement] disable default OpenTelemetry exporters to prevent connection errors by @bigcyy in https://github.com/apache/hertzbeat/pull/3437
* [bugfix] Fix the issue where Prometheus RealTime Threshold is not eff… by @Duansg in https://github.com/apache/hertzbeat/pull/3434
* [feat] add support for ollama and update docs by @bigcyy in https://github.com/apache/hertzbeat/pull/3441
* [release] add support for darwin by @lx1229 in https://github.com/apache/hertzbeat/pull/3431
* [feature] Support Huawei Cloud `Cloud Eye` alert source by @Duansg in https://github.com/apache/hertzbeat/pull/3443
* [doc] japanese euleros by @Calvin979 in https://github.com/apache/hertzbeat/pull/3442
* docs: Add one-click installation for Rainbond Cloud by @RainBondsongyg in https://github.com/apache/hertzbeat/pull/3440
* [feat] add support for OpenRouter AI provider by @bigcyy in https://github.com/apache/hertzbeat/pull/3439
* [doc] japanese flink by @Calvin979 in https://github.com/apache/hertzbeat/pull/3447
* [security] update hertzbeat security model by @tomsun28 in https://github.com/apache/hertzbeat/pull/3450
* [feature] support volcengine alert source by @LiuTianyou in https://github.com/apache/hertzbeat/pull/3451
* [doc] add publish version 1.7.1 blog by @tomsun28 in https://github.com/apache/hertzbeat/pull/3449
* [doc] japanese flink on yarn by @Calvin979 in https://github.com/apache/hertzbeat/pull/3452
* [doc] japanese freebsd by @Calvin979 in https://github.com/apache/hertzbeat/pull/3456
* [improvement] disable default OpenTelemetry exporters to prevent connection errors by @bigcyy in https://github.com/apache/hertzbeat/pull/3461
* [doc] add doc for integrate volcengine alerts by @LiuTianyou in https://github.com/apache/hertzbeat/pull/3460
* [Fix] fix custom monitoring bulletin `NullPointerException` by @Duansg in https://github.com/apache/hertzbeat/pull/3448
* [fix] fix jacoco can not generate test reports. by @Duansg in https://github.com/apache/hertzbeat/pull/3455
* [doc] Alert notification template by @MasamiYui in https://github.com/apache/hertzbeat/pull/3466
* [doc] japanese greenplum by @Calvin979 in https://github.com/apache/hertzbeat/pull/3468
* [improvement] change column definitions for commonAnnotations and alertFingerprints to TEXT type by @bigcyy in https://github.com/apache/hertzbeat/pull/3463
* [fix] Fix `Monitors` paging display. by @Duansg in https://github.com/apache/hertzbeat/pull/3467
* [doc] japanese greptime by @Calvin979 in https://github.com/apache/hertzbeat/pull/3469
* [doc] japanese h3c switch by @Calvin979 in https://github.com/apache/hertzbeat/pull/3471
* [feature] Add statusCode metrics data. by @Duansg in https://github.com/apache/hertzbeat/pull/3446
* [doc] japanese hadoop by @Calvin979 in https://github.com/apache/hertzbeat/pull/3476
* [docs](webhook): update Chinese documentation for alert integration by @zqr10159 in https://github.com/apache/hertzbeat/pull/3478
* [doc] japanese hbase master by @Calvin979 in https://github.com/apache/hertzbeat/pull/3477
* [doc] japanese hbase region server by @Calvin979 in https://github.com/apache/hertzbeat/pull/3479
* [doc] japanese hdfs datanode by @Calvin979 in https://github.com/apache/hertzbeat/pull/3487
* [fix] antlr4 `vectors and` parse semantic fixes and optimizations by @Duansg in https://github.com/apache/hertzbeat/pull/3482
* [ci]: add mvnd support and update backend build by @zqr10159 in https://github.com/apache/hertzbeat/pull/3491
* [doc] japanese hdfs namenode by @Calvin979 in https://github.com/apache/hertzbeat/pull/3490
* [doc] japanese hertzbeat by @Calvin979 in https://github.com/apache/hertzbeat/pull/3492
* [fix] Fix antlr4 parsing of `or` and `unless` logical and set binary operators by @Duansg in https://github.com/apache/hertzbeat/pull/3488
* [doc] japanese hertzbeat token by @Calvin979 in https://github.com/apache/hertzbeat/pull/3493
* [feat] update_mvnd_version by @Aias00 in https://github.com/apache/hertzbeat/pull/3498
* add:a small jdbc modified. by @TJxiaobao in https://github.com/apache/hertzbeat/pull/3500
* fixed:a minor issue change by @TJxiaobao in https://github.com/apache/hertzbeat/pull/3428
* [bugfix] Fix incorrect expression parsing in alert setting component by @bigcyy in https://github.com/apache/hertzbeat/pull/3497
* [bugfix] Correctly parse binary comparison expressions by @bigcyy in https://github.com/apache/hertzbeat/pull/3504
* [bugfix]Fixed an error in the format of the flying book notification by @pruidong in https://github.com/apache/hertzbeat/pull/3508
* [release] release new version 1.7.2 by @tomsun28 in https://github.com/apache/hertzbeat/pull/3510
```
## New Contributors
- @Duansg made their first contribution in <https://github.com/apache/hertzbeat/pull/3380>
- @lx1229 made their first contribution in <https://github.com/apache/hertzbeat/pull/3431>
- @RainBondsongyg made their first contribution in <https://github.com/apache/hertzbeat/pull/3440>
## Apache Hertzbeat
**Repository URL:**
<https://github.com/apache/hertzbeat>
**Official Website:**
<https://hertzbeat.apache.org/>
**Apache Hertzbeat Download Link:**
<https://hertzbeat.apache.org/docs/download>
**Apache Hertzbeat Docker Images:**
Apache Hertzbeat provides Docker images for each release, available on Docker Hub:
- HertzBeat: <https://hub.docker.com/r/apache/hertzbeat>
- HertzBeat Collector: <https://hub.docker.com/r/apache/hertzbeat-collector>
**How to Contribute to the Apache Hertzbeat Open Source Community?**
<https://hertzbeat.apache.org/docs/community/contribution>
-48
View File
@@ -1,48 +0,0 @@
---
title: Welcome HertzBeat's New Community Committer!
author: bigcyy
author_title: Yang Chen
author_url: https://github.com/bigcyy
author_image_url: https://avatars.githubusercontent.com/u/73413979
tags: [opensource, practice]
keywords:
[
open source monitoring system,
alerting system,
Apache,
Apache Committer,
Hertzbeat,
]
---
Hello everyone, I'm Yang Chen, currently a graduate student at Chongqing University of Posts and Telecommunications. I'm deeply honored to receive recognition and invitation from the Apache HertzBeat community to officially become a project Committer. This marks the true beginning of my open-source journey!
## My Open Source Exploration
As early as my undergraduate years, I had exposure to open source.
Back then, I developed a [epidemic notice QQ bot](https://github.com/bigcyy/GroupNotifier) based on the open-source [Mirai](https://github.com/mamoe/mirai) framework. However, that was more at the usage level.
In my junior year, I attempted to independently open-source an AI project called [customized_chat](https://github.com/bigcyy/customized-chat), which was my first step into "open source."
But these experiences were all solo explorations, and I deeply felt that this wasn't true open source, as it failed to establish a complete community ecosystem.
## Meeting HertzBeat: True Open Source Practice
To participate more deeply in open source, I began searching for suitable open-source activities and thus encountered HertzBeat. For me, this was the true beginning of my open-source journey. Here, I not only learned solid technical development but also experienced a mature community ecosystem. I deeply understood the essence of the "Apache Way" - the community builds the project, not the project builds the community.
I first learned about HertzBeat through GSoC (Google Summer of Code), when the community's proposal about developing monitoring MCP deeply attracted me. So I proactively contacted Tom and officially began participating in community activities. Tom was very enthusiastic, and the entire community was exceptionally active.
I clearly remember my first PR (Pull Request), when I even conducted online testing with a user in an Issue, which was quite a unique experience for me. Although I wasn't ultimately selected for GSoC, during that period, I had already deeply participated in the community and fully experienced its excellence.
## Growth and Gains from Open Source
Participating in open source has indeed significantly improved my abilities. By reading HertzBeat's architectural design and actively participating in community discussions, I've accumulated many valuable experiences, such as:
- Cutting-edge Technology: I gained deep understanding of monitoring system design and implementation, and practiced core technologies like concurrent programming and distributed systems in the project.
- Practical Abilities: Through solving real problems and participating in code contributions, I successfully transformed theoretical knowledge into practical operational skills.
- Community Culture Experience: I personally experienced the unique charm of the "Apache Way" and engaged in deep exchanges and learning with developers from around the world.
My experience has convinced me that open source is not just about writing code, but an excellent platform for learning, growing, and contributing.
If you're also passionate about technology, eager to improve yourself through practice, and want to experience true community collaboration, then the Apache HertzBeat community is definitely your best choice!
## Finally
I sincerely thank [Tom](https://github.com/tomsun28), [Shenghang](https://github.com/zhangshenghang), [Logic](https://github.com/zqr10159), and other community members for their meticulous code reviews and patient guidance. I hope Apache HertzBeat continues to thrive!
+8 -8
View File
@@ -60,14 +60,14 @@ The following table is filled according to the [Apache Maturity Model](https://c
### Community
| **ID** | **Description** | **Status** |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **CO10** | The project has a well-known homepage that points to all the information required to operate according to this maturity model. | **YES** The [official website](https://hertzbeat.apache.org/) includes all information user need to run Apache HertzBeat. |
| **CO20** | The community welcomes contributions from anyone who acts in good faith and in a respectful manner, and who adds value to the project. | **Yes** We provide contributing guides for every component. And we also have a [general contributing guide](https://hertzbeat.apache.org/docs/community/contribution) |
| **CO30** | Contributions include source code, documentation, constructive bug reports, constructive discussions, marketing and generally anything that adds value to the project. | **YES** All good contributions including code and non-code are welcomed. |
| **CO40** | The community strives to be meritocratic and gives more rights and responsibilities to contributors who, over time, add value to the project. | **YES** The community has elected 3 new PPMC members and 13 new committers so far. |
| **CO50** | The project documents how contributors can earn more rights such as commit access or decision power, and applies these principles consistently. | **YES** The community has clear docs on nominating committers and PPMC members |
| **CO60** | The community operates based on consensus of its members (see CS10) who have decision power. Dictators, benevolent or not, are not welcome in Apache projects. | **YES** All decisions are made after vote by community members. |
| **ID** | **Description** | **Status** |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **CO10** | The project has a well-known homepage that points to all the information required to operate according to this maturity model. | **YES** The [official website](https://hertzbeat.apache.org/) includes all information user need to run Apache HertzBeat. |
| **CO20** | The community welcomes contributions from anyone who acts in good faith and in a respectful manner, and who adds value to the project. | **Yes** We provide contributing guides for every component. And we also have a [general contributing guide](https://hertzbeat.apache.org/docs/community/contribution) |
| **CO30** | Contributions include source code, documentation, constructive bug reports, constructive discussions, marketing and generally anything that adds value to the project. | **YES** All good contributions including code and non-code are welcomed. |
| **CO40** | The community strives to be meritocratic and gives more rights and responsibilities to contributors who, over time, add value to the project. | **YES** The community has elected 2 new PPMC members and 12 new committers so far. |
| **CO50** | The project documents how contributors can earn more rights such as commit access or decision power, and applies these principles consistently. | **YES** The community has clear docs on nominating committers and PPMC members |
| **CO60** | The community operates based on consensus of its members (see CS10) who have decision power. Dictators, benevolent or not, are not welcome in Apache projects. | **YES** All decisions are made after vote by community members. |
| **CO70** | The project strives to answer user questions in a timely manner. | **YES** We use <dev@hertzbeat.apache.org>, [GitHub issue](https://github.com/apache/hertzbeat/issues) and [GitHub discussion](https://github.com/apache/hertzbeat/discussions) to do this in a timely manner. |
### Consensus
-18
View File
@@ -21,24 +21,6 @@ sidebar_label: Common issues
> When you install HertzBeat via DockerDocker root is enabled by default. No such problem.
> See <https://stackoverflow.com/questions/11506321/how-to-ping-an-ip-address>
4. Configured Kubernetes monitoring, but the actual monitoring is not executing at the correct interval
Please troubleshoot the issue by following these steps:
> 1. First, check HertzBeat's error logs. If you see the message 'desc: SQL statement too long, check maxSQLLength config',
> 2. You need to adjust the TDengine configuration file. Create a taos.cfg file on the server and modify # max length of an SQL : maxSQLLength 654800, then restart TDengine. Ensure the configuration file is properly mounted.
> 3. If TDengine fails to restart, adjust the configuration in the mounted data file. Refer to .../taosdata/dnode/dnodeEps.json and change dnodeFqdn to the Docker ID of the failed startup instance, then run docker restart tdengine.
5. Configured HTTP API monitoring for business interface probing to ensure service availability. The API has token authentication, e.g., "Authorization: Bearer eyJhbGciOiJIUzI1....". After configuration, testing returns "StatusCode 401". The server receives the token as "Authorization: Bearer%20eyJhbGciOiJIUzI1....". HertzBeat escapes spaces to %20, but the server does not unescape it, causing authentication failure. It is recommended to make the escaping feature optional.
6. What is the task limit for a single collector?
> Specific limit parameters:
Core thread count: Math.max(2, Runtime.getRuntime().availableProcessors()) at least 2 threads, or equal to the number of CPU cores.
Maximum thread count: Runtime.getRuntime().availableProcessors() * 16 16 times the number of CPU cores.
> The limit depends entirely on the server's CPU core count. For example, on an 8-core CPU server, a maximum of 8 × 16 = 128 collection tasks can be processed simultaneously. Exceeding this number triggers the error message. This is a dynamic configuration that adjusts automatically based on the hardware specifications of the runtime environment.
> If the runtime exceeds the maximum thread count, an error will appear: "the worker pool is full, reject this metrics task, put in queue again".
> In such cases, it is recommended to configure a new collector in public mode. HertzBeat will automatically distribute tasks to other collectors, avoiding errors due to the task limit of a single collector.
### Docker Deployment common issues
1. **MYSQL, TDENGINE and HertzBeat are deployed on the same host by Docker,HertzBeat use localhost or 127.0.0.1 connect to the database but fail**
+1 -1
View File
@@ -434,7 +434,7 @@
"message": "{docker} {br}集监控-告警-通知为一体,支持应用服务,Web,数据库,缓存,操作系统,中间件,大数据,云原生,网络等监控阈值告警通知一步到位。{br} 易用友好,无需Agent,全WEB页面操作,鼠标点一点就能监控告警,无需学习成本。{br}安全是最重要的,数据密钥全链路加密。"
},
"custom-multi-support-content": {
"message": "将 Http,Jmx,Ssh,Snmp,Jdbc 等协议规范可配置模板化,只需在线配置YML就可自定义监控指标。{br} 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。{br}灵活的告警阈值规则,邮箱,短信,钉钉,企业微信,飞书,Webhook等消息及时送达。{br} 您相信只需配置下就能适配新K8s监控类型吗?"
"message": "将 Http,Jmx,Ssh,Snmp,Jdbc 等协议规范可配置模板化,只需在线配置YML就可自定义监控指标。{br} 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。{br}自由的告警阈值规则,邮箱,短信,钉钉,企业微信,飞书,Webhook等消息及时送达。{br} 您相信只需配置下就能适配新K8s监控类型吗?"
},
"opensource-content": {
"message": "Apache HertzBeat (incubating) 是开源的,拥有一个包容开放的社区。{br}欢迎任何对此有兴趣的同学参与其中,无论是代码文档或者错别字,尊重社区的每一位,一起进步成长。{br}我们的代码正被部署到全球成千上万机器上。{github}"
@@ -9,7 +9,7 @@ tags: [opensource]
[HertzBeat 赫兹跳动](https://github.com/apache/hertzbeat) 是由 [Dromara](https://dromara.org) 孵化,[TanCloud](https://tancloud.cn) 开源的一个支持网站,API,PING,端口,数据库,全站,操作系统,中间件等监控类型,支持阈值告警,告警通知 (邮箱,webhook,钉钉,企业微信,飞书机器人),拥有易用友好的可视化操作界面的开源监控告警项目。
**官网: [hertzbeat.com](https://hertzbeat.apache.org) | [tancloud.cn](https://tancloud.cn)**
**官网: [hertzbeat.com](https://hertzbeat.com) | [tancloud.cn](https://tancloud.cn)**
从v1.0-beta.1到v1.0-beat.8,经过多个版本的迭代完善,我们很高兴宣布hertzbeat v1.0正式发布。
@@ -9,7 +9,7 @@ tags: [opensource]
[HertzBeat 赫兹跳动](https://github.com/apache/hertzbeat) 是由 [Dromara](https://dromara.org) 孵化,[TanCloud](https://tancloud.cn) 开源的一个支持网站,API,PING,端口,数据库,全站,操作系统,中间件等监控类型,支持阈值告警,告警通知 (邮箱,webhook,钉钉,企业微信,飞书机器人),拥有易用友好的可视化操作界面的开源监控告警项目。
**官网: [hertzbeat.com](https://hertzbeat.apache.org) | [tancloud.cn](https://tancloud.cn)**
**官网: [hertzbeat.com](https://hertzbeat.com) | [tancloud.cn](https://tancloud.cn)**
大家好,HertzBeat v1.1.0 发布啦!这个版本我们支持了SNMP协议,并使用SNMP协议监控支持了windwos操作系统的应用监控。
另一个重大变更是我们默认使用了H2数据库来替换MYSQL数据库作为存储,来方便使用者们的安装部署,现在只需要一条docker命令即可安装体验hertzbeat `docker run -d -p 1157:1157 --name hertzbeat apache/hertzbeat`
@@ -9,7 +9,7 @@ tags: [opensource]
[HertzBeat 赫兹跳动](https://github.com/apache/hertzbeat) 是由 [Dromara](https://dromara.org) 孵化,[TanCloud](https://tancloud.cn) 开源的一个支持网站,API,PING,端口,数据库,全站,操作系统,中间件等监控类型,支持阈值告警,告警通知 (邮箱,webhook,钉钉,企业微信,飞书机器人),拥有易用友好的可视化操作界面的开源监控告警项目。
**官网: [hertzbeat.com](https://hertzbeat.apache.org) | [tancloud.cn](https://tancloud.cn)**
**官网: [hertzbeat.com](https://hertzbeat.com) | [tancloud.cn](https://tancloud.cn)**
大家好,HertzBeat v1.1.0 发布啦!这个版本我们支持了SNMP协议,并使用SNMP协议监控支持了windwos操作系统的应用监控。
另一个重大变更是我们默认使用了H2数据库来替换MYSQL数据库作为存储,来方便使用者们的安装部署,现在只需要一条docker命令即可安装体验hertzbeat `docker run -d -p 1157:1157 --name hertzbeat apache/hertzbeat`
@@ -9,7 +9,7 @@ tags: [opensource]
[HertzBeat 赫兹跳动](https://github.com/apache/hertzbeat) 是由 [Dromara](https://dromara.org) 孵化,[TanCloud](https://tancloud.cn) 开源的一个支持网站,API,PING,端口,数据库,全站,操作系统,中间件等监控类型,支持阈值告警,告警通知 (邮箱,webhook,钉钉,企业微信,飞书机器人),拥有易用友好的可视化操作界面的开源监控告警项目。
**官网: [hertzbeat.com](https://hertzbeat.apache.org) | [tancloud.cn](https://tancloud.cn)**
**官网: [hertzbeat.com](https://hertzbeat.com) | [tancloud.cn](https://tancloud.cn)**
大家好,HertzBeat v1.1.1 发布啦!这个版本带来了自定义监控增强,采集指标数据可以作为变量赋值给下一个采集。修复了若干bug,提升整体稳定性。
@@ -17,7 +17,7 @@ tags: [opensource, practice]
HertzBeat 一个拥有强大自定义监控能力,无需Agent的实时监控工具。网站监测,PING连通性,端口可用性,数据库,操作系统,中间件,API监控,阈值告警,告警通知(邮件微信钉钉飞书)。
**官网: <https://hertzbeat.apache.org> | <https://tancloud.cn>**
**官网: <https://hertzbeat.com> | <https://tancloud.cn>**
github: <https://github.com/apache/hertzbeat>
gitee: <https://gitee.com/hertzbeat/hertzbeat>
@@ -87,7 +87,7 @@ gitee: <https://gitee.com/hertzbeat/hertzbeat>
钉钉微信飞书等token配置可以参考帮助文档
<https://hertzbeat.apache.org/docs/help/alert_dingtalk>
<https://hertzbeat.com/docs/help/alert_dingtalk>
<https://tancloud.cn/docs/help/alert_dingtalk>
> 告警通知 -> 新增告警通知策略 -> 将刚才配置的接收人启用通知
@@ -98,7 +98,7 @@ github[Ceilzcx (zcx) (github.com)](https://github.com/Ceilzcx)
### 如何参与Hertzbeat
+ 官网有非常完善的贡献者指南:[贡献者指南 | HertzBeat](https://hertzbeat.apache.org/docs/community/contribution)
+ 官网有非常完善的贡献者指南:[贡献者指南 | HertzBeat](https://hertzbeat.com/docs/community/contribution)
+ Github issues[Issues · apache/hertzbeat (github.com)](https://github.com/apache/hertzbeat/issues)
@@ -26,7 +26,7 @@ keywords: [开源监控系统, 开源数据库监控, IotDB数据库监控]
#### 操作前提,您已拥有 IoTDB 环境和 HertzBeat 环境
- IoTDB [部署安装文档](https://iotdb.apache.org/UserGuide/V0.13.x/QuickStart/QuickStart.html)
- HertzBeat [部署安装文档](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [部署安装文档](https://hertzbeat.com/docs/start/docker-deploy)
#### 一. 在 IoTDB 端开启`metrics`功能,它将提供 prometheus metrics 形式的接口数据
@@ -55,7 +55,7 @@ keywords: [开源监控系统, 开源数据库监控, IotDB数据库监控]
2. 配置监控IoTDB所需参数
在监控页面填写 IoTDB **服务IP**,**监控端口**(默认9091),最后点击确定添加即可。
其他参数如**采集间隔**,**超时时间**等可以参考[帮助文档](https://hertzbeat.apache.org/docs/help/iotdb/) <https://hertzbeat.apache.org/docs/help/iotdb/>
其他参数如**采集间隔**,**超时时间**等可以参考[帮助文档](https://hertzbeat.com/docs/help/iotdb/) <https://hertzbeat.com/docs/help/iotdb/>
![HertzBeat](/img/blog/monitor-iotdb-2.png)
@@ -97,7 +97,7 @@ keywords: [开源监控系统, 开源数据库监控, IotDB数据库监控]
消息通知方式支持 **邮件,钉钉,企业微信,飞书,WebHook,短信**等,我们这里以常用的钉钉为例。
- 参照此[帮助文档](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 参照此[帮助文档](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 在 HertzBeat 配置接收人参数如下。
【告警通知】->【新增接收人】 ->【选择钉钉机器人通知方式】->【设置钉钉机器人ACCESS_TOKEN】-> 【确定】
@@ -33,7 +33,7 @@ tags: [opensource, practice]
#### 操作前提,您已拥有 ShenYu 环境和 HertzBeat 环境
- ShenYu [部署安装文档](https://shenyu.apache.org/zh/docs/deployment/deployment-before)
- HertzBeat [部署安装文档](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [部署安装文档](https://hertzbeat.com/docs/start/docker-deploy)
#### 一. 在 ShenYu 端开启`metrics`插件,它将提供 metrics 接口数据
@@ -77,7 +77,7 @@ tags: [opensource, practice]
2. 配置监控 ShenYu 所需参数
在监控页面填写 ShenYu **服务IP**,**监控端口**(默认8090),最后点击确定添加即可。
其他参数如**采集间隔**,**超时时间**等可以参考[帮助文档](https://hertzbeat.apache.org/docs/help/shenyu/) <https://hertzbeat.apache.org/docs/help/shenyu/>
其他参数如**采集间隔**,**超时时间**等可以参考[帮助文档](https://hertzbeat.com/docs/help/shenyu/) <https://hertzbeat.com/docs/help/shenyu/>
![HertzBeat](/img/blog/monitor-shenyu-1.png)
@@ -126,7 +126,7 @@ tags: [opensource, practice]
消息通知方式支持 **邮件,钉钉,企业微信,飞书,WebHook,短信**等,我们这里以常用的钉钉为例。
- 参照此[帮助文档](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 参照此[帮助文档](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 在 HertzBeat 配置接收人参数如下。
【告警通知】->【新增接收人】 ->【选择钉钉机器人通知方式】->【设置钉钉机器人ACCESS_TOKEN】-> 【确定】
@@ -30,7 +30,7 @@ tags: [opensource, practice]
#### 操作前提,您已拥有 DynamicTp 环境和 HertzBeat 环境
- DynamicTp [集成接入文档](https://dynamictp.cn/guide/use/quick-start.html)
- HertzBeat [部署安装文档](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [部署安装文档](https://hertzbeat.com/docs/start/docker-deploy)
#### 一. 在 DynamicTp 端暴露出`DynamicTp`指标接口 `/actuator/dynamic-tp`,它将提供 metrics 接口数据
@@ -89,7 +89,7 @@ tags: [opensource, practice]
2. 配置监控 DynamicTp 所需参数
在监控页面填写 DynamicTp **服务IP**,**监控端口**(默认8080),最后点击确定添加即可。
其他参数如**采集间隔**,**超时时间**等可以参考[帮助文档](https://hertzbeat.apache.org/docs/help/dynamic_tp/) <https://hertzbeat.apache.org/docs/help/dynamic_tp/>
其他参数如**采集间隔**,**超时时间**等可以参考[帮助文档](https://hertzbeat.com/docs/help/dynamic_tp/) <https://hertzbeat.com/docs/help/dynamic_tp/>
![HertzBeat](/img/blog/monitor-dynamic-tp-2.png)
@@ -138,7 +138,7 @@ tags: [opensource, practice]
消息通知方式支持 **邮件,钉钉,企业微信,飞书,WebHook,短信**等,我们这里以常用的钉钉为例。
- 参照此[帮助文档](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 参照此[帮助文档](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 在 HertzBeat 配置接收人参数如下。
【告警通知】->【新增接收人】 ->【选择钉钉机器人通知方式】->【设置钉钉机器人ACCESS_TOKEN】-> 【确定】
@@ -27,7 +27,7 @@ keywords: [开源监控系统, 开源数据库监控, Mysql数据库监控]
#### 操作前提,您已拥有 Mysql 环境和 HertzBeat 环境
- Mysql [安装部署文档](https://www.runoob.com/mysql/mysql-install.html)
- HertzBeat [安装部署文档](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [安装部署文档](https://hertzbeat.com/docs/start/docker-deploy)
#### 在开源监控系统 HertzBeat 监控页面添加对 Mysql 数据库监控
@@ -40,7 +40,7 @@ keywords: [开源监控系统, 开源数据库监控, Mysql数据库监控]
2. 配置新增监控 Mysql 数据库所需参数
在监控页面填写 Mysql **服务IP****监控端口**(默认3306),**账户密码等**,最后点击确定添加即可。
其他参数如**采集间隔**,**超时时间**等可以参考[帮助文档](https://hertzbeat.apache.org/docs/help/mysql/) <https://hertzbeat.apache.org/docs/help/mysql/>
其他参数如**采集间隔**,**超时时间**等可以参考[帮助文档](https://hertzbeat.com/docs/help/mysql/) <https://hertzbeat.com/docs/help/mysql/>
![HertzBeat](/img/blog/monitor-mysql-2.png)
@@ -88,7 +88,7 @@ keywords: [开源监控系统, 开源数据库监控, Mysql数据库监控]
消息通知方式支持 **邮件,钉钉,企业微信,飞书,WebHook,短信**等,我们这里以常用的钉钉为例。
- 参照此[帮助文档](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 参照此[帮助文档](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 在 HertzBeat 配置接收人参数如下。
【告警通知】->【新增接收人】 ->【选择钉钉机器人通知方式】->【设置钉钉机器人ACCESS_TOKEN】-> 【确定】
@@ -24,7 +24,7 @@ Github: <https://github.com/apache/hertzbeat>
#### 操作前提,您已拥有 Linux 环境和 HertzBeat 环境
- HertzBeat [安装部署文档](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [安装部署文档](https://hertzbeat.com/docs/start/docker-deploy)
#### 在开源监控系统 HertzBeat 监控页面添加对 Linux 操作系统监控
@@ -37,7 +37,7 @@ Github: <https://github.com/apache/hertzbeat>
2. 配置新增监控 Linux 所需参数
在监控页面填写 Linux **对端IP****SSH端口**(默认22),**账户密码等**,最后点击确定添加即可。
其他参数如**采集间隔**,**超时时间**等可以参考帮助文档 <https://hertzbeat.apache.org/docs/help/mysql/>
其他参数如**采集间隔**,**超时时间**等可以参考帮助文档 <https://hertzbeat.com/docs/help/mysql/>
![HertzBeat](/img/blog/monitor-linux-2.png)
@@ -149,7 +149,7 @@ Github: <https://github.com/apache/hertzbeat>
消息通知方式支持 **邮件,钉钉,企业微信,飞书,WebHook,短信**等,我们这里以常用的钉钉为例。
- 参照此[帮助文档](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 参照此[帮助文档](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 在 HertzBeat 配置接收人参数如下。
【告警通知】->【新增接收人】 ->【选择钉钉机器人通知方式】->【设置钉钉机器人ACCESS_TOKEN】-> 【确定】
@@ -24,7 +24,7 @@ Github: <https://github.com/apache/hertzbeat>
#### 操作前提,您已拥有 SpringBoot2 应用环境和 HertzBeat 环境
- HertzBeat [安装部署文档](https://hertzbeat.apache.org/docs/start/docker-deploy)
- HertzBeat [安装部署文档](https://hertzbeat.com/docs/start/docker-deploy)
#### 一. 在 SpringBoot2 应用端暴露出`actuator`指标接口,它将提供 metrics 接口数据
@@ -90,7 +90,7 @@ Github: <https://github.com/apache/hertzbeat>
2. 配置新增监控 SpringBoot2 所需参数
在监控页面填写 SpringBoot2应用 **对端IP****服务端口**(默认8080),**账户密码等**,最后点击确定添加即可。
其他参数如**采集间隔**,**超时时间**等可以参考帮助文档 <https://hertzbeat.apache.org/docs/help/>
其他参数如**采集间隔**,**超时时间**等可以参考帮助文档 <https://hertzbeat.com/docs/help/>
![HertzBeat](/img/blog/monitor-springboot2-2.png)
@@ -138,7 +138,7 @@ Github: <https://github.com/apache/hertzbeat>
消息通知方式支持 **邮件,钉钉,企业微信,飞书,WebHook,短信**等,我们这里以常用的钉钉为例。
- 参照此[帮助文档](https://hertzbeat.apache.org/docs/help/alert_dingtalk) <https://hertzbeat.apache.org/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 参照此[帮助文档](https://hertzbeat.com/docs/help/alert_dingtalk) <https://hertzbeat.com/docs/help/alert_dingtalk> 在钉钉端配置机器人,设置安全自定义关键词`HertzBeat`,获取对应`access_token`值。
- 在 HertzBeat 配置接收人参数如下。
【告警通知】->【新增接收人】 ->【选择钉钉机器人通知方式】->【设置钉钉机器人ACCESS_TOKEN】-> 【确定】
@@ -58,7 +58,7 @@ Cloud: **[TanCloud](https://console.tancloud.cn/)**
#### 安装部署 HertzBeat
具体可以参考 [官方文档](https://hertzbeat.apache.org/zh-cn/docs/start/docker-deploy)
具体可以参考 [官方文档](https://hertzbeat.com/zh-cn/docs/start/docker-deploy)
1. Docker 安装 HertzBeat
@@ -20,7 +20,7 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
- 易用友好,无需 `Agent`,全 `WEB` 页面操作,鼠标点一点就能监控告警,无需学习成本。
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` 等方式消息及时送达。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助开发者和团队快速搭建自有监控系统。
@@ -95,7 +95,7 @@ HertzBeat 提供云边协同能力,可以在多个隔离网络部署边缘采
- `-e MANAGER_IP=127.0.0.1` : 配置连接主HertzBeat服务的对外IP。
- `-e MANAGER_PORT=1158` : 配置连接主HertzBeat服务的对外端口,默认1158。
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.apache.org/docs/start/docker-deploy)
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.com/docs/start/docker-deploy)
---
@@ -79,7 +79,7 @@ HertzBeat 赫兹跳动是一个拥有强大自定义监控能力,高性能集
* 易用友好,无需 `Agent`,全 `WEB` 页面操作,鼠标点一点就能监控告警,无需学习成本。
* 将 `Http,Jmx,Ssh,Snmp,Jdbc` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
* 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
* 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
* 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助开发者和团队快速搭建自有监控系统。
@@ -56,7 +56,7 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
- 易用友好,无需 `Agent`,全 `WEB` 页面操作,鼠标点一点就能监控告警,无需学习成本。
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` 等方式消息及时送达。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助开发者和团队快速搭建自有监控系统。
@@ -88,7 +88,7 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
- `-e MANAGER_HOST=127.0.0.1` : 配置连接主HertzBeat服务的对外IP。
- `-e MANAGER_PORT=1158` : 配置连接主HertzBeat服务的对外端口,默认1158。
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.apache.org/docs/start/docker-deploy)
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.com/docs/start/docker-deploy)
---
@@ -33,7 +33,7 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
- 易用友好,无需 `Agent`,全 `WEB` 页面操作,鼠标点一点就能监控告警,无需学习成本。
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助开发者和团队快速搭建自有监控系统。
@@ -65,7 +65,7 @@ keywords: [open source monitoring system, alerting system, Linux monitoring]
- `-e MANAGER_HOST=127.0.0.1` : 配置连接主HertzBeat服务的对外IP。
- `-e MANAGER_PORT=1158` : 配置连接主HertzBeat服务的对外端口,默认1158。
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.apache.org/docs/start/docker-deploy)
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.com/docs/start/docker-deploy)
---
@@ -19,7 +19,7 @@ keywords: [open source monitoring system, alerting system]
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
**Github: <https://github.com/apache/hertzbeat>**
@@ -60,7 +60,7 @@ keywords: [open source monitoring system, alerting system]
- `-e MANAGER_HOST=127.0.0.1` : 配置连接主HertzBeat服务的对外IP。
- `-e MANAGER_PORT=1158` : 配置连接主HertzBeat服务的对外端口,默认1158。
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.apache.org/docs/start/docker-deploy)
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.com/docs/start/docker-deploy)
---
@@ -125,7 +125,7 @@ keywords: [open source monitoring system, alerting system]
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助开发者和团队快速搭建自有监控系统。
@@ -19,7 +19,7 @@ keywords: [open source monitoring system, alerting system]
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
**Github: <https://github.com/apache/hertzbeat>**
@@ -61,7 +61,7 @@ keywords: [open source monitoring system, alerting system]
- `-e MANAGER_HOST=127.0.0.1` : 配置连接主HertzBeat服务的对外IP。
- `-e MANAGER_PORT=1158` : 配置连接主HertzBeat服务的对外端口,默认1158。
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.apache.org/docs/start/docker-deploy)
更多配置详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.com/docs/start/docker-deploy)
---
@@ -31,7 +31,7 @@ HertzBeat 于 2022 年 1 月在 Dromara 开源社区正式开源,经过两年
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 提供强大的状态页构建能力,轻松向用户传达您产品服务的实时状态。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助用户快速搭建自有监控系统。
@@ -11,7 +11,7 @@
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
**Github: <https://github.com/apache/hertzbeat>**
@@ -32,7 +32,7 @@ keywords: [open source, monitoring, alerting]
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 提供强大的状态页构建能力,轻松向用户传达您产品服务的实时状态。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助用户快速搭建自有监控系统。
@@ -374,7 +374,7 @@ keywords: [open source, monitoring, alerting]
```docker run -d -p 1157:1157 -p 1158:1158 --name hertzbeat quay.io/tancloud/hertzbeat```
详细参考 HertzBeat 官网文档 <https://hertzbeat.apache.org/docs>
详细参考 HertzBeat 官网文档 <https://hertzbeat.com/docs>
---
**Github: <https://github.com/apache/hertzbeat>**
@@ -1,193 +0,0 @@
---
title: Apache Hertzbeat 1.7.2 发布公告
author: tomsun28
author_title: tomsun28
author_url: https://github.com/zhangshenghang
author_image_url: https://avatars.githubusercontent.com/u/24788200?s=400&v=4
tags: [opensource, release]
keywords: [open source monitoring system, alerting system, Hertzbeat, release]
---
亲爱的社区小伙伴们,
我们很高兴地宣布 Apache Hertzbeat 1.7.2 版本正式发布!
## Downloads and Documentation
- **Apache Hertzbeat 1.7.2 Download Link**: <https://hertzbeat.apache.org/zh-cn/docs/download>
- **Apache Hertzbeat Documentation**: <https://hertzbeat.apache.org/zh-cn/docs/>
## Major Updates
### New Features and Enhancements
- **云服务告警集成**:支持阿里云 SLS 日志服务告警源 (#3422)、华为云云监控告警源 (#3443)、火山引擎告警源 (#3451)。
- **服务发现增强**:新增 Zookeeper 服务发现支持 (#3377)、Nacos 自动服务发现 (#3324)、支持认证的 HTTP 服务发现采集器 (#3388)。
- **AI 与数据源扩展**:集成 Ollama AI 模型 (#3441)、支持 OpenRouter AI 提供商 (#3439)、提供 GreptimeDB 作为 Grafana 数据源 (#3403)。
- **表达式与数据处理**:支持 sql 和 promql 表达式语法 (#3410)、新增批量导入指标至 VictoriaMetrics 功能 (#3337)。
- **平台兼容性**:新增 Darwin (macOS) 平台兼容支持 (#3431)。
- **监控指标增强**:新增 statusCode 指标数据 (#3446)。
- **更多新功能**
### Bug Fixes
- **告警通知问题**:修复 Uptime Kuma/Zabbix/腾讯云 Webhook URL 错误 (#3351)、飞书通知格式错误 (#3508)。
- **阈值功能异常**:修复 Prometheus 实时阈值不生效问题 (#3434)。
- **监控状态异常**:修复服务发现子监控状态显示错误 (#3340)、监控列表分页显示异常 (#3467)。
- **系统稳定性**:修复自定义监控公告板空指针异常 (#3448)、Jacoco 测试报告生成失败 (#3455)。
- **数据解析问题**:修复 ANTLR4 解析逻辑错误(二元运算符/向量)(#3482, #3488)、告警表达式解析异常 (#3497, #3504)。
- **数据存储优化**:改进 GreptimeDB 存储与查询逻辑 (#3387)。
- **和其它的BUG修复**
### Refactoring and Optimization
- **安全验证增强**:强化 URL 验证(企业微信/Telegram/Slack/Server酱)(#3361-3364)、JNDI 安全验证 (#3358)、插件服务路径验证 (#3375)。
- **架构与存储优化**:更新安全模型 (#3450)、数据库列类型优化(commonAnnotations/alertFingerprints 改为 TEXT(#3463)、JDBC 逻辑调整 (#3500)。
- **开发工具链**:添加 Maven Wrapper (mvnw) (#3430)、依赖库更新 (#3359, #3498)、支持 mvnd 并优化后端构建 (#3491)。
- **可观测性**:默认禁用 OpenTelemetry exporters 防止连接错误 (#3437, #3461)。
- **社区协作**:更新 Issue 模板 (#3421)。
- **和其它的优化**
### Tests and Quality
- **单元测试覆盖**:为 HttpSdCollectImpl 添加单元测试 (#3386)
- **和其它的测试**
### Documentation Enhancements
- **国际化文档**:新增 30+ 组件日文文档(API/CentOS/Cisco 交换机/ClickHouse 等)(#3352, #3376, #3389 等)。
- **告警功能文档**:更新告警阈值配置 (#3399)、告警通知模板 (#3466)、火山引擎告警集成指南 (#3460)。
- **部署与配置**:新增 Grafana 匿名认证配置说明 (#3407)、Rainbond 云一键安装指南 (#3440)。
- **内容修正与优化**:修复时间模板语法错误 (#3378)、精炼中文术语 (#3380, #3383)、更新 Greptime-init 文档 (#3355)。
- **社区生态**:新增贡献者/Committer 简介 (#3357, #3391, #3395)、版本发布博客 (#3449)。
- **更多的文档更新**
## Acknowledgements
感谢以下社区成员的共同努力:
> @pruidong @MasamiYui @tomsun28 @Aias00 @zhangshenghang @zqr10159 @LiuTianyou @LL-LIN @lx1229 @xiaomizhou2 @pwallk
> @bigcyy @yuluo-yx @TJxiaobao @RainBondsongyg @Duansg @Calvin979 @Cyanty
## What's Changed
```markdown
* [bugfix] Fix incorrect webhook URLs for Uptime Kuma, Zabbix, and Tencent Cloud by @bigcyy in https://github.com/apache/hertzbeat/pull/3351
* [doc] japanese api by @Calvin979 in https://github.com/apache/hertzbeat/pull/3352
* [doc] update OS monitor by @MasamiYui in https://github.com/apache/hertzbeat/pull/3353
* [doc](start): update greptime-init documentation by @zqr10159 in https://github.com/apache/hertzbeat/pull/3355
* [doc] new ppmc liutianyou and update qq num by @tomsun28 in https://github.com/apache/hertzbeat/pull/3357
* [bugfix] Incorrect SD sub-monitor status by @MasamiYui in https://github.com/apache/hertzbeat/pull/3340
* [improve] improve url validation for WeComRobotAlertNotifyHandlerImpl by @Aias00 in https://github.com/apache/hertzbeat/pull/3361
* [improve] improve url validation for TelegramBotAlertNotifyHandlerImpl by @Aias00 in https://github.com/apache/hertzbeat/pull/3362
* [improve] improve url validation for SlackAlertNotifyHandlerImpl by @Aias00 in https://github.com/apache/hertzbeat/pull/3363
* [improve] improve url validation for serverChan by @Aias00 in https://github.com/apache/hertzbeat/pull/3364
* [improve] improve jndi validation by @Aias00 in https://github.com/apache/hertzbeat/pull/3358
* update maven dep by @Aias00 in https://github.com/apache/hertzbeat/pull/3359
* [doc] japanese centos by @Calvin979 in https://github.com/apache/hertzbeat/pull/3376
* [doc] fix incorrect time template syntax usercase in doc by @LL-LIN in https://github.com/apache/hertzbeat/pull/3378
* [doc] Add blog by @LiuTianyou in https://github.com/apache/hertzbeat/pull/3379
* [improve] add path validation for pluginservice by @Aias00 in https://github.com/apache/hertzbeat/pull/3375
* [feat] Support Zookeeper Service Discovery by @bigcyy in https://github.com/apache/hertzbeat/pull/3377
* [doc] modify chinese words by @Duansg in https://github.com/apache/hertzbeat/pull/3380
* [Task] Batch import metrics data in victoria-metrics by @MasamiYui in https://github.com/apache/hertzbeat/pull/3337
* [feature] support auto nacos service discovery by @xiaomizhou2 in https://github.com/apache/hertzbeat/pull/3324
* [doc] modify supplement related documentation by @Duansg in https://github.com/apache/hertzbeat/pull/3383
* [doc] japanese cisco switch by @Calvin979 in https://github.com/apache/hertzbeat/pull/3389
* [test] Add unit tests for HttpSdCollectImpl by @xiaomizhou2 in https://github.com/apache/hertzbeat/pull/3386
* [fix](warehouse): improve GreptimeDB data storage and querying by @zqr10159 in https://github.com/apache/hertzbeat/pull/3387
* [doc] japanese clickhouse by @Calvin979 in https://github.com/apache/hertzbeat/pull/3390
* [doc] new contributor and committer, update doc by @tomsun28 in https://github.com/apache/hertzbeat/pull/3391
* [doc] japanese consul sd by @Calvin979 in https://github.com/apache/hertzbeat/pull/3392
* [doc]add new committer blog by @pwallk in https://github.com/apache/hertzbeat/pull/3395
* [doc] japanese coreos by @Calvin979 in https://github.com/apache/hertzbeat/pull/3393
* [doc] japanese dahua by @Calvin979 in https://github.com/apache/hertzbeat/pull/3396
* [doc] japanese Debian by @Calvin979 in https://github.com/apache/hertzbeat/pull/3398
* [improve] http sd collector adds authentication by @Cyanty in https://github.com/apache/hertzbeat/pull/3388
* [doc] japanese deepseek & dm by @Calvin979 in https://github.com/apache/hertzbeat/pull/3400
* [docs] update alert threshold doc by @bigcyy in https://github.com/apache/hertzbeat/pull/3399
* [doc] japanese dns by @Calvin979 in https://github.com/apache/hertzbeat/pull/3404
* [doc] japanese dns sd by @Calvin979 in https://github.com/apache/hertzbeat/pull/3405
* [doc] japanese docker by @Calvin979 in https://github.com/apache/hertzbeat/pull/3408
* [doc] japanese doris_be by @Calvin979 in https://github.com/apache/hertzbeat/pull/3409
* [Doc] Update 1.7.1 by @zhangshenghang in https://github.com/apache/hertzbeat/pull/3411
* [doc] update home doc by @tomsun28 in https://github.com/apache/hertzbeat/pull/3418
* [doc] Update anonymous user auth configuration of the grafana dashboard document by @Cyanty in https://github.com/apache/hertzbeat/pull/3407
* [doc] japanese doris_fe by @Calvin979 in https://github.com/apache/hertzbeat/pull/3416
* [infra]: Update issue tmpl by @yuluo-yx in https://github.com/apache/hertzbeat/pull/3421
* [feature]Make GreptimeDB as a grafana data source by @zqr10159 in https://github.com/apache/hertzbeat/pull/3403
* [feat] support sql("...") and promql("...") expressions including SQL condition parsing by @bigcyy in https://github.com/apache/hertzbeat/pull/3410
* [doc] japanese dynamic_tp by @Calvin979 in https://github.com/apache/hertzbeat/pull/3419
* [doc] japanese elasticsearch by @Calvin979 in https://github.com/apache/hertzbeat/pull/3423
* [feature]Support Alibaba Cloud 'Simple Log Service(SLS)' alert source by @Duansg in https://github.com/apache/hertzbeat/pull/3422
* [Improve] add mvnw by @zhangshenghang in https://github.com/apache/hertzbeat/pull/3430
* [doc] japanese emqx by @Calvin979 in https://github.com/apache/hertzbeat/pull/3433
* [improvement] disable default OpenTelemetry exporters to prevent connection errors by @bigcyy in https://github.com/apache/hertzbeat/pull/3437
* [bugfix] Fix the issue where Prometheus RealTime Threshold is not eff… by @Duansg in https://github.com/apache/hertzbeat/pull/3434
* [feat] add support for ollama and update docs by @bigcyy in https://github.com/apache/hertzbeat/pull/3441
* [release] add support for darwin by @lx1229 in https://github.com/apache/hertzbeat/pull/3431
* [feature] Support Huawei Cloud `Cloud Eye` alert source by @Duansg in https://github.com/apache/hertzbeat/pull/3443
* [doc] japanese euleros by @Calvin979 in https://github.com/apache/hertzbeat/pull/3442
* docs: Add one-click installation for Rainbond Cloud by @RainBondsongyg in https://github.com/apache/hertzbeat/pull/3440
* [feat] add support for OpenRouter AI provider by @bigcyy in https://github.com/apache/hertzbeat/pull/3439
* [doc] japanese flink by @Calvin979 in https://github.com/apache/hertzbeat/pull/3447
* [security] update hertzbeat security model by @tomsun28 in https://github.com/apache/hertzbeat/pull/3450
* [feature] support volcengine alert source by @LiuTianyou in https://github.com/apache/hertzbeat/pull/3451
* [doc] add publish version 1.7.1 blog by @tomsun28 in https://github.com/apache/hertzbeat/pull/3449
* [doc] japanese flink on yarn by @Calvin979 in https://github.com/apache/hertzbeat/pull/3452
* [doc] japanese freebsd by @Calvin979 in https://github.com/apache/hertzbeat/pull/3456
* [improvement] disable default OpenTelemetry exporters to prevent connection errors by @bigcyy in https://github.com/apache/hertzbeat/pull/3461
* [doc] add doc for integrate volcengine alerts by @LiuTianyou in https://github.com/apache/hertzbeat/pull/3460
* [Fix] fix custom monitoring bulletin `NullPointerException` by @Duansg in https://github.com/apache/hertzbeat/pull/3448
* [fix] fix jacoco can not generate test reports. by @Duansg in https://github.com/apache/hertzbeat/pull/3455
* [doc] Alert notification template by @MasamiYui in https://github.com/apache/hertzbeat/pull/3466
* [doc] japanese greenplum by @Calvin979 in https://github.com/apache/hertzbeat/pull/3468
* [improvement] change column definitions for commonAnnotations and alertFingerprints to TEXT type by @bigcyy in https://github.com/apache/hertzbeat/pull/3463
* [fix] Fix `Monitors` paging display. by @Duansg in https://github.com/apache/hertzbeat/pull/3467
* [doc] japanese greptime by @Calvin979 in https://github.com/apache/hertzbeat/pull/3469
* [doc] japanese h3c switch by @Calvin979 in https://github.com/apache/hertzbeat/pull/3471
* [feature] Add statusCode metrics data. by @Duansg in https://github.com/apache/hertzbeat/pull/3446
* [doc] japanese hadoop by @Calvin979 in https://github.com/apache/hertzbeat/pull/3476
* [docs](webhook): update Chinese documentation for alert integration by @zqr10159 in https://github.com/apache/hertzbeat/pull/3478
* [doc] japanese hbase master by @Calvin979 in https://github.com/apache/hertzbeat/pull/3477
* [doc] japanese hbase region server by @Calvin979 in https://github.com/apache/hertzbeat/pull/3479
* [doc] japanese hdfs datanode by @Calvin979 in https://github.com/apache/hertzbeat/pull/3487
* [fix] antlr4 `vectors and` parse semantic fixes and optimizations by @Duansg in https://github.com/apache/hertzbeat/pull/3482
* [ci]: add mvnd support and update backend build by @zqr10159 in https://github.com/apache/hertzbeat/pull/3491
* [doc] japanese hdfs namenode by @Calvin979 in https://github.com/apache/hertzbeat/pull/3490
* [doc] japanese hertzbeat by @Calvin979 in https://github.com/apache/hertzbeat/pull/3492
* [fix] Fix antlr4 parsing of `or` and `unless` logical and set binary operators by @Duansg in https://github.com/apache/hertzbeat/pull/3488
* [doc] japanese hertzbeat token by @Calvin979 in https://github.com/apache/hertzbeat/pull/3493
* [feat] update_mvnd_version by @Aias00 in https://github.com/apache/hertzbeat/pull/3498
* add:a small jdbc modified. by @TJxiaobao in https://github.com/apache/hertzbeat/pull/3500
* fixed:a minor issue change by @TJxiaobao in https://github.com/apache/hertzbeat/pull/3428
* [bugfix] Fix incorrect expression parsing in alert setting component by @bigcyy in https://github.com/apache/hertzbeat/pull/3497
* [bugfix] Correctly parse binary comparison expressions by @bigcyy in https://github.com/apache/hertzbeat/pull/3504
* [bugfix]Fixed an error in the format of the flying book notification by @pruidong in https://github.com/apache/hertzbeat/pull/3508
* [release] release new version 1.7.2 by @tomsun28 in https://github.com/apache/hertzbeat/pull/3510
```
## Apache Hertzbeat
**仓库地址:**
<https://github.com/apache/hertzbeat>
**网址:**
<https://hertzbeat.apache.org/>
**Apache Hertzbeat 下载地址:**
<https://hertzbeat.apache.org/zh-cn/docs/download>
**Apache Hertzbeat Docker 镜像版本:**
> Apache HertzBeat 为每个版本制作了 Docker 镜像. 你可以从 Docker Hub 拉取使用.
- HertzBeat <https://hub.docker.com/r/apache/hertzbeat>
- HertzBeat Collector <https://hub.docker.com/r/apache/hertzbeat-collector>
**Apache Hertzbeat 开源社区如何参与?**
<https://hertzbeat.apache.org/zh-cn/docs/community/contribution>
@@ -1,46 +0,0 @@
---
title: 热烈欢迎 HertzBeat 小伙伴新晋社区 Committer!
author: bigcyy
author_title: Yang Chen
author_url: https://github.com/bigcyy
author_image_url: https://avatars.githubusercontent.com/u/73413979
tags: [opensource, practice]
keywords:
[
open source monitoring system,
alerting system,
Apache,
Apache Committer,
Hertzbeat,
]
---
大家好,我是陈阳,目前是重庆邮电大学的一名研究生。非常荣幸能得到 Apache HertzBeat 社区的认可与邀请,正式成为项目的 Committer,这标志着我真正意义上的开源之旅的开启!
## 我的开源初探
早在本科时期,我就接触过开源,那时曾基于开源的 [Mirai](https://github.com/mamoe/mirai) 框架开发了一个[疫情防控 QQ 机器人](https://github.com/bigcyy/GroupNotifier)。然而,那更多是停留在使用层面。
大三时,我尝试独立开源了名为 [customized_chat](https://github.com/bigcyy/customized-chat) 的 AI 项目,这算是我迈出的“开源”第一步。
但这些经历都是独自摸索,我深感这并非真正的开源,因为它未能建立起一个完整的社区生态。
## 结缘 HertzBeat:真正意义的开源实践
为了更深入地参与开源,我开始寻找合适的开源活动,并因此结识了 HertzBeat。这对我而言,是真正意义上的开源之旅。在这里,我不仅学到了扎实的技术开发,更领略了成熟的社区生态。我深刻理解了 “Apache Way” 的精髓——社区成就项目,而非项目成就社区。
我最初是通过 GSoCGoogle Summer of Code)了解到 HertzBeat 的,当时社区关于开发监控 MCP 的提案深深吸引了我。于是,我主动联系了 Tom ,并正式开始参与社区活动。Tom 非常热情,整个社区也异常活跃。我清晰地记得我的第一个 PR(Pull Request),当时甚至与一位用户在 Issue 中进行了在线测试,这对我来说是一次相当独特的经历。尽管最终未能入选 GSoC,但在此期间,我已深度参与到社区中,并充分感受到了它的卓越之处。
## 开源带来的成长与收获
参与开源,确实让我的能力得到了显著提升。通过阅读 HertzBeat 的架构设计并积极参与社区讨论,我积累了许多宝贵的经验,例如:
- 前沿技术: 我深入了解了监控系统的设计与实现,并在项目中实践了并发编程、分布式等核心技术。
- 实战能力: 通过解决实际问题和参与代码贡献,我成功地将理论知识转化为了实际操作能力。
- 社区文化体验: 我亲身感受了“Apache Way”的独特魅力,并与来自世界各地的开发者们进行了深入交流与学习。
我的经历让我深信,开源不仅仅是编写代码,更是一个学习、成长和贡献的绝佳平台。
如果你也对技术充满热情,渴望在实践中提升自我,并希望体验真正意义上的社区协作,那么 Apache HertzBeat 社区绝对是你的不二选择!
## 最后
我衷心感谢 [Tom](https://github.com/tomsun28)、[Shenghang](https://github.com/zhangshenghang)、[Logic](https://github.com/zqr10159) 等社区的小伙伴们,感谢你们对我的代码进行细致的 Review 与悉心指导。希望 Apache HertzBeat 能够越来越好!
@@ -60,14 +60,14 @@ The following table is filled according to the [Apache Maturity Model](https://c
### Community
| **ID** | **Description** | **Status** |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **CO10** | The project has a well-known homepage that points to all the information required to operate according to this maturity model. | **YES** The [official website](https://hertzbeat.apache.org/) includes all information user need to run Apache HertzBeat. |
| **CO20** | The community welcomes contributions from anyone who acts in good faith and in a respectful manner, and who adds value to the project. | **Yes** We provide contributing guides for every component. And we also have a [general contributing guide](https://hertzbeat.apache.org/docs/community/contribution) |
| **CO30** | Contributions include source code, documentation, constructive bug reports, constructive discussions, marketing and generally anything that adds value to the project. | **YES** All good contributions including code and non-code are welcomed. |
| **CO40** | The community strives to be meritocratic and gives more rights and responsibilities to contributors who, over time, add value to the project. | **YES** The community has elected 3 new PPMC members and 13 new committers so far. |
| **CO50** | The project documents how contributors can earn more rights such as commit access or decision power, and applies these principles consistently. | **YES** The community has clear docs on nominating committers and PPMC members |
| **CO60** | The community operates based on consensus of its members (see CS10) who have decision power. Dictators, benevolent or not, are not welcome in Apache projects. | **YES** All decisions are made after vote by community members. |
| **ID** | **Description** | **Status** |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **CO10** | The project has a well-known homepage that points to all the information required to operate according to this maturity model. | **YES** The [official website](https://hertzbeat.apache.org/) includes all information user need to run Apache HertzBeat. |
| **CO20** | The community welcomes contributions from anyone who acts in good faith and in a respectful manner, and who adds value to the project. | **Yes** We provide contributing guides for every component. And we also have a [general contributing guide](https://hertzbeat.apache.org/docs/community/contribution) |
| **CO30** | Contributions include source code, documentation, constructive bug reports, constructive discussions, marketing and generally anything that adds value to the project. | **YES** All good contributions including code and non-code are welcomed. |
| **CO40** | The community strives to be meritocratic and gives more rights and responsibilities to contributors who, over time, add value to the project. | **YES** The community has elected 2 new PPMC members and 12 new committers so far. |
| **CO50** | The project documents how contributors can earn more rights such as commit access or decision power, and applies these principles consistently. | **YES** The community has clear docs on nominating committers and PPMC members |
| **CO60** | The community operates based on consensus of its members (see CS10) who have decision power. Dictators, benevolent or not, are not welcome in Apache projects. | **YES** All decisions are made after vote by community members. |
| **CO70** | The project strives to answer user questions in a timely manner. | **YES** We use <dev@hertzbeat.apache.org>, [GitHub issue](https://github.com/apache/hertzbeat/issues) and [GitHub discussion](https://github.com/apache/hertzbeat/discussions) to do this in a timely manner. |
### Consensus
@@ -30,15 +30,6 @@ sidebar_label: 常见问题
5. 配置http api监控,用于进行业务接口探测,确保业务可以用,另外接口有进行token鉴权校验,"AuthorizationBearer eyJhbGciOiJIUzI1....",配置后测试,提示“StatusCode 401”。服务端应用收到的token为"AuthorizationBearer%20eyJhbGciOiJIUzI1....",hertzbeat对空格进行转义为“%20”,服务器没有转义导致鉴权失败,建议转义功能作为可选项。
6. 单个采集器的任务上限是多少?
> 具体上限参数
核心线程数: Math.max(2, Runtime.getRuntime().availableProcessors()) - 至少2个线程,或等于CPU核心数。
最大线程数: Runtime.getRuntime().availableProcessors() * 16 - CPU核心数的16倍。
> 上限完全取决于服务器的CPU核心数。例如,在8核CPU的服务器上,最大可同时处理 8 × 16 = 128 个采集任务。当超过这个数量时就会触发该错误消息。这是一个动态配置,会根据运行环境的硬件规格自动调整。
> 当运行时超出最大线程数会报错提示"the worker pool is full, reject this metrics taskput in queue again"。
> 此时建议配置新的采集器,并设置为public模式,hertzbeat会自动将任务分配给其他采集器,不会因为单个采集器任务上限而报错。
### Docker部署常见问题
1. **MYSQL,TDENGINE和HertzBeat都Docker部署在同一主机上,HertzBeat使用localhost或127.0.0.1连接数据库失败**
@@ -20,7 +20,7 @@ slug: /
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 提供强大的状态页构建能力,轻松向用户传达您产品服务的实时状态。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助开发者和团队快速搭建自有监控系统。
@@ -27,7 +27,7 @@ slug: /
- 将 `Http, Jmx, Ssh, Snmp, Jdbc, Prometheus` 等协议规范可配置化,只需在浏览器配置监控模板 `YML` 就能使用这些协议去自定义采集想要的指标。您相信只需简单配置即可快速适配一款 `K8s``Docker` 等新的监控类型吗?
- 兼容 `Prometheus` 的系统生态并且更多,只需页面操作就可以监控 `Prometheus` 所能监控的。
- 高性能,支持多采集器集群横向扩展,支持多隔离网络监控,云边协同。
- 灵活的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 自由的告警阈值规则,`邮件` `Discord` `Slack` `Telegram` `钉钉` `微信` `飞书` `短信` `Webhook` `Server酱` 等方式消息及时送达。
- 提供强大的状态页构建能力,轻松向用户传达您产品服务的实时状态。
> `HertzBeat`的强大自定义,多类型支持,高性能,易扩展,低耦合,希望能帮助开发者和团队快速搭建自有监控系统。
+5 -15
View File
@@ -86,11 +86,6 @@
"githubId": "30208283",
"gitUrl": "https://github.com/LiuTianyou",
"name": "LiuTianyou"
},
{
"githubId": "25810623",
"gitUrl": "https://github.com/Aias00",
"name": "Aias00"
}
],
"committer" : [
@@ -119,6 +114,11 @@
"gitUrl": "https://github.com/yuluo-yx",
"name": "Shown"
},
{
"githubId": "25810623",
"gitUrl": "https://github.com/Aias00",
"name": "Aias00"
},
{
"githubId": "61108539",
"gitUrl": "https://github.com/zuobiao-zhou",
@@ -133,16 +133,6 @@
"githubId": "69385076",
"gitUrl": "https://github.com/pwallk",
"name": "Kang Li"
},
{
"githubId": "22274133",
"gitUrl": "https://github.com/masamiyui",
"name": "Yijun Yin"
},
{
"githubId": "73413979",
"gitUrl": "https://github.com/bigcyy",
"name": "Yang Chen"
}
]
}
@@ -125,9 +125,6 @@ warehouse:
url: http://victoria-metrics:8428
username: root
password: root
insert:
buffer-size: 100
flush-interval: 3
# store real-time metrics data, enable only one below
real-time:
memory:
@@ -124,9 +124,6 @@ warehouse:
url: http://victoria-metrics:8428
username: root
password: root
insert:
buffer-size: 100
flush-interval: 3
# store real-time metrics data, enable only one below
real-time:
memory:
@@ -100,7 +100,7 @@
<div class="tp-feature__content">
<h4 class="tp-feature__title">高性能与自定义</h4>
<p
>将 Http,Jmx,Ssh,Snmp,Jdbc 等协议规范可配置模版化,只需在线配置YML就可自定义监控指标; 灵活的告警阈值规则,消息及时送达</p
>将 Http,Jmx,Ssh,Snmp,Jdbc 等协议规范可配置模版化,只需在线配置YML就可自定义监控指标; 自由的告警阈值规则,消息及时送达</p
>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More