blob: 4b4342cff5819fa6320de01928d88ca7231290d4 [file] [log] [blame]
// Licensed to 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. Apache Software Foundation (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 metrics
func newMeterOpts() *Opts {
return &Opts{labels: make(map[string]string)}
}
func (b *Opts) GetLabels() map[string]string {
return b.labels
}
type counterImpl struct {
name string
val float64
labels map[string]string
getFunc func() float64
addFunc func(float64)
}
func newDefaultCounter(name string, opt ...Opt) *counterImpl {
result := &counterImpl{name: name, val: 0}
opts := newMeterOpts()
for _, o := range opt {
o(opts)
}
result.labels = opts.GetLabels()
result.getFunc = func() float64 {
return result.val
}
result.addFunc = func(f float64) {
result.val += f
}
return result
}
func (c *counterImpl) Name() string {
return c.name
}
func (c *counterImpl) Get() float64 {
return c.getFunc()
}
func (c *counterImpl) Labels() map[string]string {
return c.labels
}
func (c *counterImpl) Inc(val float64) {
c.addFunc(val)
}
func (c *counterImpl) ChangeFunctions(add func(v float64), get func() float64) {
c.addFunc = add
c.getFunc = get
}
type gaugeImpl struct {
name string
labels map[string]string
getter func() float64
}
func newDefaultGauge(name string, getter func() float64, opt ...Opt) *gaugeImpl {
result := &gaugeImpl{name: name, getter: getter}
opts := newMeterOpts()
for _, o := range opt {
o(opts)
}
result.labels = opts.GetLabels()
return result
}
func (g *gaugeImpl) Name() string {
return g.name
}
func (g *gaugeImpl) Labels() map[string]string {
return g.labels
}
func (g *gaugeImpl) Get() float64 {
return g.getter()
}
func (g *gaugeImpl) Getter() func() float64 {
return g.getter
}
type histogramImpl struct {
name string
labels map[string]string
buckets []*histogramBucket
observeFunc func(float64)
observeWithCountFunc func(float64, int64)
}
type histogramBucket struct {
bucket float64
val *int64
}
func newDefaultHistogram(name string, minVal float64, steps []float64, opt ...Opt) *histogramImpl {
result := &histogramImpl{name: name}
opts := newMeterOpts()
for _, o := range opt {
o(opts)
}
result.labels = opts.GetLabels()
result.initBuckets(minVal, steps)
result.observeFunc = func(f float64) {
b := result.findBucket(f)
if b != nil {
*b.val++
}
}
result.observeWithCountFunc = func(f float64, c int64) {
b := result.findBucket(f)
if b != nil {
*b.val += c
}
}
return result
}
func (h *histogramImpl) Observe(val float64) {
h.observeFunc(val)
}
func (h *histogramImpl) ObserveWithCount(val float64, c int64) {
h.observeWithCountFunc(val, c)
}
func (h *histogramImpl) findBucket(v float64) *histogramBucket {
var low, high = 0, len(h.buckets) - 1
for low <= high {
var mid = (low + high) / 2
if h.buckets[mid].bucket < v {
low = mid + 1
} else if h.buckets[mid].bucket > v {
high = mid - 1
} else {
return h.buckets[mid]
}
}
low--
if low < len(h.buckets) && low >= 0 {
return h.buckets[low]
}
return nil
}
func (h *histogramImpl) initBuckets(minVal float64, steps []float64) {
n := len(steps)
for i := 1; i < n; i++ {
key := steps[i]
j := i - 1
if steps[j] == key {
panic("duplicate steps found")
}
for j >= 0 && steps[j] > key {
steps[j+1] = steps[j]
j--
}
steps[j+1] = key
}
if steps[0] != minVal {
steps = append([]float64{minVal}, steps...)
}
buckets := make([]*histogramBucket, len(steps))
for i, step := range steps {
buckets[i] = &histogramBucket{bucket: step, val: new(int64)}
}
h.buckets = buckets
}
func (h *histogramImpl) Name() string {
return h.name
}
func (h *histogramImpl) Labels() map[string]string {
return h.labels
}
func (h *histogramImpl) Buckets() []interface{} {
result := make([]interface{}, len(h.buckets))
for i, b := range h.buckets {
result[i] = b
}
return result
}
func (h *histogramImpl) ChangeFunctions(observe func(v float64), observeWithCount func(v float64, c int64)) {
h.observeFunc = observe
h.observeWithCountFunc = observeWithCount
}
func (h *histogramBucket) Bucket() float64 {
return h.bucket
}
func (h *histogramBucket) Value() *int64 {
return h.val
}