PNG  IHDR pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F@8N ' p @8N@8}' p '#@8N@8N pQ9p!i~}|6-ӪG` VP.@*j>[ K^<֐Z]@8N'KQ<Q(`s" 'hgpKB`R@Dqj '  'P$a ( `D$Na L?u80e J,K˷NI'0eݷ(NI'؀ 2ipIIKp`:O'`ʤxB8Ѥx Ѥx $ $P6 :vRNb 'p,>NB 'P]-->P T+*^h& p '‰a ‰ (ĵt#u33;Nt̵'ޯ; [3W ~]0KH1q@8]O2]3*̧7# *p>us p _6]/}-4|t'|Smx= DoʾM×M_8!)6lq':l7!|4} '\ne t!=hnLn (~Dn\+‰_4k)0e@OhZ`F `.m1} 'vp{F`ON7Srx 'D˸nV`><;yMx!IS钦OM)Ե٥x 'DSD6bS8!" ODz#R >S8!7ّxEh0m$MIPHi$IvS8IN$I p$O8I,sk&I)$IN$Hi$I^Ah.p$MIN$IR8I·N "IF9Ah0m$MIN$IR8IN$I 3jIU;kO$ɳN$+ q.x* tEXtComment

Viewing File: /opt/go/pkg/mod/github.com/armon/go-metrics@v0.3.10/inmem_endpoint_test.go

package metrics

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/pascaldekloe/goe/verify"
)

func TestDisplayMetrics(t *testing.T) {
	interval := 10 * time.Millisecond
	inm := NewInmemSink(interval, 50*time.Millisecond)

	// Add data points
	inm.SetGauge([]string{"foo", "bar"}, 42)
	inm.SetGaugeWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}})
	inm.EmitKey([]string{"foo", "bar"}, 42)
	inm.IncrCounter([]string{"foo", "bar"}, 20)
	inm.IncrCounter([]string{"foo", "bar"}, 22)
	inm.IncrCounterWithLabels([]string{"foo", "bar"}, 20, []Label{{"a", "b"}})
	inm.IncrCounterWithLabels([]string{"foo", "bar"}, 40, []Label{{"a", "b"}})
	inm.AddSample([]string{"foo", "bar"}, 20)
	inm.AddSample([]string{"foo", "bar"}, 24)
	inm.AddSampleWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}})
	inm.AddSampleWithLabels([]string{"foo", "bar"}, 33, []Label{{"a", "b"}})

	data := inm.Data()
	if len(data) != 1 {
		t.Fatalf("bad: %v", data)
	}

	expected := MetricsSummary{
		Timestamp: data[0].Interval.Round(time.Second).UTC().String(),
		Gauges: []GaugeValue{
			{
				Name:          "foo.bar",
				Hash:          "foo.bar",
				Value:         float32(42),
				DisplayLabels: map[string]string{},
			},
			{
				Name:          "foo.bar",
				Hash:          "foo.bar;a=b",
				Value:         float32(23),
				DisplayLabels: map[string]string{"a": "b"},
			},
		},
		Points: []PointValue{
			{
				Name:   "foo.bar",
				Points: []float32{42},
			},
		},
		Counters: []SampledValue{
			{
				Name: "foo.bar",
				Hash: "foo.bar",
				AggregateSample: &AggregateSample{
					Count: 2,
					Min:   20,
					Max:   22,
					Sum:   42,
					SumSq: 884,
					Rate:  4200,
				},
				Mean:   21,
				Stddev: 1.4142135623730951,
			},
			{
				Name: "foo.bar",
				Hash: "foo.bar;a=b",
				AggregateSample: &AggregateSample{
					Count: 2,
					Min:   20,
					Max:   40,
					Sum:   60,
					SumSq: 2000,
					Rate:  6000,
				},
				Mean:          30,
				Stddev:        14.142135623730951,
				DisplayLabels: map[string]string{"a": "b"},
			},
		},
		Samples: []SampledValue{
			{
				Name: "foo.bar",
				Hash: "foo.bar",
				AggregateSample: &AggregateSample{
					Count: 2,
					Min:   20,
					Max:   24,
					Sum:   44,
					SumSq: 976,
					Rate:  4400,
				},
				Mean:   22,
				Stddev: 2.8284271247461903,
			},
			{
				Name: "foo.bar",
				Hash: "foo.bar;a=b",
				AggregateSample: &AggregateSample{
					Count: 2,
					Min:   23,
					Max:   33,
					Sum:   56,
					SumSq: 1618,
					Rate:  5600,
				},
				Mean:          28,
				Stddev:        7.0710678118654755,
				DisplayLabels: map[string]string{"a": "b"},
			},
		},
	}

	raw, err := inm.DisplayMetrics(nil, nil)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	result := raw.(MetricsSummary)

	// Ignore the LastUpdated field, we don't export that anyway
	for i, got := range result.Counters {
		expected.Counters[i].LastUpdated = got.LastUpdated
	}
	for i, got := range result.Samples {
		expected.Samples[i].LastUpdated = got.LastUpdated
	}

	verify.Values(t, "all", result, expected)
}

func TestDisplayMetrics_RaceSetGauge(t *testing.T) {
	interval := 200 * time.Millisecond
	inm := NewInmemSink(interval, 10*interval)
	result := make(chan float32)

	go func() {
		for {
			time.Sleep(150 * time.Millisecond)
			inm.SetGauge([]string{"foo", "bar"}, float32(42))
		}
	}()

	go func() {
		start := time.Now()
		var summary MetricsSummary
		// test for twenty intervals
		for time.Now().Sub(start) < 20*interval {
			time.Sleep(100 * time.Millisecond)
			raw, _ := inm.DisplayMetrics(nil, nil)
			summary = raw.(MetricsSummary)
		}
		// save result
		for _, g := range summary.Gauges {
			if g.Name == "foo.bar" {
				result <- g.Value
			}
		}
		close(result)
	}()

	got := <-result
	verify.Values(t, "all", got, float32(42))
}

func TestDisplayMetrics_RaceAddSample(t *testing.T) {
	interval := 200 * time.Millisecond
	inm := NewInmemSink(interval, 10*interval)
	result := make(chan float32)

	go func() {
		for {
			time.Sleep(75 * time.Millisecond)
			inm.AddSample([]string{"foo", "bar"}, float32(0.0))
		}
	}()

	go func() {
		start := time.Now()
		var summary MetricsSummary
		// test for twenty intervals
		for time.Now().Sub(start) < 20*interval {
			time.Sleep(100 * time.Millisecond)
			raw, _ := inm.DisplayMetrics(nil, nil)
			summary = raw.(MetricsSummary)
		}
		// save result
		for _, g := range summary.Gauges {
			if g.Name == "foo.bar" {
				result <- g.Value
			}
		}
		close(result)
	}()

	got := <-result
	verify.Values(t, "all", got, float32(0.0))
}

func TestDisplayMetrics_RaceIncrCounter(t *testing.T) {
	interval := 200 * time.Millisecond
	inm := NewInmemSink(interval, 10*interval)
	result := make(chan float32)

	go func() {
		for {
			time.Sleep(75 * time.Millisecond)
			inm.IncrCounter([]string{"foo", "bar"}, float32(0.0))
		}
	}()

	go func() {
		start := time.Now()
		var summary MetricsSummary
		// test for twenty intervals
		for time.Now().Sub(start) < 20*interval {
			time.Sleep(30 * time.Millisecond)
			raw, _ := inm.DisplayMetrics(nil, nil)
			summary = raw.(MetricsSummary)
		}
		// save result for testing
		for _, g := range summary.Gauges {
			if g.Name == "foo.bar" {
				result <- g.Value
			}
		}
		close(result)
	}()

	got := <-result
	verify.Values(t, "all", got, float32(0.0))
}

func TestDisplayMetrics_RaceMetricsSetGauge(t *testing.T) {
	interval := 200 * time.Millisecond
	inm := NewInmemSink(interval, 10*interval)
	met := &Metrics{Config: Config{FilterDefault: true}, sink: inm}
	result := make(chan float32)
	labels := []Label{
		{"name1", "value1"},
		{"name2", "value2"},
	}

	go func() {
		for {
			time.Sleep(75 * time.Millisecond)
			met.SetGaugeWithLabels([]string{"foo", "bar"}, float32(42), labels)
		}
	}()

	go func() {
		start := time.Now()
		var summary MetricsSummary
		// test for twenty intervals
		for time.Now().Sub(start) < 40*interval {
			time.Sleep(150 * time.Millisecond)
			raw, _ := inm.DisplayMetrics(nil, nil)
			summary = raw.(MetricsSummary)
		}
		// save result
		for _, g := range summary.Gauges {
			if g.Name == "foo.bar" {
				result <- g.Value
			}
		}
		close(result)
	}()

	got := <-result
	verify.Values(t, "all", got, float32(42))
}

func TestInmemSink_Stream(t *testing.T) {
	interval := 10 * time.Millisecond
	total := 50 * time.Millisecond
	inm := NewInmemSink(interval, total)

	ctx, cancel := context.WithTimeout(context.Background(), total*2)
	defer cancel()

	chDone := make(chan struct{})

	go func() {
		for i := float32(0); ctx.Err() == nil; i++ {
			inm.SetGaugeWithLabels([]string{"gauge", "foo"}, 20+i, []Label{{"a", "b"}})
			inm.EmitKey([]string{"key", "foo"}, 30+i)
			inm.IncrCounterWithLabels([]string{"counter", "bar"}, 40+i, []Label{{"a", "b"}})
			inm.IncrCounterWithLabels([]string{"counter", "bar"}, 50+i, []Label{{"a", "b"}})
			inm.AddSampleWithLabels([]string{"sample", "bar"}, 60+i, []Label{{"a", "b"}})
			inm.AddSampleWithLabels([]string{"sample", "bar"}, 70+i, []Label{{"a", "b"}})
			time.Sleep(interval / 3)
		}
		close(chDone)
	}()

	resp := httptest.NewRecorder()
	enc := encoder{
		encoder: json.NewEncoder(resp),
		flusher: resp,
	}
	inm.Stream(ctx, enc)

	<-chDone

	decoder := json.NewDecoder(resp.Body)
	var prevGaugeValue float32
	for i := 0; i < 8; i++ {
		var summary MetricsSummary
		if err := decoder.Decode(&summary); err != nil {
			t.Fatalf("expected no error while decoding response %d, got %v", i, err)
		}
		if count := len(summary.Gauges); count != 1 {
			t.Fatalf("expected at least one gauge in response %d, got %v", i, count)
		}
		value := summary.Gauges[0].Value
		// The upper bound of the gauge value is not known, but we can expect it
		// to be less than 50 because it increments by 3 every interval and we run
		// for ~10 intervals.
		if value < 20 || value > 50 {
			t.Fatalf("expected interval %d guage value between 20 and 50, got %v", i, value)
		}
		if value <= prevGaugeValue {
			t.Fatalf("expected interval %d guage value to be greater than previous, %v == %v", i, value, prevGaugeValue)
		}
		prevGaugeValue = value
	}
}

type encoder struct {
	flusher http.Flusher
	encoder *json.Encoder
}

func (e encoder) Encode(metrics interface{}) error {
	if err := e.encoder.Encode(metrics); err != nil {
		fmt.Println("failed to encode metrics summary", "error", err)
		return err
	}
	e.flusher.Flush()
	return nil
}
Back to Directory=ceiIENDB`