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 ¶
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)
type ResultLabel ¶
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)