Skip to content

Commit

Permalink
add metrics base api interface (#2350)
Browse files Browse the repository at this point in the history
  • Loading branch information
FoghostCn committed Jul 7, 2023
1 parent f6fdbfd commit 2a4625d
Show file tree
Hide file tree
Showing 8 changed files with 495 additions and 3 deletions.
14 changes: 14 additions & 0 deletions common/host_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
)

import (
"github.com/dubbogo/gost/log/logger"
gxnet "github.com/dubbogo/gost/net"
)

Expand All @@ -31,6 +32,7 @@ import (
)

var localIp string
var localHostname string

func GetLocalIp() string {
if len(localIp) != 0 {
Expand All @@ -40,6 +42,18 @@ func GetLocalIp() string {
return localIp
}

func GetLocalHostName() string {
if len(localHostname) != 0 {
return localHostname
}
hostname, err := os.Hostname()
if err != nil {
logger.Errorf("can not get local hostname")
}
localHostname = hostname
return localHostname
}

func HandleRegisterIPAndPort(url *URL) {
// if developer define registry port and ip, use it first.
if ipToRegistry := os.Getenv(constant.DubboIpToRegistryKey); len(ipToRegistry) > 0 {
Expand Down
12 changes: 9 additions & 3 deletions config/metric_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ import (

"github.com/dubbogo/gost/log/logger"

"github.com/pkg/errors"
)

import (
"dubbo.apache.org/dubbo-go/v3/common/extension"
"dubbo.apache.org/dubbo-go/v3/metrics"
"github.com/pkg/errors"
)

// MetricConfig This is the config struct for all metrics implementation
Expand All @@ -36,6 +39,7 @@ type MetricConfig struct {
Path string `default:"/metrics" yaml:"path" json:"path,omitempty" property:"path"`
PushGatewayAddress string `default:"" yaml:"push-gateway-address" json:"push-gateway-address,omitempty" property:"push-gateway-address"`
SummaryMaxAge int64 `default:"600000000000" yaml:"summary-max-age" json:"summary-max-age,omitempty" property:"summary-max-age"`
Protocol string `default:"prometheus" yaml:"protocol" json:"protocol,omitempty" property:"protocol"`
}

func (mc *MetricConfig) ToReporterConfig() *metrics.ReporterConfig {
Expand Down Expand Up @@ -65,7 +69,9 @@ func (mc *MetricConfig) Init() error {
if err := verify(mc); err != nil {
return err
}
extension.GetMetricReporter("prometheus", mc.ToReporterConfig())
config := mc.ToReporterConfig()
extension.GetMetricReporter(mc.Protocol, config)
metrics.Init(config)
return nil
}

Expand All @@ -88,7 +94,7 @@ func (mc *MetricConfig) DynamicUpdateProperties(newMetricConfig *MetricConfig) {
mc.Enable = newMetricConfig.Enable
logger.Infof("MetricConfig's Enable was dynamically updated, new value:%v", mc.Enable)

extension.GetMetricReporter("prometheus", mc.ToReporterConfig())
extension.GetMetricReporter(mc.Protocol, mc.ToReporterConfig())
}
}
}
1 change: 1 addition & 0 deletions imports/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import (
_ "dubbo.apache.org/dubbo-go/v3/metadata/service/exporter/configurable"
_ "dubbo.apache.org/dubbo-go/v3/metadata/service/local"
_ "dubbo.apache.org/dubbo-go/v3/metadata/service/remote"
_ "dubbo.apache.org/dubbo-go/v3/metrics/app_info"
_ "dubbo.apache.org/dubbo-go/v3/metrics/prometheus"
_ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo"
_ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3"
Expand Down
161 changes: 161 additions & 0 deletions metrics/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package metrics

var registries = make(map[string]func(*ReporterConfig) MetricRegistry)
var collectors = make([]CollectorFunc, 0)
var registry MetricRegistry

// CollectorFunc 各个指标处理模块扩展
type CollectorFunc func(MetricRegistry, *ReporterConfig)

// Init 整个 Metrics 模块初始化入口
func Init(config *ReporterConfig) {
// config.extention = prometheus
regFunc, ok := registries[config.Protocol]
if !ok {
regFunc = registries["prometheus"] // default
}
registry = regFunc(config)
for _, co := range collectors {
co(registry, config)
}
registry.Export()
}

// SetRegistry 扩展其他数据容器,暴露方式,内置 Prometheus 实现
func SetRegistry(name string, v func(*ReporterConfig) MetricRegistry) {
registries[name] = v
}

// AddCollector 扩展指标收集器,例如 metadata、耗时、配置中心等
func AddCollector(name string, fun func(MetricRegistry, *ReporterConfig)) {
collectors = append(collectors, fun)
}

// MetricRegistry 数据指标容器,指标计算、指标暴露、聚合
type MetricRegistry interface {
Counter(*MetricId) CounterMetric // add or update a counter
Gauge(*MetricId) GaugeMetric // add or update a gauge
Histogram(*MetricId) HistogramMetric // add a metric num to a histogram
Summary(*MetricId) SummaryMetric // add a metric num to a summary
Export() // 数据暴露, 如 Prometheus 是 http 暴露
// GetMetrics() []*MetricSample // 获取所有指标数据
// GetMetricsString() (string, error) // 如需复用端口则加一下这个接口
}

// 组合暴露方式,参考 micrometer CompositeMeterRegistry
//type CompositeRegistry struct {
// rs []MetricRegistry
//}

// Type 指标类型,暂定和 micrometer 一致
type Type uint8

const (
Counter Type = iota
Gauge
LongTaskTimer
Timer
DistributionSummary
Other
)

// MetricId
// # HELP dubbo_metadata_store_provider_succeed_total Succeed Store Provider Metadata
// # TYPE dubbo_metadata_store_provider_succeed_total gauge
// dubbo_metadata_store_provider_succeed_total{application_name="provider",hostname="localhost",interface="org.example.DemoService",ip="10.252.156.213",} 1.0
// 除值以外的其他属性
type MetricId struct {
Name string
Desc string
Tags map[string]string
Type Type
}

func (m *MetricId) TagKeys() []string {
keys := make([]string, 0, len(m.Tags))
for k := range m.Tags {
keys = append(keys, k)
}
return keys
}

// MetricSample 一个指标的完整定义,包含值,这是指标的最终呈现,不是中间值(如 summary,histogram 他们统计完后会导出为一组 MetricSample)
type MetricSample struct {
*MetricId
value float64
}

// CounterMetric 指标抽象接口
type CounterMetric interface {
Inc()
Add(float64)
}

// GaugeMetric 指标抽象接口
type GaugeMetric interface {
Set(float64)
// Inc()
// Dec()
// Add(float64)
// Sub(float64)
}

// HistogramMetric 指标抽象接口
type HistogramMetric interface {
Record(float64)
}

// SummaryMetric 指标抽象接口
type SummaryMetric interface {
Record(float64)
}

// StatesMetrics 综合指标,包括总数、成功数,失败数,调用 MetricsRegistry 实现最终暴露
type StatesMetrics interface {
Success()
AddSuccess(float64)
Fail()
AddFailed(float64)
}

func NewStatesMetrics(total *MetricId, succ *MetricId, fail *MetricId) StatesMetrics {
return &DefaultStatesMetric{total: total, succ: succ, fail: fail, r: registry}
}

// TimeMetrics 综合指标, 包括 min(Gauge)、max(Gauge)、avg(Gauge)、sum(Gauge)、last(Gauge),调用 MetricRegistry 实现最终暴露
// 参见 dubbo-java org.apache.dubbo.metrics.aggregate.TimeWindowAggregator 类实现
type TimeMetrics interface {
Record(float64)
}

// NewTimeMetrics init and write all data to registry
func NewTimeMetrics(min *MetricId, avg *MetricId, max *MetricId, last *MetricId, sum *MetricId) {

}

type DefaultStatesMetric struct {
r MetricRegistry
total *MetricId
succ *MetricId
fail *MetricId
}

func (c DefaultStatesMetric) Success() {
c.r.Counter(c.total).Inc()
c.r.Counter(c.succ).Inc()
}

func (c DefaultStatesMetric) AddSuccess(v float64) {
c.r.Counter(c.total).Add(v)
c.r.Counter(c.succ).Add(v)
}

func (c DefaultStatesMetric) Fail() {
c.r.Counter(c.total).Inc()
c.r.Counter(c.fail).Inc()
}

func (c DefaultStatesMetric) AddFailed(v float64) {
c.r.Counter(c.total).Add(v)
c.r.Counter(c.fail).Add(v)
}
36 changes: 36 additions & 0 deletions metrics/app_info/application_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 app_info

import (
"dubbo.apache.org/dubbo-go/v3/metrics"
"dubbo.apache.org/dubbo-go/v3/metrics/common"
)

/*
* # HELP dubbo_application_info_total Total Application Info
* # TYPE dubbo_application_info_total counter
* dubbo_application_info_total{application_name="metrics-provider",application_version="3.2.1",git_commit_id="20de8b22ffb2a23531f6d9494a4963fcabd52561",hostname="localhost",ip="127.0.0.1",} 1.0
*/
var info = common.NewMetricKey("dubbo_application_info_total", "Total Application Info") // Total Application Info include application name、version etc

func init() {
metrics.AddCollector("application_info", func(mr metrics.MetricRegistry, config *metrics.ReporterConfig) {
mr.Counter(&metrics.MetricId{Name: info.Name, Desc: info.Desc, Tags: common.NewApplicationLevel().Tags()}).Inc()
})
}
101 changes: 101 additions & 0 deletions metrics/common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package common

import (
"dubbo.apache.org/dubbo-go/v3/common"
"dubbo.apache.org/dubbo-go/v3/config"
)

const (
TagIp = "ip"
TagPid = "pid"
TagHostname = "hostname"
TagApplicationName = "application_name"
TagApplicationModule = "application_module_id"
TagInterfaceKey = "interface"
TagMethodKey = "method"
TagGroupKey = "group"
TagVersionKey = "version"
TagApplicationVersionKey = "application_version"
TagKeyKey = "key"
TagConfigCenter = "config_center"
TagChangeType = "change_type"
TagThreadName = "thread_pool_name"
TagGitCommitId = "git_commit_id"
)

type MetricKey struct {
Name string
Desc string
}

func NewMetricKey(name string, desc string) *MetricKey {
return &MetricKey{Name: name, Desc: desc}
}

type MetricLevel interface {
Tags() map[string]string
}

type ApplicationMetricLevel struct {
ApplicationName string
Version string
GitCommitId string
Ip string
HostName string
}

var appLevel *ApplicationMetricLevel

func NewApplicationLevel() *ApplicationMetricLevel {
if appLevel == nil {
var rootConfig = config.GetRootConfig()
appLevel = &ApplicationMetricLevel{
ApplicationName: rootConfig.Application.Name,
Version: rootConfig.Application.Version,
Ip: common.GetLocalIp(),
HostName: common.GetLocalHostName(),
GitCommitId: "",
}
}
return appLevel
}

func (m *ApplicationMetricLevel) Tags() map[string]string {
tags := make(map[string]string)
tags[TagIp] = m.Ip
tags[TagHostname] = m.HostName
tags[TagApplicationName] = m.ApplicationName
tags[TagApplicationVersionKey] = m.Version
tags[TagGitCommitId] = m.GitCommitId
return tags
}

type ServiceMetricLevel struct {
*ApplicationMetricLevel
Interface string
}

func NewServiceMetric(interfaceName string) *ServiceMetricLevel {
return &ServiceMetricLevel{ApplicationMetricLevel: NewApplicationLevel(), Interface: interfaceName}
}

func (m ServiceMetricLevel) Tags() map[string]string {
tags := m.ApplicationMetricLevel.Tags()
tags[TagInterfaceKey] = m.Interface
return tags
}

type MethodMetricLevel struct {
*ServiceMetricLevel
Method string
Group string
Version string
}

func (m MethodMetricLevel) Tags() map[string]string {
tags := m.ServiceMetricLevel.Tags()
tags[TagMethodKey] = m.Method
tags[TagGroupKey] = m.Group
tags[TagVersionKey] = m.Version
return tags
}
Loading

0 comments on commit 2a4625d

Please sign in to comment.