github.com/XiaoMi/Gaea@v1.2.5/stats/counters_test.go (about)

     1  /*
     2  Copyright 2017 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package stats
    18  
    19  import (
    20  	"expvar"
    21  	"math/rand"
    22  	"reflect"
    23  	"sort"
    24  	"strings"
    25  	"testing"
    26  	"time"
    27  )
    28  
    29  func TestCounters(t *testing.T) {
    30  	clear()
    31  	c := NewCountersWithSingleLabel("counter1", "help", "label")
    32  	c.Add("c1", 1)
    33  	c.Add("c2", 1)
    34  	c.Add("c2", 1)
    35  	want1 := `{"c1": 1, "c2": 2}`
    36  	want2 := `{"c2": 2, "c1": 1}`
    37  	if s := c.String(); s != want1 && s != want2 {
    38  		t.Errorf("want %s or %s, got %s", want1, want2, s)
    39  	}
    40  	counts := c.Counts()
    41  	if counts["c1"] != 1 {
    42  		t.Errorf("want 1, got %d", counts["c1"])
    43  	}
    44  	if counts["c2"] != 2 {
    45  		t.Errorf("want 2, got %d", counts["c2"])
    46  	}
    47  }
    48  
    49  func TestCountersTags(t *testing.T) {
    50  	clear()
    51  	c := NewCountersWithSingleLabel("counterTag1", "help", "label")
    52  	want := map[string]int64{}
    53  	got := c.Counts()
    54  	if !reflect.DeepEqual(got, want) {
    55  		t.Errorf("want %v, got %v", want, got)
    56  	}
    57  
    58  	c = NewCountersWithSingleLabel("counterTag2", "help", "label", "tag1", "tag2")
    59  	want = map[string]int64{"tag1": 0, "tag2": 0}
    60  	got = c.Counts()
    61  	if !reflect.DeepEqual(got, want) {
    62  		t.Errorf("want %v, got %v", want, got)
    63  	}
    64  }
    65  
    66  func TestMultiCounters(t *testing.T) {
    67  	clear()
    68  	c := NewCountersWithMultiLabels("mapCounter1", "help", []string{"aaa", "bbb"})
    69  	c.Add([]string{"c1a", "c1b"}, 1)
    70  	c.Add([]string{"c2a", "c2b"}, 1)
    71  	c.Add([]string{"c2a", "c2b"}, 1)
    72  	want1 := `{"c1a.c1b": 1, "c2a.c2b": 2}`
    73  	want2 := `{"c2a.c2b": 2, "c1a.c1b": 1}`
    74  	if s := c.String(); s != want1 && s != want2 {
    75  		t.Errorf("want %s or %s, got %s", want1, want2, s)
    76  	}
    77  	counts := c.Counts()
    78  	if counts["c1a.c1b"] != 1 {
    79  		t.Errorf("want 1, got %d", counts["c1a.c1b"])
    80  	}
    81  	if counts["c2a.c2b"] != 2 {
    82  		t.Errorf("want 2, got %d", counts["c2a.c2b"])
    83  	}
    84  	f := NewCountersFuncWithMultiLabels("", "help", []string{"aaa", "bbb"}, func() map[string]int64 {
    85  		return map[string]int64{
    86  			"c1a.c1b": 1,
    87  			"c2a.c2b": 2,
    88  		}
    89  	})
    90  	if s := f.String(); s != want1 && s != want2 {
    91  		t.Errorf("want %s or %s, got %s", want1, want2, s)
    92  	}
    93  }
    94  
    95  func TestMultiCountersDot(t *testing.T) {
    96  	clear()
    97  	c := NewCountersWithMultiLabels("mapCounter2", "help", []string{"aaa", "bbb"})
    98  	c.Add([]string{"c1.a", "c1b"}, 1)
    99  	c.Add([]string{"c2a", "c2.b"}, 1)
   100  	c.Add([]string{"c2a", "c2.b"}, 1)
   101  	c1a := safeLabel("c1.a")
   102  	c1aJSON := strings.Replace(c1a, "\\", "\\\\", -1)
   103  	c2b := safeLabel("c2.b")
   104  	c2bJSON := strings.Replace(c2b, "\\", "\\\\", -1)
   105  	want1 := `{"` + c1aJSON + `.c1b": 1, "c2a.` + c2bJSON + `": 2}`
   106  	want2 := `{"c2a.` + c2bJSON + `": 2, "` + c1aJSON + `.c1b": 1}`
   107  	if s := c.String(); s != want1 && s != want2 {
   108  		t.Errorf("want %s or %s, got %s", want1, want2, s)
   109  	}
   110  	counts := c.Counts()
   111  	if counts[c1a+".c1b"] != 1 {
   112  		t.Errorf("want 1, got %d", counts[c1a+".c1b"])
   113  	}
   114  	if counts["c2a."+c2b] != 2 {
   115  		t.Errorf("want 2, got %d", counts["c2a."+c2b])
   116  	}
   117  }
   118  
   119  func TestCountersHook(t *testing.T) {
   120  	var gotname string
   121  	var gotv *CountersWithSingleLabel
   122  	clear()
   123  	Register(func(name string, v expvar.Var) {
   124  		gotname = name
   125  		gotv = v.(*CountersWithSingleLabel)
   126  	})
   127  
   128  	v := NewCountersWithSingleLabel("counter2", "help", "label")
   129  	if gotname != "counter2" {
   130  		t.Errorf("want counter2, got %s", gotname)
   131  	}
   132  	if gotv != v {
   133  		t.Errorf("want %#v, got %#v", v, gotv)
   134  	}
   135  }
   136  
   137  var benchCounter = NewCountersWithSingleLabel("bench", "help", "label")
   138  
   139  func BenchmarkCounters(b *testing.B) {
   140  	clear()
   141  	benchCounter.Add("c1", 1)
   142  	b.ResetTimer()
   143  
   144  	b.RunParallel(func(pb *testing.PB) {
   145  		for pb.Next() {
   146  			benchCounter.Add("c1", 1)
   147  		}
   148  	})
   149  }
   150  
   151  var benchMultiCounter = NewCountersWithMultiLabels("benchMulti", "help", []string{"call", "keyspace", "dbtype"})
   152  
   153  func BenchmarkMultiCounters(b *testing.B) {
   154  	clear()
   155  	key := []string{"execute-key-ranges", "keyspacename", "replica"}
   156  	benchMultiCounter.Add(key, 1)
   157  	b.ResetTimer()
   158  
   159  	b.RunParallel(func(pb *testing.PB) {
   160  		for pb.Next() {
   161  			benchMultiCounter.Add(key, 1)
   162  		}
   163  	})
   164  }
   165  
   166  func BenchmarkCountersTailLatency(b *testing.B) {
   167  	// For this one, ignore the time reported by 'go test'.
   168  	// The 99th Percentile log line is all that matters.
   169  	// (Cmd: go test -bench=BenchmarkCountersTailLatency -benchtime=30s -cpu=10)
   170  	clear()
   171  	benchCounter.Add("c1", 1)
   172  	c := make(chan time.Duration, 100)
   173  	done := make(chan struct{})
   174  	go func() {
   175  		all := make([]int, b.N)
   176  		i := 0
   177  		for dur := range c {
   178  			all[i] = int(dur)
   179  			i++
   180  		}
   181  		sort.Ints(all)
   182  		p99 := time.Duration(all[b.N*99/100])
   183  		b.Logf("99th Percentile (for N=%v): %v", b.N, p99)
   184  		close(done)
   185  	}()
   186  
   187  	b.ResetTimer()
   188  	b.SetParallelism(100) // The actual number of goroutines is 100*GOMAXPROCS
   189  	b.RunParallel(func(pb *testing.PB) {
   190  		r := rand.New(rand.NewSource(time.Now().UnixNano()))
   191  
   192  		var start time.Time
   193  
   194  		for pb.Next() {
   195  			// sleep between 0~200ms to simulate 10 QPS per goroutine.
   196  			time.Sleep(time.Duration(r.Int63n(200)) * time.Millisecond)
   197  			start = time.Now()
   198  			benchCounter.Add("c1", 1)
   199  			c <- time.Since(start)
   200  		}
   201  	})
   202  	b.StopTimer()
   203  
   204  	close(c)
   205  	<-done
   206  }
   207  
   208  func TestCountersFuncWithMultiLabels(t *testing.T) {
   209  	clear()
   210  	f := NewCountersFuncWithMultiLabels("TestCountersFuncWithMultiLabels", "help", []string{"label1"}, func() map[string]int64 {
   211  		return map[string]int64{
   212  			"c1": 1,
   213  			"c2": 2,
   214  		}
   215  	})
   216  
   217  	want1 := `{"c1": 1, "c2": 2}`
   218  	want2 := `{"c2": 2, "c1": 1}`
   219  	if s := f.String(); s != want1 && s != want2 {
   220  		t.Errorf("want %s or %s, got %s", want1, want2, s)
   221  	}
   222  }
   223  
   224  func TestCountersFuncWithMultiLabels_Hook(t *testing.T) {
   225  	var gotname string
   226  	var gotv *CountersFuncWithMultiLabels
   227  	clear()
   228  	Register(func(name string, v expvar.Var) {
   229  		gotname = name
   230  		gotv = v.(*CountersFuncWithMultiLabels)
   231  	})
   232  
   233  	v := NewCountersFuncWithMultiLabels("TestCountersFuncWithMultiLabels_Hook", "help", []string{"label1"}, func() map[string]int64 {
   234  		return map[string]int64{}
   235  	})
   236  	if gotname != "TestCountersFuncWithMultiLabels_Hook" {
   237  		t.Errorf("want TestCountersFuncWithMultiLabels_Hook, got %s", gotname)
   238  	}
   239  	if gotv != v {
   240  		t.Errorf("want %#v, got %#v", v, gotv)
   241  	}
   242  }