istio

Форк
0
/
gauge.go 
104 строки · 2.9 Кб
1
// Copyright Istio Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package monitoring
16

17
import (
18
	"context"
19
	"sync"
20

21
	"go.opentelemetry.io/otel/attribute"
22
	api "go.opentelemetry.io/otel/metric"
23

24
	"istio.io/istio/pkg/log"
25
)
26

27
type gauge struct {
28
	baseMetric
29
	g api.Float64ObservableGauge
30

31
	// attributeSets stores a map of attributes -> values, for gauges.
32
	attributeSetsMutex *sync.RWMutex
33
	attributeSets      map[attribute.Set]*gaugeValues
34
	currentGaugeSet    *gaugeValues
35
}
36

37
var _ Metric = &gauge{}
38

39
func newGauge(o options) *gauge {
40
	r := &gauge{
41
		attributeSetsMutex: &sync.RWMutex{},
42
	}
43
	r.attributeSets = map[attribute.Set]*gaugeValues{}
44
	g, err := meter().Float64ObservableGauge(o.name,
45
		api.WithFloat64Callback(func(ctx context.Context, observer api.Float64Observer) error {
46
			r.attributeSetsMutex.Lock()
47
			defer r.attributeSetsMutex.Unlock()
48
			for _, gv := range r.attributeSets {
49
				observer.Observe(gv.val, gv.opt...)
50
			}
51
			return nil
52
		}),
53
		api.WithDescription(o.description),
54
		api.WithUnit(string(o.unit)))
55
	if err != nil {
56
		log.Fatalf("failed to create gauge: %v", err)
57
	}
58
	r.g = g
59
	r.baseMetric = baseMetric{
60
		name: o.name,
61
		rest: r,
62
	}
63
	return r
64
}
65

66
func (f *gauge) Record(value float64) {
67
	f.runRecordHook(value)
68
	// TODO: https://github.com/open-telemetry/opentelemetry-specification/issues/2318 use synchronous gauge so we don't need to deal with this
69
	f.attributeSetsMutex.Lock()
70
	// Special case: we lazy-load the non-labeled value. This ensures that metrics which should always have labels do not end up with a un-labeled zero-value
71
	// If a metric really requires `metric{} 0`, they can explicitly call .Record(0).
72
	if f.currentGaugeSet == nil {
73
		f.currentGaugeSet = &gaugeValues{}
74
		f.attributeSets[attribute.NewSet()] = f.currentGaugeSet
75
	}
76
	f.currentGaugeSet.val = value
77
	f.attributeSetsMutex.Unlock()
78
}
79

80
func (f *gauge) With(labelValues ...LabelValue) Metric {
81
	attrs, set := rebuildAttributes(f.baseMetric, labelValues)
82
	nm := &gauge{
83
		g:                  f.g,
84
		attributeSetsMutex: f.attributeSetsMutex,
85
		attributeSets:      f.attributeSets,
86
	}
87
	if _, f := nm.attributeSets[set]; !f {
88
		nm.attributeSets[set] = &gaugeValues{
89
			opt: []api.ObserveOption{api.WithAttributeSet(set)},
90
		}
91
	}
92
	nm.currentGaugeSet = nm.attributeSets[set]
93
	nm.baseMetric = baseMetric{
94
		name:  f.name,
95
		attrs: attrs,
96
		rest:  nm,
97
	}
98
	return nm
99
}
100

101
type gaugeValues struct {
102
	val float64
103
	opt []api.ObserveOption
104
}
105

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.