This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch refactor-with-go
in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git
The following commit(s) were added to refs/heads/refactor-with-go by this push:
new c483ed37 monitor -- Traffic Overview (#1047)
c483ed37 is described below
commit c483ed3702bee2b37ab41beb6081b9c8af5cca52
Author: 无言独上机房 <[email protected]>
AuthorDate: Wed Mar 22 08:51:23 2023 +0800
monitor -- Traffic Overview (#1047)
---
go.mod | 6 +-
go.sum | 2 +
pkg/admin/config/config.go | 21 ++++-
pkg/admin/constant/const.go | 9 +++
pkg/admin/handlers/service.go | 25 +++++-
pkg/admin/model/monitor.go | 21 +++++
pkg/admin/router/router.go | 2 +
pkg/admin/services/monitor_service.go | 23 ++++++
pkg/admin/services/prometheus_service_impl.go | 110 ++++++++++++++++++++++++++
pkg/monitor/prometheus/metrics.go | 60 ++++++++++++++
pkg/monitor/prometheus/types.go | 23 ++++++
11 files changed, 296 insertions(+), 6 deletions(-)
diff --git a/go.mod b/go.mod
index 92f3d0b2..26fbe51f 100644
--- a/go.mod
+++ b/go.mod
@@ -22,10 +22,12 @@ require (
dubbo.apache.org/dubbo-go/v3 v3.0.2
github.com/dubbogo/gost v1.11.25
github.com/gin-gonic/gin v1.8.2
- github.com/golang/mock v1.6.0
github.com/golang-jwt/jwt/v4 v4.5.0
+ github.com/golang/mock v1.6.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/mattbaird/jsonpatch v0.0.0-20200820163806-098863c1fc24
+ github.com/prometheus/client_golang v1.12.2
+ github.com/prometheus/common v0.32.1
github.com/stretchr/testify v1.8.2
github.com/tidwall/gjson v1.14.4
go.uber.org/zap v1.24.0
@@ -104,9 +106,7 @@ require (
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/prometheus/client_golang v1.12.2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
- github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/prometheus/statsd_exporter v0.21.0 // indirect
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b //
indirect
diff --git a/go.sum b/go.sum
index 955d3a2c..5528ead8 100644
--- a/go.sum
+++ b/go.sum
@@ -457,6 +457,7 @@ github.com/jonboulle/clockwork v0.1.0/go.mod
h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22
github.com/jonboulle/clockwork v0.2.2/go.mod
h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/josharian/intern v1.0.0
h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod
h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/jpillora/backoff v1.0.0
h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod
h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.5/go.mod
h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod
h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -564,6 +565,7 @@ github.com/mschoch/smat v0.2.0/go.mod
h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOl
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod
h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod
h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod
h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nacos-group/nacos-sdk-go v1.0.8/go.mod
h1:hlAPn3UdzlxIlSILAyOXKxjFSvDJ9oLzTJ9hLAK1KzA=
github.com/nacos-group/nacos-sdk-go v1.1.1
h1:beczWcOoTaVBMgCgikqvZflrN5Xbw7pWAWpxl+VJGIA=
diff --git a/pkg/admin/config/config.go b/pkg/admin/config/config.go
index a19b43c8..72f1c34e 100644
--- a/pkg/admin/config/config.go
+++ b/pkg/admin/config/config.go
@@ -38,7 +38,13 @@ import (
const conf = "./conf/dubboadmin.yml"
type Config struct {
- Admin Admin `yaml:"admin"`
+ Admin Admin `yaml:"admin"`
+ Prometheus Prometheus `yaml:"prometheus"`
+}
+
+type Prometheus struct {
+ Ip string `json:"ip"`
+ Port string `json:"port"`
}
type Admin struct {
@@ -55,6 +61,11 @@ var (
Group string
)
+var (
+ PrometheusIp string
+ PrometheusPort string
+)
+
func LoadConfig() {
path, err := filepath.Abs(conf)
if err != nil {
@@ -69,6 +80,14 @@ func LoadConfig() {
address := config.Admin.ConfigCenter
registryAddress := config.Admin.Registry.Address
metadataReportAddress := config.Admin.MetadataReport.Address
+ PrometheusIp = config.Prometheus.Ip
+ PrometheusPort = config.Prometheus.Port
+ if PrometheusIp == "" {
+ PrometheusIp = "127.0.0.1"
+ }
+ if PrometheusPort == "" {
+ PrometheusPort = "9090"
+ }
if len(address) > 0 {
c := newAddressConfig(address)
factory, err :=
extension.GetConfigCenterFactory(c.getProtocol())
diff --git a/pkg/admin/constant/const.go b/pkg/admin/constant/const.go
index ccb4cc81..b4832a6d 100644
--- a/pkg/admin/constant/const.go
+++ b/pkg/admin/constant/const.go
@@ -68,3 +68,12 @@ const (
)
var Configs = set.NewSet(WeightKey, BalancingKey)
+
+const (
+ MetricsQps = "" // QPS
+ MetricsHttpRequestTotalCount = "" // Total number of http requests
+ MetricsHttpRequestSuccessCount = "" // Total number of http
successful requests
+ MetricsHttpRequestOutOfTimeCount = "" // Total number of http out of
time requests
+ MetricsHttpRequestAddressNotFount = "" // Total number of HTTP requests
where the address cannot be found
+ MetricsHttpRequestOtherException = "" // Total number of other errors
for http requests
+)
diff --git a/pkg/admin/handlers/service.go b/pkg/admin/handlers/service.go
index 948bb52d..fe7c6697 100644
--- a/pkg/admin/handlers/service.go
+++ b/pkg/admin/handlers/service.go
@@ -31,8 +31,9 @@ import (
)
var (
- providerService services.ProviderService =
&services.ProviderServiceImpl{}
- consumerService services.ConsumerService =
&services.ConsumerServiceImpl{}
+ providerService services.ProviderService =
&services.ProviderServiceImpl{}
+ consumerService services.ConsumerService =
&services.ConsumerServiceImpl{}
+ prometheusService services.MonitorService =
&services.PrometheusServiceImpl{}
)
func AllServices(c *gin.Context) {
@@ -145,3 +146,23 @@ func ServiceDetail(c *gin.Context) {
func Version(c *gin.Context) {
c.JSON(http.StatusOK, version.GetVersion())
}
+
+func FlowMetrics(c *gin.Context) {
+ res, err := prometheusService.FlowMetrics()
+ if err != nil {
+ c.JSON(http.StatusInternalServerError, gin.H{
+ "error": err.Error(),
+ })
+ }
+ c.JSON(http.StatusOK, res)
+}
+
+func ClusterMetrics(c *gin.Context) {
+ res, err := prometheusService.ClusterMetrics()
+ if err != nil {
+ c.JSON(http.StatusInternalServerError, gin.H{
+ "error": err.Error(),
+ })
+ }
+ c.JSON(http.StatusOK, res)
+}
diff --git a/pkg/admin/model/monitor.go b/pkg/admin/model/monitor.go
new file mode 100644
index 00000000..3ff6b40e
--- /dev/null
+++ b/pkg/admin/model/monitor.go
@@ -0,0 +1,21 @@
+// 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 model
+
+type Response struct {
+ Status int `json:"status"`
+ Data string `json:"data"`
+}
diff --git a/pkg/admin/router/router.go b/pkg/admin/router/router.go
index 609bf3b8..ad948a84 100644
--- a/pkg/admin/router/router.go
+++ b/pkg/admin/router/router.go
@@ -31,6 +31,8 @@ func InitRouter() *gin.Engine {
router.GET("api/dev/consumers", handlers.AllConsumers)
router.GET("api/dev/service/:service", handlers.ServiceDetail)
router.GET("/api/dev/version", handlers.Version)
+ router.GET("/api/dev/metrics/flow", handlers.FlowMetrics)
+ router.GET("/api/dev/metrics/cluster", handlers.ClusterMetrics)
override := router.Group("/api/:env/rules/override")
{
diff --git a/pkg/admin/services/monitor_service.go
b/pkg/admin/services/monitor_service.go
new file mode 100644
index 00000000..5c377d41
--- /dev/null
+++ b/pkg/admin/services/monitor_service.go
@@ -0,0 +1,23 @@
+// 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 services
+
+package services
+
+import "github.com/apache/dubbo-admin/pkg/admin/model"
+
+type MonitorService interface {
+ FlowMetrics() ([]model.Response, error) // Traffic overview
+ ClusterMetrics() ([]model.Response, error) // Cluster overview
+}
diff --git a/pkg/admin/services/prometheus_service_impl.go
b/pkg/admin/services/prometheus_service_impl.go
new file mode 100644
index 00000000..9d272014
--- /dev/null
+++ b/pkg/admin/services/prometheus_service_impl.go
@@ -0,0 +1,110 @@
+// 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 services
+
+package services
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/prometheus/client_golang/api"
+ prom_v1 "github.com/prometheus/client_golang/api/prometheus/v1"
+
+ "github.com/apache/dubbo-admin/pkg/admin/config"
+ "github.com/apache/dubbo-admin/pkg/admin/constant"
+ "github.com/apache/dubbo-admin/pkg/admin/model"
+ "github.com/apache/dubbo-admin/pkg/logger"
+ "github.com/apache/dubbo-admin/pkg/monitor/prometheus"
+)
+
+type PrometheusServiceImpl struct{}
+
+func (p *PrometheusServiceImpl) ClusterMetrics() ([]model.Response, error) {
+ return nil, nil
+}
+
+func (p *PrometheusServiceImpl) FlowMetrics() ([]model.Response, error) {
+ res := make([]model.Response, 5)
+ ip := config.PrometheusIp
+ port := config.PrometheusPort
+ address := fmt.Sprintf("http://%s:%s", ip, port)
+ client, err := api.NewClient(api.Config{
+ Address: address,
+ })
+ if err != nil {
+ logger.Sugar().Errorf("Error creating client: %v\n", err)
+ return nil, err
+ }
+ v1api := prom_v1.NewAPI(client)
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+
+ vector1 := prometheus.FetchQuery(ctx, v1api, constant.MetricsQps, nil)
+ err = vector1.Err
+ if err != nil {
+ logger.Sugar().Errorf("Error query qps: %v\n", err)
+ res[0].Status = http.StatusInternalServerError
+ res[0].Data = ""
+ } else {
+ qps := float64(vector1.Vector[0].Value)
+ res[0].Status = http.StatusOK
+ res[0].Data = fmt.Sprintf("%d", int(qps))
+ }
+ vector2 := prometheus.FetchQuery(ctx, v1api,
constant.MetricsHttpRequestSuccessCount, nil)
+ data1 := float64(vector2.Vector[0].Value)
+ vector3 := prometheus.FetchQuery(ctx, v1api,
constant.MetricsHttpRequestTotalCount, nil)
+ data2 := float64(vector3.Vector[0].Value)
+ if vector2.Err != nil && vector3.Err != nil {
+ res[1].Status = http.StatusInternalServerError
+ res[1].Data = ""
+ } else {
+ res[1].Status = http.StatusOK
+ successRate := data1 / data2
+ res[1].Data = fmt.Sprintf("%0.2f", successRate)
+ }
+ vector4 := prometheus.FetchQuery(ctx, v1api,
constant.MetricsHttpRequestOutOfTimeCount, nil)
+ data4 := float64(vector4.Vector[0].Value)
+ if vector4.Err != nil {
+ res[2].Status = http.StatusInternalServerError
+ res[2].Data = ""
+ } else {
+ res[2].Status = http.StatusOK
+ outOfTimeRate := data4 / data2
+ res[2].Data = fmt.Sprintf("%0.2f", outOfTimeRate)
+ }
+ vector5 := prometheus.FetchQuery(ctx, v1api,
constant.MetricsHttpRequestAddressNotFount, nil)
+ data5 := float64(vector5.Vector[0].Value)
+ if vector5.Err != nil {
+ res[3].Status = http.StatusInternalServerError
+ res[3].Data = ""
+ } else {
+ res[3].Status = http.StatusOK
+ notFound := data5 / data2
+ res[3].Data = fmt.Sprintf("%0.2f", notFound)
+ }
+ vector6 := prometheus.FetchQuery(ctx, v1api,
constant.MetricsHttpRequestOtherException, nil)
+ data6 := float64(vector6.Vector[0].Value)
+ if vector6.Err != nil {
+ res[4].Status = http.StatusInternalServerError
+ res[4].Data = ""
+ } else {
+ res[4].Status = http.StatusOK
+ other := data6 / data2
+ res[4].Data = fmt.Sprintf("%0.2f", other)
+ }
+ return res, nil
+}
diff --git a/pkg/monitor/prometheus/metrics.go
b/pkg/monitor/prometheus/metrics.go
new file mode 100644
index 00000000..837cd37f
--- /dev/null
+++ b/pkg/monitor/prometheus/metrics.go
@@ -0,0 +1,60 @@
+// 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 prometheus
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ prom_v1 "github.com/prometheus/client_golang/api/prometheus/v1"
+ "github.com/prometheus/common/model"
+
+ "github.com/apache/dubbo-admin/pkg/logger"
+)
+
+func stitchingLabels(labels []string) string {
+ var labelsQ string
+ for i, labelsInstance := range labels {
+ if i == 0 {
+ labelsQ += labelsInstance
+ } else {
+ labelsQ += ", " + labelsInstance
+ }
+ }
+ return labelsQ
+}
+
+func FetchQuery(ctx context.Context, api prom_v1.API, metricName string,
labels []string) Metric {
+ var query string
+ // Example: sum(my_counter{name=dubbo})
+ label := stitchingLabels(labels)
+ query = fmt.Sprintf("sum(%s{%s})", metricName, label)
+ logger.Sugar().Info(query)
+ result, warnings, err := api.Query(ctx, query, time.Now())
+ switch result.Type() {
+ case model.ValVector:
+ return Metric{Vector: result.(model.Vector)}
+ }
+ if len(warnings) > 0 {
+ logger.Sugar().Warnf("Warnings: %v", warnings)
+ }
+ if err != nil {
+ logger.Sugar().Errorf("Error query Prometheus: %v\n", err)
+ return Metric{Err: fmt.Errorf("Error query Prometheus: %v\n",
err)}
+ }
+ return Metric{Err: fmt.Errorf("invalid query, matrix expected: %s",
query)}
+}
diff --git a/pkg/monitor/prometheus/types.go b/pkg/monitor/prometheus/types.go
new file mode 100644
index 00000000..f6b13d45
--- /dev/null
+++ b/pkg/monitor/prometheus/types.go
@@ -0,0 +1,23 @@
+// 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 prometheus
+
+import "github.com/prometheus/common/model"
+
+type Metric struct {
+ Vector model.Vector `json:"vector"`
+ Err error `json:"-"`
+}