1
0
Fork 0

Opentracing support

This commit is contained in:
Michael 2018-01-10 17:48:04 +01:00 committed by Traefiker
parent 8394549857
commit 30ffba78e6
272 changed files with 44352 additions and 63 deletions

28
vendor/github.com/uber/jaeger-lib/metrics/counter.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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
// Counter tracks the number of times an event has occurred
type Counter interface {
// Inc adds the given value to the counter.
Inc(int64)
}
// NullCounter counter that does nothing
var NullCounter Counter = nullCounter{}
type nullCounter struct{}
func (nullCounter) Inc(int64) {}

35
vendor/github.com/uber/jaeger-lib/metrics/factory.go generated vendored Normal file
View file

@ -0,0 +1,35 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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
// Factory creates new metrics
type Factory interface {
Counter(name string, tags map[string]string) Counter
Timer(name string, tags map[string]string) Timer
Gauge(name string, tags map[string]string) Gauge
// Namespace returns a nested metrics factory.
Namespace(name string, tags map[string]string) Factory
}
// NullFactory is a metrics factory that returns NullCounter, NullTimer, and NullGauge.
var NullFactory Factory = nullFactory{}
type nullFactory struct{}
func (nullFactory) Counter(name string, tags map[string]string) Counter { return NullCounter }
func (nullFactory) Timer(name string, tags map[string]string) Timer { return NullTimer }
func (nullFactory) Gauge(name string, tags map[string]string) Gauge { return NullGauge }
func (nullFactory) Namespace(name string, tags map[string]string) Factory { return NullFactory }

28
vendor/github.com/uber/jaeger-lib/metrics/gauge.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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
// Gauge returns instantaneous measurements of something as an int64 value
type Gauge interface {
// Update the gauge to the value passed in.
Update(int64)
}
// NullGauge gauge that does nothing
var NullGauge Gauge = nullGauge{}
type nullGauge struct{}
func (nullGauge) Update(int64) {}

332
vendor/github.com/uber/jaeger-lib/metrics/local.go generated vendored Normal file
View file

@ -0,0 +1,332 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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
import (
"sort"
"sync"
"sync/atomic"
"time"
"github.com/codahale/hdrhistogram"
)
// This is intentionally very similar to github.com/codahale/metrics, the
// main difference being that counters/gauges are scoped to the provider
// rather than being global (to facilitate testing).
// A LocalBackend is a metrics provider which aggregates data in-vm, and
// allows exporting snapshots to shove the data into a remote collector
type LocalBackend struct {
cm sync.Mutex
gm sync.Mutex
tm sync.Mutex
counters map[string]*int64
gauges map[string]*int64
timers map[string]*localBackendTimer
stop chan struct{}
wg sync.WaitGroup
TagsSep string
TagKVSep string
}
// NewLocalBackend returns a new LocalBackend. The collectionInterval is the histogram
// time window for each timer.
func NewLocalBackend(collectionInterval time.Duration) *LocalBackend {
b := &LocalBackend{
counters: make(map[string]*int64),
gauges: make(map[string]*int64),
timers: make(map[string]*localBackendTimer),
stop: make(chan struct{}),
TagsSep: "|",
TagKVSep: "=",
}
if collectionInterval == 0 {
// Use one histogram time window for all timers
return b
}
b.wg.Add(1)
go b.runLoop(collectionInterval)
return b
}
// Clear discards accumulated stats
func (b *LocalBackend) Clear() {
b.cm.Lock()
defer b.cm.Unlock()
b.gm.Lock()
defer b.gm.Unlock()
b.tm.Lock()
defer b.tm.Unlock()
b.counters = make(map[string]*int64)
b.gauges = make(map[string]*int64)
b.timers = make(map[string]*localBackendTimer)
}
func (b *LocalBackend) runLoop(collectionInterval time.Duration) {
defer b.wg.Done()
ticker := time.NewTicker(collectionInterval)
for {
select {
case <-ticker.C:
b.tm.Lock()
timers := make(map[string]*localBackendTimer, len(b.timers))
for timerName, timer := range b.timers {
timers[timerName] = timer
}
b.tm.Unlock()
for _, t := range timers {
t.Lock()
t.hist.Rotate()
t.Unlock()
}
case <-b.stop:
ticker.Stop()
return
}
}
}
// IncCounter increments a counter value
func (b *LocalBackend) IncCounter(name string, tags map[string]string, delta int64) {
name = GetKey(name, tags, b.TagsSep, b.TagKVSep)
b.cm.Lock()
defer b.cm.Unlock()
counter := b.counters[name]
if counter == nil {
b.counters[name] = new(int64)
*b.counters[name] = delta
return
}
atomic.AddInt64(counter, delta)
}
// UpdateGauge updates the value of a gauge
func (b *LocalBackend) UpdateGauge(name string, tags map[string]string, value int64) {
name = GetKey(name, tags, b.TagsSep, b.TagKVSep)
b.gm.Lock()
defer b.gm.Unlock()
gauge := b.gauges[name]
if gauge == nil {
b.gauges[name] = new(int64)
*b.gauges[name] = value
return
}
atomic.StoreInt64(gauge, value)
}
// RecordTimer records a timing duration
func (b *LocalBackend) RecordTimer(name string, tags map[string]string, d time.Duration) {
name = GetKey(name, tags, b.TagsSep, b.TagKVSep)
timer := b.findOrCreateTimer(name)
timer.Lock()
timer.hist.Current.RecordValue(int64(d / time.Millisecond))
timer.Unlock()
}
func (b *LocalBackend) findOrCreateTimer(name string) *localBackendTimer {
b.tm.Lock()
defer b.tm.Unlock()
if t, ok := b.timers[name]; ok {
return t
}
t := &localBackendTimer{
hist: hdrhistogram.NewWindowed(5, 0, int64((5*time.Minute)/time.Millisecond), 1),
}
b.timers[name] = t
return t
}
type localBackendTimer struct {
sync.Mutex
hist *hdrhistogram.WindowedHistogram
}
var (
percentiles = map[string]float64{
"P50": 50,
"P75": 75,
"P90": 90,
"P95": 95,
"P99": 99,
"P999": 99.9,
}
)
// Snapshot captures a snapshot of the current counter and gauge values
func (b *LocalBackend) Snapshot() (counters, gauges map[string]int64) {
b.cm.Lock()
defer b.cm.Unlock()
counters = make(map[string]int64, len(b.counters))
for name, value := range b.counters {
counters[name] = atomic.LoadInt64(value)
}
b.gm.Lock()
defer b.gm.Unlock()
gauges = make(map[string]int64, len(b.gauges))
for name, value := range b.gauges {
gauges[name] = atomic.LoadInt64(value)
}
b.tm.Lock()
timers := make(map[string]*localBackendTimer)
for timerName, timer := range b.timers {
timers[timerName] = timer
}
b.tm.Unlock()
for timerName, timer := range timers {
timer.Lock()
hist := timer.hist.Merge()
timer.Unlock()
for name, q := range percentiles {
gauges[timerName+"."+name] = hist.ValueAtQuantile(q)
}
}
return
}
// Stop cleanly closes the background goroutine spawned by NewLocalBackend.
func (b *LocalBackend) Stop() {
close(b.stop)
b.wg.Wait()
}
// GetKey converts name+tags into a single string of the form
// "name|tag1=value1|...|tagN=valueN", where tag names are
// sorted alphabetically.
func GetKey(name string, tags map[string]string, tagsSep string, tagKVSep string) string {
keys := make([]string, 0, len(tags))
for k := range tags {
keys = append(keys, k)
}
sort.Strings(keys)
key := name
for _, k := range keys {
key = key + tagsSep + k + tagKVSep + tags[k]
}
return key
}
type stats struct {
name string
tags map[string]string
localBackend *LocalBackend
}
type localTimer struct {
stats
}
func (l *localTimer) Record(d time.Duration) {
l.localBackend.RecordTimer(l.name, l.tags, d)
}
type localCounter struct {
stats
}
func (l *localCounter) Inc(delta int64) {
l.localBackend.IncCounter(l.name, l.tags, delta)
}
type localGauge struct {
stats
}
func (l *localGauge) Update(value int64) {
l.localBackend.UpdateGauge(l.name, l.tags, value)
}
// LocalFactory stats factory that creates metrics that are stored locally
type LocalFactory struct {
*LocalBackend
namespace string
tags map[string]string
}
// NewLocalFactory returns a new LocalMetricsFactory
func NewLocalFactory(collectionInterval time.Duration) *LocalFactory {
return &LocalFactory{
LocalBackend: NewLocalBackend(collectionInterval),
}
}
// appendTags adds the tags to the namespace tags and returns a combined map.
func (l *LocalFactory) appendTags(tags map[string]string) map[string]string {
newTags := make(map[string]string)
for k, v := range l.tags {
newTags[k] = v
}
for k, v := range tags {
newTags[k] = v
}
return newTags
}
func (l *LocalFactory) newNamespace(name string) string {
if l.namespace == "" {
return name
}
return l.namespace + "." + name
}
// Counter returns a local stats counter
func (l *LocalFactory) Counter(name string, tags map[string]string) Counter {
return &localCounter{
stats{
name: l.newNamespace(name),
tags: l.appendTags(tags),
localBackend: l.LocalBackend,
},
}
}
// Timer returns a local stats timer.
func (l *LocalFactory) Timer(name string, tags map[string]string) Timer {
return &localTimer{
stats{
name: l.newNamespace(name),
tags: l.appendTags(tags),
localBackend: l.LocalBackend,
},
}
}
// Gauge returns a local stats gauge.
func (l *LocalFactory) Gauge(name string, tags map[string]string) Gauge {
return &localGauge{
stats{
name: l.newNamespace(name),
tags: l.appendTags(tags),
localBackend: l.LocalBackend,
},
}
}
// Namespace returns a new namespace.
func (l *LocalFactory) Namespace(name string, tags map[string]string) Factory {
return &LocalFactory{
namespace: l.newNamespace(name),
tags: l.appendTags(tags),
LocalBackend: l.LocalBackend,
}
}

85
vendor/github.com/uber/jaeger-lib/metrics/metrics.go generated vendored Normal file
View file

@ -0,0 +1,85 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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
import (
"fmt"
"reflect"
"strings"
)
// Init initializes the passed in metrics and initializes its fields using the passed in factory.
func Init(metrics interface{}, factory Factory, globalTags map[string]string) {
if err := initMetrics(metrics, factory, globalTags); err != nil {
panic(err.Error())
}
}
// initMetrics uses reflection to initialize a struct containing metrics fields
// by assigning new Counter/Gauge/Timer values with the metric name retrieved
// from the `metric` tag and stats tags retrieved from the `tags` tag.
//
// Note: all fields of the struct must be exported, have a `metric` tag, and be
// of type Counter or Gauge or Timer.
func initMetrics(m interface{}, factory Factory, globalTags map[string]string) error {
// Allow user to opt out of reporting metrics by passing in nil.
if factory == nil {
factory = NullFactory
}
counterPtrType := reflect.TypeOf((*Counter)(nil)).Elem()
gaugePtrType := reflect.TypeOf((*Gauge)(nil)).Elem()
timerPtrType := reflect.TypeOf((*Timer)(nil)).Elem()
v := reflect.ValueOf(m).Elem()
t := v.Type()
for i := 0; i < t.NumField(); i++ {
tags := make(map[string]string)
for k, v := range globalTags {
tags[k] = v
}
field := t.Field(i)
metric := field.Tag.Get("metric")
if metric == "" {
return fmt.Errorf("Field %s is missing a tag 'metric'", field.Name)
}
if tagString := field.Tag.Get("tags"); tagString != "" {
tagPairs := strings.Split(tagString, ",")
for _, tagPair := range tagPairs {
tag := strings.Split(tagPair, "=")
if len(tag) != 2 {
return fmt.Errorf(
"Field [%s]: Tag [%s] is not of the form key=value in 'tags' string [%s]",
field.Name, tagPair, tagString)
}
tags[tag[0]] = tag[1]
}
}
var obj interface{}
if field.Type.AssignableTo(counterPtrType) {
obj = factory.Counter(metric, tags)
} else if field.Type.AssignableTo(gaugePtrType) {
obj = factory.Gauge(metric, tags)
} else if field.Type.AssignableTo(timerPtrType) {
obj = factory.Timer(metric, tags)
} else {
return fmt.Errorf(
"Field %s is not a pointer to timer, gauge, or counter",
field.Name)
}
v.Field(i).Set(reflect.ValueOf(obj))
}
return nil
}

43
vendor/github.com/uber/jaeger-lib/metrics/stopwatch.go generated vendored Normal file
View file

@ -0,0 +1,43 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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
import (
"time"
)
// StartStopwatch begins recording the executing time of an event, returning
// a Stopwatch that should be used to stop the recording the time for
// that event. Multiple events can be occurring simultaneously each
// represented by different active Stopwatches
func StartStopwatch(timer Timer) Stopwatch {
return Stopwatch{t: timer, start: time.Now()}
}
// A Stopwatch tracks the execution time of a specific event
type Stopwatch struct {
t Timer
start time.Time
}
// Stop stops executing of the stopwatch and records the amount of elapsed time
func (s Stopwatch) Stop() {
s.t.Record(s.ElapsedTime())
}
// ElapsedTime returns the amount of elapsed time (in time.Duration)
func (s Stopwatch) ElapsedTime() time.Duration {
return time.Since(s.start)
}

33
vendor/github.com/uber/jaeger-lib/metrics/timer.go generated vendored Normal file
View file

@ -0,0 +1,33 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed 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
import (
"time"
)
// Timer accumulates observations about how long some operation took,
// and also maintains a historgam of percentiles.
type Timer interface {
// Records the time passed in.
Record(time.Duration)
}
// NullTimer timer that does nothing
var NullTimer Timer = nullTimer{}
type nullTimer struct{}
func (nullTimer) Record(time.Duration) {}