Compare commits

...
22 changed files with 376 additions and 116 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ jobs:
- uses: ./script/ci/github-actions/setup-deps
- name: Build with Maven
run: mvn clean -B package -Prelease -Dmaven.test.skip=false --file pom.xml
run: mvnd clean -B package -Prelease -Dmaven.test.skip=false --file pom.xml
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1
@@ -115,92 +115,51 @@ public class AlertExpressionEvalVisitor extends AlertExpressionBaseVisitor<List<
List<Map<String, Object>> leftOperand = visit(ctx.left);
List<Map<String, Object>> rightOperand = visit(ctx.right);
Map<String, Object> leftMap = null;
boolean leftMatch = false;
Map<String, Object> rightMap = null;
boolean rightMatch = false;
for (Map<String, Object> item : leftOperand) {
if (leftMap == null) {
leftMap = item;
// build a hashMap of the left-hand label collection
Map<String, Map<String, Object>> leftLabelMap = leftOperand.stream()
.filter(item -> item.get(VALUE) != null)
.collect(Collectors.toMap(this::labelKey, HashMap::new, (k1, k2) -> k1));
// first add all the non-empty items on the left side
List<Map<String, Object>> results = new ArrayList<>(leftLabelMap.values());
// add the term that has a value on the right side and not on the left side
for (Map<String, Object> rightItem : rightOperand) {
Object rightVal = rightItem.get(VALUE);
if (rightVal == null) {
continue;
}
if (item.get(VALUE) != null) {
leftMap = item;
leftMatch = true;
break;
String key = labelKey(rightItem);
if (!leftLabelMap.containsKey(key)) {
results.add(new HashMap<>(rightItem));
}
}
for (Map<String, Object> item : rightOperand) {
if (rightMap == null) {
rightMap = item;
}
if (item.get(VALUE) != null) {
rightMap = item;
rightMatch = true;
break;
}
}
if (leftMatch && rightMatch) {
rightMap.putAll(leftMap);
return new LinkedList<>(List.of(rightMap));
} else if (leftMatch) {
return new LinkedList<>(List.of(leftMap));
} else if (rightMatch) {
return new LinkedList<>(List.of(rightMap));
} else {
if (leftMap != null && rightMap != null) {
rightMap.putAll(leftMap);
return new LinkedList<>(List.of(rightMap));
} else if (leftMap != null) {
return new LinkedList<>(List.of(leftMap));
} else if (rightMap != null) {
return new LinkedList<>(List.of(rightMap));
}
}
return new LinkedList<>();
return results;
}
@Override
public List<Map<String, Object>> visitUnlessExpr(AlertExpressionParser.UnlessExprContext ctx) {
List<Map<String, Object>> leftOperand = visit(ctx.left);
List<Map<String, Object>> rightOperand = visit(ctx.right);
Map<String, Object> leftMap = null;
boolean leftMatch = false;
Map<String, Object> rightMap = null;
boolean rightMatch = false;
for (Map<String, Object> item : leftOperand) {
if (leftMap == null) {
leftMap = item;
List<Map<String, Object>> results = new ArrayList<>();
// build a hash set of the right-side tag collection
Set<String> rightLabelSet = rightOperand.stream()
.filter(item -> item.get(VALUE) != null)
.map(this::labelKey)
.collect(Collectors.toSet());
// iterate over the left side, O(1) match
for (Map<String, Object> leftItem : leftOperand) {
Object leftVal = leftItem.get(VALUE);
if (leftVal == null) {
continue;
}
if (item.get(VALUE) != null) {
leftMap = item;
leftMatch = true;
break;
if (!rightLabelSet.contains(labelKey(leftItem))) {
results.add(new HashMap<>(leftItem));
}
}
for (Map<String, Object> item : rightOperand) {
if (rightMap == null) {
rightMap = item;
}
if (item.get(VALUE) != null) {
rightMap = item;
rightMatch = true;
break;
}
}
if (leftMatch && !rightMatch) {
return new LinkedList<>(List.of(leftMap));
} else {
if (leftMap != null) {
leftMap.put(VALUE, null);
return new LinkedList<>(List.of(leftMap));
} else {
if (rightMap != null) {
rightMap.put(VALUE, null);
return new LinkedList<>(List.of(rightMap));
}
}
}
return new LinkedList<>();
return results;
}
@Override
@@ -24,12 +24,14 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
/**
@@ -240,11 +242,187 @@ class AlertExpressionEvalVisitorTest {
assertEquals(10.0, result.get(0).get("__value__"));
}
@Test
void testUnlessOpPromql() {
String promql = "http_server_requests_seconds_count > 10 unless http_server_requests_seconds_max > 0";
Map<String, Object> countValue1 = new HashMap<>() {
{
put("exception", "none");
put("instance", "host.docker.internal:8989");
put("__value__", 1307);
put("method", "GET");
put("__name__", "http_server_requests_seconds_count");
put("__timestamp__", "1.750320922467E9");
put("error", "none");
put("job", "spring-boot-app");
put("uri", "/actuator/prometheus");
put("outcome", "SUCCESS");
put("status", "200");
}
};
Map<String, Object> maxValue1 = new HashMap<>() {
{
put("exception", "none");
put("instance", "host.docker.internal:8989");
put("__value__", 10.007799125);
put("method", "GET");
put("__name__", "http_server_requests_seconds_max");
put("__timestamp__", "1.750320922467E9");
put("error", "none");
put("job", "spring-boot-app");
put("uri", "/actuator/health");
put("outcome", "SUCCESS");
put("status", "200");
}
};
when(mockExecutor.execute("http_server_requests_seconds_count")).thenReturn(List.of(countValue1));
when(mockExecutor.execute("http_server_requests_seconds_max")).thenReturn(List.of(maxValue1));
List<Map<String, Object>> result = evaluate(promql);
assertEquals(1, result.size());
assertEquals(1307, result.get(0).get("__value__"));
maxValue1.put("uri", "/actuator/prometheus");
result = evaluate(promql);
assertEquals(0, result.size());
Map<String, Object> sumValue1 = new HashMap<>() {
{
put("exception", "none");
put("instance", "host.docker.internal:8989");
put("__value__", 20.018);
put("method", "GET");
put("__name__", "http_server_requests_seconds_sum");
put("__timestamp__", "1.750320922467E9");
put("error", "none");
put("job", "spring-boot-app");
put("uri", "/**");
put("outcome", "SUCCESS");
put("status", "200");
}
};
maxValue1.put("uri", "/actuator/health");
when(mockExecutor.execute("http_server_requests_seconds_sum")).thenReturn(List.of(sumValue1));
promql = "(http_server_requests_seconds_count > 10 unless http_server_requests_seconds_max > 0) unless http_server_requests_seconds_sum > 10";
result = evaluate(promql);
assertEquals(1, result.size());
assertEquals(1307, result.get(0).get("__value__"));
}
@Test
void testOrOpPromql() {
String promql = "http_server_requests_seconds_count > 10 or jvm_threads_states_threads > 0";
Map<String, Object> countValue1 = new HashMap<>() {
{
put("exception", "none");
put("instance", "host.docker.internal:8989");
put("__value__", 1307);
put("method", "GET");
put("__name__", "http_server_requests_seconds_count");
put("__timestamp__", "1.750320922467E9");
put("error", "none");
put("job", "spring-boot-app");
put("uri", "/actuator/prometheus");
put("outcome", "SUCCESS");
put("status", "200");
}
};
Map<String, Object> countValue2 = new HashMap<>() {
{
put("exception", "none");
put("instance", "host.docker.internal:8989");
put("__value__", 16);
put("method", "GET");
put("__name__", "http_server_requests_seconds_count");
put("__timestamp__", "1.750320922467E9");
put("error", "none");
put("job", "spring-boot-app");
put("uri", "/**");
put("outcome", "SUCCESS");
put("status", "200");
}
};
Map<String, Object> countValue3 = new HashMap<>() {
{
put("exception", "none");
put("instance", "host.docker.internal:8989");
put("__value__", 7);
put("method", "GET");
put("__name__", "http_server_requests_seconds_count");
put("__timestamp__", "1.750320922467E9");
put("error", "none");
put("job", "spring-boot-app");
put("uri", "/actuator/health");
put("outcome", "SUCCESS");
put("status", "200");
}
};
Map<String, Object> threadsValue1 = new HashMap<>() {
{
put("instance", "host.docker.internal:8989");
put("__value__", 10.007799125);
put("__name__", "jvm_threads_states_threads");
put("__timestamp__", "1.750320922467E9");
put("job", "spring-boot-app");
put("state=", "runnable");
}
};
Map<String, Object> threadsValue2 = new HashMap<>() {
{
put("instance", "host.docker.internal:8989");
put("__value__", 1);
put("__name__", "jvm_threads_states_threads");
put("__timestamp__", "1.750320922467E9");
put("job", "spring-boot-app");
put("state=", "timed-waiting");
}
};
Map<String, Object> threadsValue3 = new HashMap<>() {
{
put("instance", "host.docker.internal:8989");
put("__value__", 19.02);
put("__name__", "jvm_threads_states_threads");
put("__timestamp__", "1.750320922467E9");
put("job", "spring-boot-app");
put("state=", "waiting");
}
};
when(mockExecutor.execute("http_server_requests_seconds_count")).thenReturn(List.of(countValue1, countValue2, countValue3));
when(mockExecutor.execute("jvm_threads_states_threads")).thenReturn(List.of(threadsValue1, threadsValue2, threadsValue3));
List<Map<String, Object>> result = evaluate(promql);
assertEquals(5, result.size());
assertTrue(result.stream().allMatch(t -> null != t.get("__value__")));
when(mockExecutor.execute("jvm_threads_states_threads")).thenReturn(new ArrayList<>());
result = evaluate(promql);
assertEquals(2, result.size());
assertTrue(result.stream().allMatch(t -> null != t.get("__value__")));
assertEquals(1307, result.get(0).get("__value__"));
when(mockExecutor.execute("http_server_requests_seconds_count")).thenReturn(new ArrayList<>());
when(mockExecutor.execute("jvm_threads_states_threads")).thenReturn(List.of(threadsValue1, threadsValue2, threadsValue3));
result = evaluate(promql);
assertEquals(3, result.size());
assertTrue(result.stream().allMatch(t -> null != t.get("__value__")));
assertEquals(10.007799125, result.get(0).get("__value__"));
}
@Test
void testMultipleUnlessConditions() {
when(mockExecutor.execute("metric1")).thenReturn(List.of(new HashMap<>(Map.of("__value__", 40.0))));
when(mockExecutor.execute("metric2")).thenReturn(List.of(new HashMap<>(Map.of("__value__", 50.0))));
when(mockExecutor.execute("metric3")).thenReturn(List.of(new HashMap<>(Map.of("__value__", 60.0))));
when(mockExecutor.execute("metric1")).thenReturn(List.of(new HashMap<>(Map.of("job", "api", "__value__", 40.0))));
when(mockExecutor.execute("metric2")).thenReturn(List.of(new HashMap<>(Map.of("job", "web", "__value__", 50.0))));
when(mockExecutor.execute("metric3")).thenReturn(List.of(new HashMap<>(Map.of("job", "api", "__value__", 60.0))));
when(mockExecutor.execute("select cpu_usage from metrics where service = 'web'")).thenReturn(
List.of(new HashMap<>(Map.of("__value__", 40.0))));
when(mockExecutor.execute("select memory_usage from metrics where service = 'db'")).thenReturn(
@@ -252,15 +430,13 @@ class AlertExpressionEvalVisitorTest {
when(mockExecutor.execute("select disk_usage from metrics where service = 'cache'")).thenReturn(
List.of(new HashMap<>(Map.of("__value__", 60.0))));
// promql
List<Map<String, Object>> result = evaluate("metric1 > 30 unless metric2 > 45 unless metric3 < 70");
assertEquals(1, result.size());
assertNull(result.get(0).get("__value__"));
List<Map<String, Object>> result = evaluate("(metric1 > 30 unless metric2 > 45) unless metric3 > 50");
assertEquals(0, result.size());
// sql
result = evaluate("(select cpu_usage from metrics where service = 'web') > 30"
+ " unless (select memory_usage from metrics where service = 'db') > 45"
+ " unless (select disk_usage from metrics where service = 'cache') < 70");
assertEquals(1, result.size());
assertNull(result.get(0).get("__value__"));
result = evaluate("((select cpu_usage from metrics where service = 'web') > 30"
+ " unless (select memory_usage from metrics where service = 'db') > 55)"
+ " unless (select disk_usage from metrics where service = 'cache') > 50");
assertEquals(0, result.size());
}
@Test
@@ -392,8 +392,7 @@ class DataSourceServiceTest {
dataSourceService.setExecutors(List.of(mockExecutor));
List<Map<String, Object>> result = dataSourceService.calculate("promql", "node_cpu_seconds_total{mode=\"user\"} > 250 or node_cpu_seconds_total{mode=\"idle\"} < 20");
assertEquals(1, result.size());
assertNull(result.get(0).get("__value__"));
assertEquals(0, result.size());
}
@Test
@@ -414,8 +413,7 @@ class DataSourceServiceTest {
dataSourceService.setExecutors(List.of(mockExecutor));
List<Map<String, Object>> result = dataSourceService.calculate("promql", "node_cpu_seconds_total{mode=\"user\"} > 50 or node_cpu_seconds_total{mode=\"idle\"} < 320");
assertEquals(1, result.size());
assertNotNull(result.get(0).get("__value__"));
assertEquals(4, result.size());
}
@Test
@@ -436,8 +434,8 @@ class DataSourceServiceTest {
dataSourceService.setExecutors(List.of(mockExecutor));
List<Map<String, Object>> result = dataSourceService.calculate("promql", "node_cpu_seconds_total{mode=\"user\"} > 50 unless node_cpu_seconds_total{mode=\"idle\"} < 320");
assertEquals(1, result.size());
assertNull(result.get(0).get("__value__"));
assertEquals(2, result.size());
assertEquals(100.0, result.get(0).get("__value__"));
}
@Test
@@ -458,8 +456,8 @@ class DataSourceServiceTest {
dataSourceService.setExecutors(List.of(mockExecutor));
List<Map<String, Object>> result = dataSourceService.calculate("promql", "node_cpu_seconds_total{mode=\"user\"} > 50 unless node_cpu_seconds_total{mode=\"idle\"} < 20");
assertEquals(1, result.size());
assertNotNull(result.get(0).get("__value__"));
assertEquals(2, result.size());
assertEquals(100.0, result.get(0).get("__value__"));
}
@Test
@@ -480,8 +478,7 @@ class DataSourceServiceTest {
dataSourceService.setExecutors(List.of(mockExecutor));
List<Map<String, Object>> result = dataSourceService.calculate("promql", "node_cpu_seconds_total{mode=\"user\"} > 250 unless node_cpu_seconds_total{mode=\"idle\"} < 20");
assertEquals(1, result.size());
assertNull(result.get(0).get("__value__"));
assertEquals(0, result.size());
}
@Test
@@ -474,7 +474,7 @@ metrics:
i18n:
zh-CN: 已使用内存
en-US: Used
ja-JP: 使用済みメモリ
ja-JP: 使用済みメモリ
units:
- committed=B->MB
- init=B->MB
@@ -415,7 +415,7 @@ metrics:
i18n:
zh-CN: 剩余可用内存
en-US: Available Memory
ja-JP: 使用可能メモリ
ja-JP: 使用可能メモリ
- field: usage
type: 0
unit: '%'
@@ -170,6 +170,7 @@ params:
name:
zh-CN: 请求BODY
en-US: BODY
ja-JP: ボディ
# type-param field type(most mapping the html input type)
type: textarea
# 参数输入框提示信息
@@ -73,7 +73,6 @@ params:
# required-true or false
required: false
# default value
# 默认值
defaultValue: 6000
# field-param field key
- field: reuseConnection
@@ -416,7 +415,7 @@ metrics:
i18n:
zh-CN: 剩余可用内存
en-US: Available Memory
ja-JP: 使用可能メモリ
ja-JP: 使用可能メモリ
- field: usage
type: 0
unit: '%'
@@ -415,7 +415,7 @@ metrics:
i18n:
zh-CN: 剩余可用内存
en-US: Available Memory
ja-JP: 使用可能メモリ
ja-JP: 使用可能メモリ
- field: usage
type: 0
unit: '%'
@@ -453,7 +453,7 @@ metrics:
zh-CN: 剩余可用内存
zh-TW: 剩餘可用內存
en-US: Available Memory
ja-JP: 使用可能メモリ
ja-JP: 使用可能メモリ
- field: usage
type: 0
unit: '%'
@@ -414,7 +414,7 @@ metrics:
i18n:
zh-CN: 剩余可用内存
en-US: Available Memory
ja-JP: 使用可能メモリ
ja-JP: 使用可能メモリ
- field: usage
type: 0
unit: '%'
@@ -289,14 +289,14 @@ metrics:
i18n:
zh-CN: 可用内存
en-US: available memory
ja-JP: 使用可能メモリ
ja-JP: 使用可能メモリ
type: 0
unit: MB
- field: used_memory
i18n:
zh-CN: 已用内存
en-US: used memory
ja-JP: 使用済みメモリ
ja-JP: 使用済みメモリ
type: 0
unit: MB
- field: memory_usage
@@ -316,7 +316,7 @@ metrics:
i18n:
zh-CN: 可使用CPU数
en-US: cpus number
ja-JP: 使用可能CPUコア数
ja-JP: 使用可能CPUコア数
type: 0
- field: cpu_usage
i18n:
@@ -211,7 +211,7 @@ metrics:
i18n:
zh-CN: 队列剩余容量
en-US: queue remaining capacity
ja-JP: 使用可能キュー容量
ja-JP: 使用可能キュー容量
type: 0
unit: MB
- field: active_count
@@ -415,7 +415,7 @@ metrics:
i18n:
zh-CN: 剩余可用内存
en-US: Available Memory
ja-JP: 使用可能メモリ
ja-JP: 使用可能メモリ
- field: usage
type: 0
unit: '%'
@@ -158,7 +158,7 @@ metrics:
i18n:
zh-CN: 已用插槽数
en-US: Slots Used
ja-JP: 使用済みスロット数
ja-JP: 使用済みスロット数
- field: task_total # task count
type: 0
i18n:
@@ -409,7 +409,7 @@ metrics:
i18n:
zh-CN: 可用内存
en-US: Available Memory
ja-JP: 使用可能メモリ
ja-JP: 使用可能メモリ
- field: usage
type: 0
unit: '%'
@@ -161,7 +161,7 @@ metrics:
i18n:
zh-CN: 名称
en-US: name
ja-JP: キー
ja-JP: 名前
type: 1
label: true
- field: value
@@ -196,7 +196,7 @@ metrics:
i18n:
zh-CN: 已使用内存
en-US: Used
ja-JP: 使用済みメモリ
ja-JP: 使用済みメモリ
units:
- committed=B->MB
- init=B->MB
@@ -258,7 +258,7 @@ metrics:
i18n:
zh-CN: 已使用内存
en-US: Used
ja-JP: 使用済みメモリ
ja-JP: 使用済みメモリ
aliasFields:
- Usage->committed
- Usage->init
@@ -21,11 +21,13 @@ app: hdfs_namenode
name:
zh-CN: Apache HDFS NameNode
en-US: Apache HDFS NameNode
ja-JP: Apache HDFS NameNode
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 对 HDFS NameNode 节点监控指标进行监控。<br>您可以点击 “<i>新建 Apache HDFS NameNode</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: Hertzbeat monitors the HDFS NameNode metrics. <br>You can click "<i>New Apache HDFS NameNode</i>" to configure, or select "<i>More Actions</i>" to import an existing configuration.
zh-TW: Hertzbeat 對 HDFS NameNode 節點監控指標進行監控。<br>您可以點擊 “<i>新建 Apache HDFS NameNode</i>” 並進行配置,或者選擇“<i>更多操作</i>”,導入已有配置。
ja-JP: Hertzbeat は HDFS NameNodeの一般的なメトリック監視します。<br>「<i>新規 Apache HDFS NameNode</i>」をクリックしてパラメタを設定した後、新規することができます。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/hdfs_namenode/
@@ -38,6 +40,7 @@ params:
name:
zh-CN: 目标Host
en-US: Target Host
ja-JP: 目標ホスト
# type-param field type(most mapping the html input type)
type: host
# required-true or false
@@ -48,6 +51,7 @@ 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
@@ -62,6 +66,7 @@ params:
name:
zh-CN: 查询超时时间
en-US: Query Timeout
ja-JP: クエリタイムアウト
# type-param field type(most mapping the html input type)
type: number
# required-true or false
@@ -85,6 +90,7 @@ metrics:
i18n:
zh-CN: 集群存储总容量
en-US: CapacityTotal
ja-JP: 容量合計
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: CapacityTotalGB
type: 0
@@ -92,12 +98,14 @@ metrics:
i18n:
zh-CN: 集群存储总容量
en-US: CapacityTotalGB
ja-JP: 容量合計(GB)
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: CapacityUsed
type: 0
i18n:
zh-CN: 集群存储已使用容量
en-US: CapacityUsed
ja-JP: 使用済みの容量
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: CapacityUsedGB
type: 0
@@ -105,12 +113,14 @@ metrics:
zh-CN: 集群存储已使用容量
unit: 'GB'
en-US: CapacityUsedGB
ja-JP: 使用済みの容量(GB)
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: CapacityRemaining
type: 0
i18n:
zh-CN: 集群存储剩余容量
en-US: CapacityRemaining
ja-JP: 使用可能の容量
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: CapacityRemainingGB
type: 0
@@ -118,120 +128,140 @@ metrics:
i18n:
zh-CN: 集群存储剩余容量
en-US: CapacityRemainingGB
ja-JP: 使用可能の容量(GB)
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: CapacityUsedNonDFS
type: 0
i18n:
zh-CN: 集群非 HDFS 使用容量
en-US: CapacityUsedNonDFS
ja-JP: 使用済みのノンHDFS容量
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: TotalLoad
type: 0
i18n:
zh-CN: 整个集群的客户端连接数
en-US: TotalLoad
ja-JP: クライアントとのコネクション総数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: FilesTotal
type: 0
i18n:
zh-CN: 集群文件总数量
en-US: FilesTotal
ja-JP: ファイル総数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: BlocksTotal
type: 0
i18n:
zh-CN: 总 BLOCK 数量
en-US: BlocksTotal
ja-JP: ブロック総数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: PendingReplicationBlocks
type: 0
i18n:
zh-CN: 等待被备份的块数量
en-US: PendingReplicationBlocks
ja-JP: 保留中のレプリケーションのブロック数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: UnderReplicatedBlocks
type: 0
i18n:
zh-CN: 副本数不够的块数量
en-US: UnderReplicatedBlocks
ja-JP: レプリケート中のブロック数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: CorruptBlocks
type: 0
i18n:
zh-CN: 坏块数量
en-US: CorruptBlocks
ja-JP: 破損ブロック数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: ScheduledReplicationBlocks
type: 0
i18n:
zh-CN: 安排要备份的块数量
en-US: ScheduledReplicationBlocks
ja-JP: スケジュールされたレプリケーションのブロック数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: PendingDeletionBlocks
type: 0
i18n:
zh-CN: 等待被删除的块数量
en-US: PendingDeletionBlocks
ja-JP: 保留中の削除ブロック数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: ExcessBlocks
type: 0
i18n:
zh-CN: 多余的块数量
en-US: ExcessBlocks
ja-JP: 余剰ブロック数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: PostponedMisreplicatedBlocks
type: 0
i18n:
zh-CN: 被推迟处理的异常块数量
en-US: PostponedMisreplicatedBlocks
ja-JP: 延期の異常ブロック数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: NumLiveDataNodes
type: 0
i18n:
zh-CN: 活的数据节点数量
en-US: NumLiveDataNodes
ja-JP: ライブのDATANODE数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: NumDeadDataNodes
type: 0
i18n:
zh-CN: 已经标记为 Dead 状态的数据节点数量
en-US: NumDeadDataNodes
ja-JP: デッドのDATANODE数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: NumDecomLiveDataNodes
type: 0
i18n:
zh-CN: 下线且 Live 的节点数量
en-US: NumDecomLiveDataNodes
ja-JP: オフラインとライブのDATANODE数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: NumDecomDeadDataNodes
type: 0
i18n:
zh-CN: 下线且 Dead 的节点数量
en-US: NumDecomDeadDataNodes
ja-JP: オフラインとデッドのDATANODE数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: NumDecommissioningDataNodes
type: 0
i18n:
zh-CN: 正在下线的节点数量
en-US: NumDecommissioningDataNodes
ja-JP: オフライン中のDATANODE数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: TransactionsSinceLastCheckpoint
type: 0
i18n:
zh-CN: 从上次Checkpoint之后的事务数量
en-US: TransactionsSinceLastCheckpoint
ja-JP: 前回のチェックポイントからのトランザクション数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: LastCheckpointTime
type: 0
i18n:
zh-CN: 上一次Checkpoint时间
en-US: LastCheckpointTime
ja-JP: 最終チェックポイント時刻
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: PendingDataNodeMessageCount
type: 0
i18n:
zh-CN: DATANODE 的请求被 QUEUE 在 standby namenode 中的个数
en-US: PendingDataNodeMessageCount
ja-JP: DATANODEで保留中のメッセージ数
# (optional)metrics field alias name, it is used as an alias field to map and convert the collected data and metrics field
aliasFields:
- $.CapacityTotal
@@ -306,18 +336,21 @@ metrics:
i18n:
zh-CN: 接收数据速率
en-US: ReceivedBytes
ja-JP: 受信バイト
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: SentBytes
type: 0
i18n:
zh-CN: 发送数据速率
en-US: SentBytes
ja-JP: 送信バイト
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: RpcQueueTimeNumOps
type: 0
i18n:
zh-CN: RPC 调用速率
en-US: RpcQueueTimeNumOps
ja-JP: RPCスピード
# (optional)metrics field alias name, it is used as an alias field to map and convert the collected data and metrics field
aliasFields:
- $.ReceivedBytes
@@ -349,6 +382,7 @@ metrics:
i18n:
zh-CN: 启动时间
en-US: StartTime
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:
- $.beans[?(@.name == "java.lang:type=Runtime")].StartTime
@@ -376,96 +410,112 @@ metrics:
i18n:
zh-CN: JVM 当前已经使用的 NonHeapMemory 的大小
en-US: MemNonHeapUsedM
ja-JP: 使用済みのノンヒープメモリサイズ
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: MemNonHeapCommittedM
type: 0
i18n:
zh-CN: JVM 配置的 NonHeapCommittedM 的大小
en-US: MemNonHeapCommittedM
ja-JP: コミットのノンヒープメモリサイズ
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: MemHeapUsedM
type: 0
i18n:
zh-CN: JVM 当前已经使用的 HeapMemory 的大小
en-US: MemHeapUsedM
ja-JP: 使用済みのヒープメモリサイズ
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: MemHeapCommittedM
type: 0
i18n:
zh-CN: JVM HeapMemory 提交大小
en-US: MemHeapCommittedM
ja-JP: コミットのヒープメモリサイズ
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: MemHeapMaxM
type: 0
i18n:
zh-CN: JVM 配置的 HeapMemory 的大小
en-US: MemHeapMaxM
ja-JP: 配置のヒープメモリサイズ
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: MemMaxM
type: 0
i18n:
zh-CN: JVM 运行时可以使用的最大内存大小
en-US: MemMaxM
ja-JP: 最大のヒープメモリサイズ
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: GcCountParNew
type: 0
i18n:
zh-CN: 新生代GC次数
en-US: GcCountParNew
ja-JP: 新領域GC回数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: GcTimeMillisParNew
type: 0
i18n:
zh-CN: 新生代GC消耗时间
en-US: GcTimeMillisParNew
ja-JP: 新領域GC時間
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: GcCountConcurrentMarkSweep
type: 0
i18n:
zh-CN: 老年代GC次数
en-US: GcCountConcurrentMarkSweep
ja-JP: 古い領域GC回数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: GcTimeMillisConcurrentMarkSweep
type: 0
i18n:
zh-CN: 老年代GC消耗时间
en-US: GcTimeMillisConcurrentMarkSweep
ja-JP: 古い領域GC時間
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: GcCount
type: 0
i18n:
zh-CN: GC次数
en-US: GcCount
ja-JP: GC回数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: GcTimeMillis
type: 0
i18n:
zh-CN: GC消耗时间
en-US: GcTimeMillis
ja-JP: GC時間
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: ThreadsRunnable
type: 0
i18n:
zh-CN: 处于 BLOCKED 状态的线程数量
zh-CN: 处于 RUNNABLE 状态的线程数量
en-US: ThreadsRunnable
ja-JP: RUNNABLE スレッド数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: ThreadsBlocked
type: 0
i18n:
zh-CN: 处于 BLOCKED 状态的线程数量
en-US: ThreadsBlocked
ja-JP: BLOCKED スレッド数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: ThreadsWaiting
type: 0
i18n:
zh-CN: 处于 WAITING 状态的线程数量
en-US: ThreadsWaiting
ja-JP: WAITING スレッド数
# field-metric name, type-metric type(0-number,1-string), unit-metric unit('%','ms','MB'), label-whether it is a metrics label field
- field: ThreadsTimedWaiting
type: 0
i18n:
zh-CN: 处于 TIMED WAITING 状态的线程数量
en-US: ThreadsTimedWaiting
ja-JP: TIMED WAITING スレッド数
# (optional)metrics field alias name, it is used as an alias field to map and convert the collected data and metrics field
aliasFields:
- $.MemNonHeapUsedM
@@ -20,11 +20,13 @@ app: hertzbeat
name:
zh-CN: HertzBeat
en-US: HertzBeat
ja-JP: HertzBeat
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 对 Hertzbeat 监控系统的通用指标进行测量监控。<br>您可以点击 “<i>新建 HertzBeat监控系统</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor through general performance metric. You could click the "<i>New HertzBeat Monitor</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat對Hertzbeat監控系統的通用名額進行量測監控。<br>您可以點擊“<i>新建HertzBeat監控系統</i>”並進行配寘,或者選擇“<i>更多操作</i>”,導入已有配寘。
zh-TW: Hertzbeat對Hertzbeat監控系統的通用指標進行量測監控。<br>您可以點擊“<i>新建HertzBeat監控系統</i>”並進行配寘,或者選擇“<i>更多操作</i>”,導入已有配寘。
ja-JP: Hertzbeat は Hertzbeatの一般的なメトリック監視します。<br>「<i>新規 Apache Hertzbeat</i>」をクリックしてパラメタを設定した後、新規することができます。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/hertzbeat
en-US: https://hertzbeat.apache.org/docs/help/hertzbeat
@@ -33,12 +35,14 @@ 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
@@ -47,12 +51,14 @@ params:
name:
zh-CN: 启用HTTPS
en-US: HTTPS
ja-JP: HTTPS
type: boolean
required: true
- field: timeout
name:
zh-CN: 超时时间(ms)
en-US: Timeout(ms)
ja-JP: タイムアウト(ms)
type: number
required: false
hide: true
@@ -60,6 +66,7 @@ params:
name:
zh-CN: 认证方式
en-US: Auth Type
ja-JP: 認証方法
type: radio
required: false
hide: true
@@ -72,6 +79,7 @@ params:
name:
zh-CN: 用户名
en-US: Username
ja-JP: ユーザー名
type: text
limit: 50
required: false
@@ -80,6 +88,7 @@ params:
name:
zh-CN: 密码
en-US: Password
ja-JP: パスワード
type: password
required: false
hide: true
@@ -90,6 +99,7 @@ metrics:
i18n:
zh-CN: 概要信息
en-US: Summary
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
@@ -102,26 +112,31 @@ metrics:
i18n:
zh-CN: 应用
en-US: App
ja-JP: 応用
- field: category
type: 1
i18n:
zh-CN: 类别
en-US: Category
ja-JP: カテゴリ
- field: status
type: 0
i18n:
zh-CN: 状态
en-US: Status
ja-JP: ステータス
- field: size
type: 0
i18n:
zh-CN: 数量
en-US: Size
ja-JP: サイズ
- field: availableSize
type: 0
i18n:
zh-CN: 可用数量
en-US: Available Size
ja-JP: 利用可能なサイズ
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk, we use HTTP protocol here
protocol: http
# the config content when protocol is http
@@ -153,6 +168,7 @@ metrics:
i18n:
zh-CN: 内部队列
en-US: Inner Queue
ja-JP: 内部キュー
priority: 1
fields:
- field: responseTime
@@ -161,26 +177,31 @@ metrics:
i18n:
zh-CN: 响应时间
en-US: Response Time
ja-JP: 応答時間
- field: alertDataQueue
type: 0
i18n:
zh-CN: 变更数据队列
en-US: Data Change Queue
ja-JP: データ変更キュー
- field: metricsDataToAlertQueue
type: 0
i18n:
zh-CN: 指标数据到变更队列
en-US: Metrics Data to Change Queue
ja-JP: データ変更キュー
- field: metricsDataToPersistentStorageQueue
type: 0
i18n:
zh-CN: 指标数据到持久化队列
en-US: Metrics Data to Persistent Queue
ja-JP: 永続キュー
- field: metricsDataToMemoryStorageQueue
type: 0
i18n:
zh-CN: 指标数据到内存存储队列
en-US: Metrics Data to Memory Storage Queue
ja-JP: メモリストレージキュー
protocol: http
http:
host: ^_^host^_^
@@ -202,6 +223,7 @@ metrics:
i18n:
zh-CN: 线程状态
en-US: Thread State
ja-JP: スレッド状態
visible: false
priority: 1
fields:
@@ -210,6 +232,7 @@ metrics:
i18n:
zh-CN: 状态
en-US: State
ja-JP: 状態
protocol: http
http:
host: ^_^host^_^
@@ -230,6 +253,7 @@ metrics:
i18n:
zh-CN: 线程
en-US: Threads
ja-JP: スレッド
priority: 3
fields:
- field: state
@@ -237,11 +261,13 @@ metrics:
i18n:
zh-CN: 状态
en-US: State
ja-JP: 状態
- field: number
type: 0
i18n:
zh-CN: 数量
en-US: Number
ja-JP: 総数
aliasFields:
- $.measurements[?(@.statistic == "VALUE")].value
calculates:
@@ -267,6 +293,7 @@ metrics:
i18n:
zh-CN: 空间名称
en-US: Space Name
ja-JP: スペース名
visible: false
priority: 4
fields:
@@ -275,6 +302,7 @@ metrics:
i18n:
zh-CN: ID
en-US: ID
ja-JP: ID
protocol: http
http:
host: ^_^host^_^
@@ -295,6 +323,7 @@ metrics:
i18n:
zh-CN: 内存使用
en-US: Memory Used
ja-JP: 使用済みのメモリ
priority: 5
fields:
- field: space
@@ -302,12 +331,14 @@ metrics:
i18n:
zh-CN: 空间
en-US: Space
ja-JP: スペース
- field: mem_used
type: 0
unit: MB
i18n:
zh-CN: 已使用内存
en-US: Used Memory
ja-JP: 使用済みのメモリ
aliasFields:
- $.measurements[?(@.statistic == "VALUE")].value
calculates:
@@ -22,11 +22,13 @@ app: hertzbeat_token
name:
zh-CN: HertzBeat(Token)
en-US: HertzBeat(Token)
ja-JP: HertzBeat(Token)
# The description and help of this monitoring type
help:
zh-CN: Hertzbeat 对 HertzBeat监控(Token)进行测量监控。<br>您可以点击 “<i>新建 HertzBeat监控(Token)</i>” 并进行配置,或者选择“<i>更多操作</i>”,导入已有配置。
en-US: Hertzbeat monitors HertzBeat Monitor(Token). You could click the "<i>New HertzBeat Monitor(Token)</i>" button and proceed with the configuration or import an existing setup through the "<i>More Actions</i>" menu.
zh-TW: Hertzbeat對HertzBeat監控(Token)進行量測監控。<br>您可以點擊“<i>新建HertzBeat監控(Token</i>”並進行配寘,或者選擇“<i>更多操作</i>”,導入已有配寘。
ja-JP: Hertzbeat は Hertzbeat(Token)の一般的なメトリック監視します。<br>「<i>新規 Apache Hertzbeat(Token)</i>」をクリックしてパラメタを設定した後、新規することができます。
helpLink:
zh-CN: https://hertzbeat.apache.org/zh-cn/docs/help/hertzbeat_token
en-US: https://hertzbeat.apache.org/docs/help/hertzbeat_token
@@ -38,6 +40,7 @@ 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
@@ -46,6 +49,7 @@ 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
@@ -57,6 +61,7 @@ params:
name:
zh-CN: 启动SSL
en-US: SSL
ja-JP: SSL利用
# type-param field type(boolean mapping the html switch tag)
type: boolean
required: false
@@ -64,6 +69,7 @@ params:
name:
zh-CN: Content-Type
en-US: Content-Type
ja-JP: コンテンツタイプ
type: text
placeholder: 'Request Body Type'
required: false
@@ -71,6 +77,7 @@ params:
name:
zh-CN: 请求BODY
en-US: BODY
ja-JP: ボディ
type: textarea
placeholder: 'Available When POST PUT'
required: false
@@ -81,6 +88,7 @@ metrics:
i18n:
zh-CN: 认证
en-US: Auth
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
@@ -92,11 +100,13 @@ metrics:
i18n:
zh-CN: 令牌
en-US: Token
ja-JP: トークン
- field: refreshToken
type: 1
i18n:
zh-CN: 刷新令牌
en-US: Refresh Token
ja-JP: リフレッシュトークン
# the protocol used for monitoring, eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: http
# the config content when protocol is http
@@ -128,6 +138,7 @@ metrics:
i18n:
zh-CN: 概要信息
en-US: Summary
ja-JP: 概要
priority: 1
fields:
- field: app
@@ -136,26 +147,31 @@ metrics:
i18n:
zh-CN: 应用
en-US: App
ja-JP: 応用
- field: category
type: 1
i18n:
zh-CN: 类别
en-US: Category
ja-JP: カテゴリ
- field: status
type: 0
i18n:
zh-CN: 状态
en-US: Status
ja-JP: ステータス
- field: size
type: 0
i18n:
zh-CN: 数量
en-US: Size
ja-JP: サイズ
- field: availableSize
type: 0
i18n:
zh-CN: 可用数量
en-US: Available Size
ja-JP: 利用可能なサイズ
protocol: http
http:
host: ^_^host^_^
@@ -174,6 +190,7 @@ metrics:
i18n:
zh-CN: 内部队列
en-US: Inner Queue
ja-JP: 内部キュー
priority: 1
fields:
- field: responseTime
@@ -182,26 +199,31 @@ metrics:
i18n:
zh-CN: 响应时间
en-US: Response Time
ja-JP: 応答時間
- field: alertDataQueue
type: 0
i18n:
zh-CN: 变更数据队列
en-US: Alert Data Queue
ja-JP: アラートデータキュー
- field: metricsDataToAlertQueue
type: 0
i18n:
zh-CN: 指标数据到变更队列
en-US: Metrics Data to Alert Queue
ja-JP: アラートキュー
- field: metricsDataToPersistentStorageQueue
type: 0
i18n:
zh-CN: 指标数据到持久化队列
en-US: Metrics Data to Persistent Storage Queue
ja-JP: 永続ストレージキュー
- field: metricsDataToMemoryStorageQueue
type: 0
i18n:
zh-CN: 指标数据到内存存储队列
en-US: Metrics Data to Memory Storage Queue
ja-JP: メモリストレージキュー
protocol: http
http:
host: ^_^host^_^
@@ -221,6 +243,7 @@ metrics:
i18n:
zh-CN: 指标数据到内存存储队列
en-US: Metrics Data to Memory Storage Queue
ja-JP: メモリストレージキュー
visible: false
priority: 2
fields:
@@ -229,6 +252,7 @@ metrics:
i18n:
zh-CN: 状态
en-US: State
ja-JP: 状態
protocol: http
http:
host: ^_^host^_^
@@ -247,6 +271,7 @@ metrics:
i18n:
zh-CN: 线程
en-US: Threads
ja-JP: スレッド
priority: 3
fields:
- field: state
@@ -254,11 +279,13 @@ metrics:
i18n:
zh-CN: 状态
en-US: State
ja-JP: 状態
- field: number
type: 0
i18n:
zh-CN: 数量
en-US: Number
ja-JP: 総数
aliasFields:
- $.measurements[?(@.statistic == "VALUE")].value
calculates:
@@ -282,6 +309,7 @@ metrics:
i18n:
zh-CN: 空间名称
en-US: Space Name
ja-JP: スペース名
visible: false
priority: 4
fields:
@@ -290,6 +318,7 @@ metrics:
i18n:
zh-CN: ID
en-US: ID
ja-JP: ID
protocol: http
http:
host: ^_^host^_^
@@ -308,6 +337,7 @@ metrics:
i18n:
zh-CN: 内存使用
en-US: Memory Used
ja-JP: 使用済みのメモリ
priority: 5
fields:
- field: space
@@ -315,12 +345,14 @@ metrics:
i18n:
zh-CN: 空间
en-US: Space
ja-JP: スペース
- field: mem_used
type: 0
unit: MB
i18n:
zh-CN: 内存使用量
en-US: Memory Used
ja-JP: 使用済みのメモリ
aliasFields:
- $.measurements[?(@.statistic == "VALUE")].value
calculates:
+16 -1
View File
@@ -16,7 +16,7 @@
# under the License.
name: setup-deps
description: Install host system dependencies
description: Install host system dependencies (with mvnd)
runs:
using: composite
@@ -26,3 +26,18 @@ runs:
with:
distribution: "zulu"
java-version: 17
- name: Install mvnd
shell: bash
run: |
MVND_VERSION=2.0.0-rc-3
curl -sL https://dlcdn.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip -o mvnd.zip
unzip -q mvnd.zip
mkdir -p $HOME/.local
mv maven-mvnd-${MVND_VERSION}-linux-amd64 $HOME/.local/mvnd
echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH
echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV
- name: Verify mvnd installation
shell: bash
run: mvnd --version