Skip to content

Commit

Permalink
refactor: adapt to Go 1.17 and bundle gaugeVec with syncMap
Browse files Browse the repository at this point in the history
  • Loading branch information
ev1lQuark committed Jun 19, 2023
1 parent cd3d6dc commit 17cfbc9
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 27 deletions.
13 changes: 4 additions & 9 deletions metrics/prometheus/metric_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package prometheus

import (
"strings"
"sync"
)

import (
Expand All @@ -44,8 +43,7 @@ type metricSet struct {
// The number of requests successfully received by the provider
providerRequestsSucceedTotalCounterVec *prometheus.CounterVec

providerRTMillisecondsMinGaugeVec *prometheus.GaugeVec
providerRTMillisecondsMinSyncMap *sync.Map
providerRTMillisecondsMinGaugeVecWithSyncMap *GaugeVecWithSyncMap

// report the consumer-side's request total counter data
consumerRequestsTotalCounterVec *prometheus.CounterVec
Expand All @@ -54,8 +52,7 @@ type metricSet struct {
// The number of successful requests sent by consumers
consumerRequestsSucceedTotalCounterVec *prometheus.CounterVec

consumerRTMillisecondsMinGaugeVec *prometheus.GaugeVec
consumerRTMillisecondsMinSyncMap *sync.Map
consumerRTMillisecondsMinGaugeVecWithSyncMap *GaugeVecWithSyncMap
}

var labelNames = []string{applicationNameKey, groupKey, hostnameKey, interfaceKey, ipKey, methodKey, versionKey}
Expand All @@ -70,10 +67,8 @@ func (ms *metricSet) initAndRegister(reporterConfig *metrics.ReporterConfig) {
ms.providerRequestsProcessingTotalGaugeVec = newAutoGaugeVec(buildMetricsName(providerField, requestsField, processingField, totalField), reporterConfig.Namespace, labelNames)
ms.consumerRequestsSucceedTotalCounterVec = newAutoCounterVec(buildMetricsName(consumerField, requestsField, succeedField, totalField), reporterConfig.Namespace, labelNames)
ms.providerRequestsSucceedTotalCounterVec = newAutoCounterVec(buildMetricsName(providerField, requestsField, succeedField, totalField), reporterConfig.Namespace, labelNames)
ms.consumerRTMillisecondsMinGaugeVec = newAutoGaugeVec(buildMetricsName(consumerField, rtField, milliSecondsField, minField), reporterConfig.Namespace, labelNames)
ms.consumerRTMillisecondsMinSyncMap = &sync.Map{}
ms.providerRTMillisecondsMinGaugeVec = newAutoGaugeVec(buildMetricsName(providerField, rtField, milliSecondsField, minField), reporterConfig.Namespace, labelNames)
ms.providerRTMillisecondsMinSyncMap = &sync.Map{}
ms.consumerRTMillisecondsMinGaugeVecWithSyncMap = newAutoGaugeVecWithSyncMap(buildMetricsName(consumerField, rtField, milliSecondsField, minField), reporterConfig.Namespace, labelNames)
ms.providerRTMillisecondsMinGaugeVecWithSyncMap = newAutoGaugeVecWithSyncMap(buildMetricsName(providerField, rtField, milliSecondsField, minField), reporterConfig.Namespace, labelNames)
}

func buildMetricsName(args ...string) string {
Expand Down
11 changes: 2 additions & 9 deletions metrics/prometheus/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,10 @@ func (reporter *PrometheusReporter) incRequestsSucceedTotalCounterVec(role strin
}

func (reporter *PrometheusReporter) updateRTMillisecondsMinGaugeVec(role string, labels *prometheus.Labels, costMs int64) {
var gaugeVec *prometheus.GaugeVec
var m *sync.Map

switch role {
case providerField:
gaugeVec = reporter.providerRTMillisecondsMinGaugeVec
m = reporter.providerRTMillisecondsMinSyncMap
go reporter.providerRTMillisecondsMinGaugeVecWithSyncMap.updateMin(labels, costMs)
case consumerField:
gaugeVec = reporter.consumerRTMillisecondsMinGaugeVec
m = reporter.consumerRTMillisecondsMinSyncMap
go reporter.consumerRTMillisecondsMinGaugeVecWithSyncMap.updateMin(labels, costMs)
}

go updateMin(m, labels, gaugeVec, costMs)
}
35 changes: 26 additions & 9 deletions metrics/prometheus/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,25 @@ package prometheus
import (
"strings"
"sync"
"sync/atomic"
)

import (
"github.com/prometheus/client_golang/prometheus"
)

type GaugeVecWithSyncMap struct {
GaugeVec *prometheus.GaugeVec
SyncMap *sync.Map
}

func newAutoGaugeVecWithSyncMap(name, namespace string, labels []string) *GaugeVecWithSyncMap {
return &GaugeVecWithSyncMap{
GaugeVec: newAutoGaugeVec(name, namespace, labels),
SyncMap: &sync.Map{},
}
}

func convertLabelsToMapKey(labels prometheus.Labels) string {
return strings.Join([]string{
labels[applicationNameKey],
Expand All @@ -38,24 +51,28 @@ func convertLabelsToMapKey(labels prometheus.Labels) string {
}, "_")
}

func updateMin(m *sync.Map, labels *prometheus.Labels, gaugeVec *prometheus.GaugeVec, costMs int64) {
func (gv *GaugeVecWithSyncMap) updateMin(labels *prometheus.Labels, curValue int64) {
key := convertLabelsToMapKey(*labels)
cur := &atomic.Int64{} // for first store
cur.Store(curValue)
for {
if actual, loaded := m.LoadOrStore(key, costMs); loaded {
if costMs < actual.(int64) {
// need to update
if m.CompareAndSwap(key, actual, costMs) {
// value is not changed, update success
gaugeVec.With(*labels).Set(float64(costMs))
if actual, loaded := gv.SyncMap.LoadOrStore(key, cur); loaded {
store := actual.(*atomic.Int64)
storeValue := store.Load()
if curValue < storeValue {
if store.CompareAndSwap(storeValue, curValue) {
// value is not changed, should update
gv.GaugeVec.With(*labels).Set(float64(curValue))
break
}
// value has changed, continue for loop
} else {
// no need to update
break
}
} else {
// store current costMs as this labels' init value
gaugeVec.With(*labels).Set(float64(costMs))
// store current curValue as this labels' init value
gv.GaugeVec.With(*labels).Set(float64(curValue))
break
}
}
Expand Down

0 comments on commit 17cfbc9

Please sign in to comment.