metric

package
v3.0.8+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2017 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package metric contains adaptors of metrics collectors used for gentle-ments in gentle. Currently prometheus and statsd are supported.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidLabel = errors.New("Invalid label")
)

Functions

This section is empty.

Types

type PromCbMetric

type PromCbMetric struct {
	// contains filtered or unexported fields
}

func NewPromCbMetric

func NewPromCbMetric(
	histOpts prom.HistogramOpts,
	counterOpts prom.CounterOpts,
	resultLabel ResultLabel, cbErrLabelName string) (*PromCbMetric, error)
Example
gentle.CircuitReset()
opts := gentle.NewCircuitStreamOpts("", "test3", "test_circuit")
opts.CbMetric, _ = NewPromCbMetric(prom.HistogramOpts{
	Help:      "duration of CircuitStream.Get()",
	Namespace: "test",
	Subsystem: "circuit",
	Name:      "example_seconds",
	Buckets:   []float64{0.1, 0.5, 1, 2.5},
	ConstLabels: prom.Labels{
		"host": "localhost",
	},
}, prom.CounterOpts{
	Help:      "totals of different errors",
	Namespace: "test",
	Subsystem: "circuit",
	Name:      "example_total",
	ConstLabels: prom.Labels{
		"host": "localhost",
	},
}, ResultLabel{
	Name:     "result",
	ValueOk:  "ok",
	ValueErr: "err",
}, "cbErr")

okRun := 3
totalRun := 6
var upstream gentle.SimpleStream = func(ctx context.Context) (gentle.Message, error) {
	if okRun > 0 {
		okRun--
		return gentle.SimpleMessage(""), nil
	}
	return nil, gentle.ErrCbOpen
}

stream := gentle.NewCircuitStream(opts, upstream)
for i := 0; i < totalRun; i++ {
	stream.Get(context.Background())
}

bs, err := scrap()
if err != nil {
	log.Fatalf("scrap() err: %s\n", err)
}
// # HELP test_circuit_example_seconds duration of CircuitStream.Get()
// # TYPE test_circuit_example_seconds histogram
// test_circuit_example_seconds_bucket{host="localhost",result="err",le="0.1"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="err",le="0.5"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="err",le="1"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="err",le="2.5"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="err",le="+Inf"} 3
// test_circuit_example_seconds_sum{host="localhost",result="err"} 0.000357439
// test_circuit_example_seconds_count{host="localhost",result="err"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="ok",le="0.1"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="ok",le="0.5"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="ok",le="1"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="ok",le="2.5"} 3
// test_circuit_example_seconds_bucket{host="localhost",result="ok",le="+Inf"} 3
// test_circuit_example_seconds_sum{host="localhost",result="ok"} 0.000684208
// test_circuit_example_seconds_count{host="localhost",result="ok"} 3
// # HELP test_circuit_example_total totals of different errors
// # TYPE test_circuit_example_total counter
// test_circuit_example_total{cbErr="open",host="localhost"} 3
log.Print(string(bs))
Output:

func (*PromCbMetric) ObserveErr

func (m *PromCbMetric) ObserveErr(timespan time.Duration, err error)

func (*PromCbMetric) ObserveOk

func (m *PromCbMetric) ObserveOk(timespan time.Duration)

type PromMetric

type PromMetric struct {
	// contains filtered or unexported fields
}

func NewPromMetric

func NewPromMetric(
	histOpts prom.HistogramOpts,
	resultLabel ResultLabel) (*PromMetric, error)
Example
opts := gentle.NewRateLimitedStreamOpts("", "test1",
	gentle.NewTokenBucketRateLimit(time.Second, 1))
opts.Metric, _ = NewPromMetric(prom.HistogramOpts{
	Help:      "duration of RateLimitedStream.Get()",
	Namespace: "test",
	Subsystem: "rate",
	Name:      "example_seconds",
	Buckets:   []float64{0.1, 0.5, 1, 2.5},
	ConstLabels: prom.Labels{
		"host": "localhost",
	},
}, ResultLabel{
	Name:     "result",
	ValueOk:  "ok",
	ValueErr: "err",
})

okRun := 3
totalRun := 6
var upstream gentle.SimpleStream = func(ctx context.Context) (gentle.Message, error) {
	if okRun > 0 {
		okRun--
		return gentle.SimpleMessage(""), nil
	}
	return nil, errors.New("fake err")
}

stream := gentle.NewRateLimitedStream(opts, upstream)
for i := 0; i < totalRun; i++ {
	stream.Get(context.Background())
}

bs, err := scrap()
if err != nil {
	log.Fatalf("scrap() err: %s\n", err)
}
// # HELP test_rate_example_seconds duration of RateLimitedStream.Get()
// # TYPE test_rate_example_seconds histogram
// test_rate_example_seconds_bucket{host="localhost",result="err",le="0.1"} 0
// test_rate_example_seconds_bucket{host="localhost",result="err",le="0.5"} 0
// test_rate_example_seconds_bucket{host="localhost",result="err",le="1"} 1
// test_rate_example_seconds_bucket{host="localhost",result="err",le="2.5"} 3
// test_rate_example_seconds_bucket{host="localhost",result="err",le="+Inf"} 3
// test_rate_example_seconds_sum{host="localhost",result="err"} 2.998811008
// test_rate_example_seconds_count{host="localhost",result="err"} 3
// test_rate_example_seconds_bucket{host="localhost",result="ok",le="0.1"} 1
// test_rate_example_seconds_bucket{host="localhost",result="ok",le="0.5"} 1
// test_rate_example_seconds_bucket{host="localhost",result="ok",le="1"} 2
// test_rate_example_seconds_bucket{host="localhost",result="ok",le="2.5"} 3
// test_rate_example_seconds_bucket{host="localhost",result="ok",le="+Inf"} 3
// test_rate_example_seconds_sum{host="localhost",result="ok"} 2.001090599
// test_rate_example_seconds_count{host="localhost",result="ok"} 3
log.Print(string(bs))
Output:

func (*PromMetric) ObserveErr

func (m *PromMetric) ObserveErr(timespan time.Duration)

func (*PromMetric) ObserveOk

func (m *PromMetric) ObserveOk(timespan time.Duration)

type PromRetryMetric

type PromRetryMetric struct {
	// contains filtered or unexported fields
}

func NewPromRetryMetric

func NewPromRetryMetric(
	histOpts prom.HistogramOpts,
	counterOpts prom.CounterOpts,
	resultLabel, retryLabel ResultLabel) (*PromRetryMetric, error)
Example
factory := gentle.NewConstBackOffFactory(
	gentle.NewConstBackOffFactoryOpts(100*time.Millisecond, time.Second))
opts := gentle.NewRetryStreamOpts("", "test2", factory)
opts.RetryMetric, _ = NewPromRetryMetric(prom.HistogramOpts{
	Help:      "duration of RetryStream.Get()",
	Namespace: "test",
	Subsystem: "retry",
	Name:      "example_seconds",
	Buckets:   []float64{0.1, 0.5, 1, 2.5},
	ConstLabels: prom.Labels{
		"host": "localhost",
	},
}, prom.CounterOpts{
	Help:      "total of retries",
	Namespace: "test",
	Subsystem: "retry",
	Name:      "example_total",
	ConstLabels: prom.Labels{
		"host": "localhost",
	},
}, ResultLabel{
	Name:     "result",
	ValueOk:  "ok",
	ValueErr: "err",
}, ResultLabel{
	Name:     "retry",
	ValueOk:  "ok",
	ValueErr: "err",
})

okRun := 3
totalRun := 6
retryCount := 5
var upstream gentle.SimpleStream = func(ctx context.Context) (gentle.Message, error) {
	if okRun > 0 {
		// retry-run
		if retryCount == 0 {
			okRun--
			// reset for another okRun
			retryCount = 5
			return gentle.SimpleMessage(""), nil
		}
		retryCount--
		return nil, errors.New("fake err")
	}
	// errRun: always fall
	return nil, errors.New("fake err")
}

stream := gentle.NewRetryStream(opts, upstream)
for i := 0; i < totalRun; i++ {
	stream.Get(context.Background())
}

bs, err := scrap()
if err != nil {
	log.Fatalf("scrap() err: %s\n", err)
}
// # HELP test_retry_example_seconds duration of RetryStream.Get()
// # TYPE test_retry_example_seconds histogram
// test_retry_example_seconds_bucket{host="localhost",result="err",le="0.1"} 0
// test_retry_example_seconds_bucket{host="localhost",result="err",le="0.5"} 0
// test_retry_example_seconds_bucket{host="localhost",result="err",le="1"} 0
// test_retry_example_seconds_bucket{host="localhost",result="err",le="2.5"} 3
// test_retry_example_seconds_bucket{host="localhost",result="err",le="+Inf"} 3
// test_retry_example_seconds_sum{host="localhost",result="err"} 3.07845743
// test_retry_example_seconds_count{host="localhost",result="err"} 3
// test_retry_example_seconds_bucket{host="localhost",result="ok",le="0.1"} 0
// test_retry_example_seconds_bucket{host="localhost",result="ok",le="0.5"} 0
// test_retry_example_seconds_bucket{host="localhost",result="ok",le="1"} 3
// test_retry_example_seconds_bucket{host="localhost",result="ok",le="2.5"} 3
// test_retry_example_seconds_bucket{host="localhost",result="ok",le="+Inf"} 3
// test_retry_example_seconds_sum{host="localhost",result="ok"} 1.554815478
// test_retry_example_seconds_count{host="localhost",result="ok"} 3
// # HELP test_retry_example_total total of retries
// # TYPE test_retry_example_total counter
// test_retry_example_total{host="localhost",retry="err"} 30
// test_retry_example_total{host="localhost",retry="ok"} 15
log.Print(string(bs))
Output:

func (*PromRetryMetric) ObserveErr

func (m *PromRetryMetric) ObserveErr(timespan time.Duration, retry int)

func (*PromRetryMetric) ObserveOk

func (m *PromRetryMetric) ObserveOk(timespan time.Duration, retry int)

type ResultLabel

type ResultLabel struct {
	Name     string
	ValueOk  string
	ValueErr string
}

type StatsdCbMetric

type StatsdCbMetric struct {
	*StatsdMetric
	SubTimeout        string
	SubMaxConcurrency string
	SubOpen           string
	SubOther          string
	Rate              float32
	// contains filtered or unexported fields
}

StatsdCbMetric implements gentle.CbMetric. In addition to whatever StatsdMetric has, it adds counters of circuit errors. Namely: stats.foo.ok stats.foo.err stats.timers.foo.ok stats.timers.foo.err

stats.foo.cbErr.timeout stats.foo.cbErr.maxConcurrency stats.foo.cbErr.open

func NewStatsdCbMetric

func NewStatsdCbMetric(subPath string, cbErrSubPath string, statter statsd.Statter) *StatsdCbMetric
Example
gentle.CircuitReset()
subPath := "example.test3.result"
cbSubPath := "example.test3.cb"
client, _ := statsd.NewClient("127.0.0.1:8125", "extra")
opts := gentle.NewCircuitStreamOpts("", "test3", "test_circuit")
opts.CbMetric = NewStatsdCbMetric(subPath, cbSubPath, client)
opts.Log = log2.NewLog15Adapter(log15.New())

var upstream gentle.SimpleStream = func(ctx context.Context) (gentle.Message, error) {
	return nil, gentle.ErrCbOpen
}
stream := gentle.NewCircuitStream(opts, upstream)

// listen like "nc 8125 -l -u"
conn, err := net.ListenPacket("udp", ":8125")
if err != nil {
	log.Fatalf("ListenPacket() err: %s\n", err)
}
defer conn.Close()
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
	defer wg.Done()
	bs := make([]byte, 256)
	// read 5 times should be enough
	for i := 0; i < 5; i++ {
		conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		n, _, err := conn.ReadFrom(bs)
		if err != nil {
			log.Printf("ReadFrom() err: %s\n", err)
			continue
		}
		// timer:
		// 	extra.example.test3.result.err:1.358839|ms
		// counter:
		// 	extra.example.test3.result.err:1|c
		// cb-error-counter:
		// 	extra.example.test3.cb.open:1|c
		log.Println(string(bs[:n]))
	}
}()

stream.Get(context.Background())
wg.Wait()
Output:

func (*StatsdCbMetric) ObserveErr

func (m *StatsdCbMetric) ObserveErr(timespan time.Duration, err error)

func (*StatsdCbMetric) ObserveOk

func (m *StatsdCbMetric) ObserveOk(timespan time.Duration)

type StatsdMetric

type StatsdMetric struct {
	Rate   float32
	SubOk  string
	SubErr string
	// contains filtered or unexported fields
}

StatsdMetric implements gentle.Metric. It has a timer and a counter which are all subdivided into ok and err cases. Namely: stats.foo.ok stats.foo.err stats.timers.foo.ok stats.timers.foo.err

func NewStatsdMetric

func NewStatsdMetric(subPath string, statter statsd.Statter) *StatsdMetric
Example
subPath := "example.test1"
client, _ := statsd.NewClient("127.0.0.1:8125", "extra")
opts := gentle.NewRateLimitedStreamOpts("", "test1",
	gentle.NewTokenBucketRateLimit(10*time.Millisecond, 1))
opts.Metric = NewStatsdMetric(subPath, client)
opts.Log = log2.NewLog15Adapter(log15.New())

var upstream gentle.SimpleStream = func(ctx context.Context) (gentle.Message, error) {
	return gentle.SimpleMessage(""), nil
}
stream := gentle.NewRateLimitedStream(opts, upstream)

// listen like "nc 8125 -l -u"
conn, err := net.ListenPacket("udp", ":8125")
if err != nil {
	log.Fatalf("ListenPacket() err: %s\n", err)
}
defer conn.Close()
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
	defer wg.Done()
	bs := make([]byte, 256)
	// read 5 times should be enough
	for i := 0; i < 5; i++ {
		conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		n, _, err := conn.ReadFrom(bs)
		if err != nil {
			log.Printf("ReadFrom() err: %s\n", err)
			continue
		}
		// timer:
		// 	extra.rate.test1.ok:0.020875|ms
		// counter:
		// 	extra.rate.test1.ok:1|c
		log.Println(string(bs[:n]))
	}
}()

stream.Get(context.Background())
wg.Wait()
Output:

func (*StatsdMetric) ObserveErr

func (m *StatsdMetric) ObserveErr(timespan time.Duration)

func (*StatsdMetric) ObserveOk

func (m *StatsdMetric) ObserveOk(timespan time.Duration)

type StatsdRetryMetric

type StatsdRetryMetric struct {
	*StatsdMetric
	SubOk  string
	SubErr string
	Rate   float32
	// contains filtered or unexported fields
}

StatsdRetryMetric implements gentle.RetryMetric. In addition to whatever StatsdMetric has, it adds a retry counter which is subdivided into ok and err cases. Namely: stats.foo.ok stats.foo.err stats.timers.foo.ok stats.timers.foo.err

stats.foo_retry.ok stats.foo_retry.err

func NewStatsdRetryMetric

func NewStatsdRetryMetric(subPath string, retrySubPath string, statter statsd.Statter) *StatsdRetryMetric
Example
subPath := "example.test2.result"
retrySubPath := "example.test2.retry"
client, _ := statsd.NewClient("127.0.0.1:8125", "extra")
factory := gentle.NewConstBackOffFactory(
	gentle.NewConstBackOffFactoryOpts(10*time.Millisecond, time.Second))
opts := gentle.NewRetryStreamOpts("", "test2", factory)
opts.RetryMetric = NewStatsdRetryMetric(subPath, retrySubPath, client)
opts.Log = log2.NewLog15Adapter(log15.New())

count := 5
var upstream gentle.SimpleStream = func(ctx context.Context) (gentle.Message, error) {
	if count == 0 {
		return gentle.SimpleMessage(""), nil
	}
	count--
	return nil, errors.New("fake err")
}
stream := gentle.NewRetryStream(opts, upstream)

// listen like "nc 8125 -l -u"
conn, err := net.ListenPacket("udp", ":8125")
if err != nil {
	log.Fatalf("ListenPacket() err: %s\n", err)
}
defer conn.Close()
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
	defer wg.Done()
	bs := make([]byte, 256)
	// read 5 times should be enough
	for i := 0; i < 5; i++ {
		conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		n, _, err := conn.ReadFrom(bs)
		if err != nil {
			log.Printf("ReadFrom() err: %s\n", err)
			continue
		}
		// timer:
		// 	extra.example.test2.result.ok:56.73204|ms
		// counter:
		// 	extra.example.test2.result.ok:1|c
		// retry-counter:
		// 	extra.example.test2.retry.ok:5|c
		log.Println(string(bs[:n]))
	}
}()

stream.Get(context.Background())
wg.Wait()
Output:

func (*StatsdRetryMetric) ObserveErr

func (m *StatsdRetryMetric) ObserveErr(timespan time.Duration, retry int)

func (*StatsdRetryMetric) ObserveOk

func (m *StatsdRetryMetric) ObserveOk(timespan time.Duration, retry int)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL