diff --git a/collector/src/main/java/com/usthe/collector/collect/http/HttpCollectImpl.java b/collector/src/main/java/com/usthe/collector/collect/http/HttpCollectImpl.java index 868ca243555..034bd997d0e 100644 --- a/collector/src/main/java/com/usthe/collector/collect/http/HttpCollectImpl.java +++ b/collector/src/main/java/com/usthe/collector/collect/http/HttpCollectImpl.java @@ -417,28 +417,15 @@ private void parseResponseByDefault(String resp, List aliasFields, HttpP if (element.isJsonArray()) { JsonArray array = element.getAsJsonArray(); for (JsonElement jsonElement : array) { - if (jsonElement.isJsonObject()) { - JsonObject object = jsonElement.getAsJsonObject(); - CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder(); - for (String alias : aliasFields) { - JsonElement valueElement = object.get(alias); - if (valueElement != null) { - String value = valueElement.getAsString(); - valueRowBuilder.addColumns(value); - } else { - if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) { - valueRowBuilder.addColumns(responseTime.toString()); - } else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) { - valueRowBuilder.addColumns(Integer.toString(keywordNum)); - } else { - valueRowBuilder.addColumns(CommonConstants.NULL_VALUE); - } - } - } - builder.addValues(valueRowBuilder.build()); - } + getValueFromJson(aliasFields, builder, responseTime, jsonElement, keywordNum); } - } else if (element.isJsonObject()) { + } else { + getValueFromJson(aliasFields, builder, responseTime, element, keywordNum); + } + } + + private void getValueFromJson(List aliasFields, CollectRep.MetricsData.Builder builder, Long responseTime, JsonElement element, int keywordNum) { + if (element.isJsonObject()) { JsonObject object = element.getAsJsonObject(); CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder(); for (String alias : aliasFields) { @@ -447,7 +434,13 @@ private void parseResponseByDefault(String resp, List aliasFields, HttpP String value = valueElement.getAsString(); valueRowBuilder.addColumns(value); } else { - valueRowBuilder.addColumns(CommonConstants.NULL_VALUE); + if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) { + valueRowBuilder.addColumns(responseTime.toString()); + } else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) { + valueRowBuilder.addColumns(Integer.toString(keywordNum)); + } else { + valueRowBuilder.addColumns(CommonConstants.NULL_VALUE); + } } } builder.addValues(valueRowBuilder.build()); diff --git a/common/src/main/java/com/usthe/common/queue/impl/InMemoryCommonDataQueue.java b/common/src/main/java/com/usthe/common/queue/impl/InMemoryCommonDataQueue.java index c1548bf608d..b675934f5c9 100644 --- a/common/src/main/java/com/usthe/common/queue/impl/InMemoryCommonDataQueue.java +++ b/common/src/main/java/com/usthe/common/queue/impl/InMemoryCommonDataQueue.java @@ -25,6 +25,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -51,6 +53,15 @@ public InMemoryCommonDataQueue() { metricsDataToMemoryStorageQueue = new LinkedBlockingQueue<>(); } + public Map getQueueSizeMetricsInfo() { + Map metrics = new HashMap<>(8); + metrics.put("alertDataQueue", alertDataQueue.size()); + metrics.put("metricsDataToAlertQueue", metricsDataToAlertQueue.size()); + metrics.put("metricsDataToPersistentStorageQueue", metricsDataToPersistentStorageQueue.size()); + metrics.put("metricsDataToMemoryStorageQueue", metricsDataToMemoryStorageQueue.size()); + return metrics; + } + @Override public void addAlertData(Alert alert) { alertDataQueue.offer(alert); diff --git a/manager/src/main/java/com/usthe/manager/controller/MetricsController.java b/manager/src/main/java/com/usthe/manager/controller/MetricsController.java new file mode 100644 index 00000000000..bbfeaa8a93a --- /dev/null +++ b/manager/src/main/java/com/usthe/manager/controller/MetricsController.java @@ -0,0 +1,59 @@ +/* + * 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 com.usthe.manager.controller; + +import com.usthe.common.entity.dto.Message; +import com.usthe.common.queue.CommonDataQueue; +import com.usthe.common.queue.impl.InMemoryCommonDataQueue; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +/** + * hertzbeat metrics exporter + * @author tom + * @date 2022/03/14 21:40 + */ +@Tag(name = "Inner Metrics Exporter API | 内部监控指标API") +@RestController +@RequestMapping(path = "/api/metrics", produces = {APPLICATION_JSON_VALUE}) +public class MetricsController { + + @Autowired + private CommonDataQueue commonDataQueue; + + @GetMapping() + @Operation(summary = "Get Hertzbeat Metrics Data") + public ResponseEntity>> getMetricsInfo() { + Map metricsInfo = new HashMap<>(8); + if (commonDataQueue instanceof InMemoryCommonDataQueue) { + Map queueInfo = ((InMemoryCommonDataQueue) commonDataQueue).getQueueSizeMetricsInfo(); + metricsInfo.putAll(queueInfo); + } + return ResponseEntity.ok(new Message<>(metricsInfo)); + } +} diff --git a/manager/src/main/resources/application.yml b/manager/src/main/resources/application.yml index db9cc13d587..50b7d91e6aa 100644 --- a/manager/src/main/resources/application.yml +++ b/manager/src/main/resources/application.yml @@ -43,8 +43,8 @@ management: endpoints: web: exposure: - include: '*' - enabled-by-default: off + include: 'metrics' + enabled-by-default: on sureness: auths: diff --git a/manager/src/main/resources/define/app-hertzbeat.yml b/manager/src/main/resources/define/app-hertzbeat.yml index 32456963d84..5e571fb7794 100644 --- a/manager/src/main/resources/define/app-hertzbeat.yml +++ b/manager/src/main/resources/define/app-hertzbeat.yml @@ -85,9 +85,6 @@ metrics: # 指标组中的具体监控指标 fields: # 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位 - - field: responseTime - type: 0 - unit: ms - field: app type: 1 instance: true @@ -125,3 +122,131 @@ metrics: # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-网站可用性指标监控,我们这里使用jsonpath来解析响应数据 parseType: jsonPath parseScript: '$.data.apps.*' + + - name: inner_queue + priority: 1 + fields: + - field: responseTime + type: 0 + unit: ms + - field: alertDataQueue + type: 0 + - field: metricsDataToAlertQueue + type: 0 + - field: metricsDataToPersistentStorageQueue + type: 0 + - field: metricsDataToMemoryStorageQueue + type: 0 + protocol: http + http: + host: ^_^host^_^ + port: ^_^port^_^ + url: /api/metrics + timeout: ^_^timeout^_^ + method: GET + ssl: ^_^ssl^_^ + parseType: jsonPath + parseScript: '$.data' + + - name: thread_state + visible: false + priority: 1 + fields: + - field: state + type: 1 + protocol: http + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: /actuator/metrics/jvm.threads.states + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: jsonPath + parseScript: '$.availableTags[?(@.tag == "state")].values[*]' + + - name: threads + priority: 2 + fields: + - field: state + type: 1 + - field: number + type: 0 + aliasFields: + - $.measurements[?(@.statistic == "VALUE")].value + calculates: + - state='^o^state^o^' + - number=#`$.measurements[?(@.statistic == "VALUE")].value` + protocol: http + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: /actuator/metrics/jvm.threads.states?tag=state:^o^state^o^ + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: jsonPath + parseScript: '$' + + - name: space_name + visible: false + priority: 3 + fields: + - field: id + type: 1 + protocol: http + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: /actuator/metrics/jvm.memory.used + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: jsonPath + parseScript: '$.availableTags[?(@.tag == "id")].values[*]' + + - name: memory_used + priority: 4 + fields: + - field: space + type: 1 + - field: mem_used + type: 0 + unit: MB + aliasFields: + - $.measurements[?(@.statistic == "VALUE")].value + calculates: + - space="^o^id^o^" + - mem_used=#`$.measurements[?(@.statistic == "VALUE")].value` + units: + - mem_used=B->MB + protocol: http + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: /actuator/metrics/jvm.memory.used?tag=id:^o^id^o^ + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: jsonPath + parseScript: '$' diff --git a/manager/src/main/resources/define/app-hertzbeat_token.yml b/manager/src/main/resources/define/app-hertzbeat_token.yml index 0e85b7fc45b..59cc1c00b07 100644 --- a/manager/src/main/resources/define/app-hertzbeat_token.yml +++ b/manager/src/main/resources/define/app-hertzbeat_token.yml @@ -146,3 +146,131 @@ metrics: # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-网站可用性指标监控 parseType: jsonPath parseScript: '$.data.apps.*' + + - name: inner_queue + priority: 1 + fields: + - field: responseTime + type: 0 + unit: ms + - field: alertDataQueue + type: 0 + - field: metricsDataToAlertQueue + type: 0 + - field: metricsDataToPersistentStorageQueue + type: 0 + - field: metricsDataToMemoryStorageQueue + type: 0 + protocol: http + http: + host: ^_^host^_^ + port: ^_^port^_^ + url: /api/metrics + timeout: ^_^timeout^_^ + method: GET + ssl: ^_^ssl^_^ + parseType: jsonPath + parseScript: '$.data' + + - name: thread_state + visible: false + priority: 2 + fields: + - field: state + type: 1 + protocol: http + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: /actuator/metrics/jvm.threads.states + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: jsonPath + parseScript: '$.availableTags[?(@.tag == "state")].values[*]' + + - name: threads + priority: 3 + fields: + - field: state + type: 1 + - field: number + type: 0 + aliasFields: + - $.measurements[?(@.statistic == "VALUE")].value + calculates: + - state='^o^state^o^' + - number=#`$.measurements[?(@.statistic == "VALUE")].value` + protocol: http + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: /actuator/metrics/jvm.threads.states?tag=state:^o^state^o^ + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: jsonPath + parseScript: '$' + + - name: space_name + visible: false + priority: 4 + fields: + - field: id + type: 1 + protocol: http + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: /actuator/metrics/jvm.memory.used + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: jsonPath + parseScript: '$.availableTags[?(@.tag == "id")].values[*]' + + - name: memory_used + priority: 5 + fields: + - field: space + type: 1 + - field: mem_used + type: 0 + unit: MB + aliasFields: + - $.measurements[?(@.statistic == "VALUE")].value + calculates: + - space="^o^id^o^" + - mem_used=#`$.measurements[?(@.statistic == "VALUE")].value` + units: + - mem_used=B->MB + protocol: http + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: /actuator/metrics/jvm.memory.used?tag=id:^o^id^o^ + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: jsonPath + parseScript: '$' diff --git a/manager/src/main/resources/define/app-springboot2.yml b/manager/src/main/resources/define/app-springboot2.yml index 19b354e07fd..e3aa5cce8bf 100644 --- a/manager/src/main/resources/define/app-springboot2.yml +++ b/manager/src/main/resources/define/app-springboot2.yml @@ -54,11 +54,35 @@ params: required: true hide: true metrics: - - name: environment + - name: available # 指标组调度优先级(0-127)越小优先级越高,优先级低的指标组会等优先级高的指标组采集完成后才会被调度,相同优先级的指标组会并行调度采集 # 优先级为0的指标组为可用性指标组,即它会被首先调度,采集成功才会继续调度其它指标组,采集失败则中断调度 priority: 0 # 指标组中的具体监控指标 + fields: + # 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位 + - field: responseTime + type: 0 + unit: ms + protocol: http + # 当protocol为http协议时具体的采集配置 + http: + # 主机host: ipv4 ipv6 域名 + host: ^_^host^_^ + # 端口 + port: ^_^port^_^ + # url请求接口路径 + url: ^_^base_path^_^ + # 请求方式 GET POST PUT DELETE PATCH + method: GET + # 是否启用ssl/tls,即是http还是https,默认false + ssl: ^_^ssl^_^ + # 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-api可用性指标监控 + parseType: default + + - name: environment + priority: 1 + # 指标组中的具体监控指标 fields: # 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位 - field: profile diff --git a/manager/src/main/resources/sureness.yml b/manager/src/main/resources/sureness.yml index c4d258e68c8..cdce22f8798 100644 --- a/manager/src/main/resources/sureness.yml +++ b/manager/src/main/resources/sureness.yml @@ -56,6 +56,7 @@ resourceRole: excludedResource: - /api/account/auth/**===* - /api/i18n/**===get + - /api/metrics===get - /api/apps/hierarchy===get - /actuator/**===get # web ui 前端静态资源 diff --git a/script/application.yml b/script/application.yml index e8addd2c11b..3ab0a88b82d 100644 --- a/script/application.yml +++ b/script/application.yml @@ -36,6 +36,13 @@ spring: suffix: .html mode: HTML +management: + endpoints: + web: + exposure: + include: 'metrics' + enabled-by-default: on + sureness: auths: - digest diff --git a/script/docker-compose/hertzbeat-mysql-iotdb/conf/application.yml b/script/docker-compose/hertzbeat-mysql-iotdb/conf/application.yml index cc22e6953f0..79ca6b21f06 100644 --- a/script/docker-compose/hertzbeat-mysql-iotdb/conf/application.yml +++ b/script/docker-compose/hertzbeat-mysql-iotdb/conf/application.yml @@ -36,6 +36,13 @@ spring: suffix: .html mode: HTML +management: + endpoints: + web: + exposure: + include: 'metrics' + enabled-by-default: on + sureness: auths: - digest diff --git a/script/docker-compose/hertzbeat-mysql-tdengine/conf/application.yml b/script/docker-compose/hertzbeat-mysql-tdengine/conf/application.yml index 8534c384720..14ef438806f 100644 --- a/script/docker-compose/hertzbeat-mysql-tdengine/conf/application.yml +++ b/script/docker-compose/hertzbeat-mysql-tdengine/conf/application.yml @@ -36,6 +36,13 @@ spring: suffix: .html mode: HTML +management: + endpoints: + web: + exposure: + include: 'metrics' + enabled-by-default: on + sureness: auths: - digest