github.com/lulzWill/go-agent@v2.1.2+incompatible/internal/metrics_test.go (about)

     1  package internal
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  var (
    11  	start = time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC)
    12  	end   = time.Date(2014, time.November, 28, 1, 2, 0, 0, time.UTC)
    13  )
    14  
    15  func TestEmptyMetrics(t *testing.T) {
    16  	mt := newMetricTable(20, start)
    17  	js, err := mt.CollectorJSON(`12345`, end)
    18  	if nil != err {
    19  		t.Fatal(err)
    20  	}
    21  	if nil != js {
    22  		t.Error(string(js))
    23  	}
    24  }
    25  
    26  func isValidJSON(data []byte) error {
    27  	var v interface{}
    28  
    29  	return json.Unmarshal(data, &v)
    30  }
    31  
    32  func TestMetrics(t *testing.T) {
    33  	mt := newMetricTable(20, start)
    34  
    35  	mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
    36  	mt.addDuration("two", "my_scope", 4*time.Second, 2*time.Second, unforced)
    37  	mt.addDuration("one", "my_scope", 2*time.Second, 1*time.Second, unforced)
    38  	mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
    39  
    40  	mt.addApdex("apdex satisfied", "", 9*time.Second, ApdexSatisfying, unforced)
    41  	mt.addApdex("apdex satisfied", "", 8*time.Second, ApdexSatisfying, unforced)
    42  	mt.addApdex("apdex tolerated", "", 7*time.Second, ApdexTolerating, unforced)
    43  	mt.addApdex("apdex tolerated", "", 8*time.Second, ApdexTolerating, unforced)
    44  	mt.addApdex("apdex failed", "my_scope", 1*time.Second, ApdexFailing, unforced)
    45  
    46  	mt.addCount("count 123", float64(123), unforced)
    47  	mt.addSingleCount("count 1", unforced)
    48  
    49  	ExpectMetrics(t, mt, []WantMetric{
    50  		{"apdex satisfied", "", false, []float64{2, 0, 0, 8, 9, 0}},
    51  		{"apdex tolerated", "", false, []float64{0, 2, 0, 7, 8, 0}},
    52  		{"one", "", false, []float64{2, 4, 2, 2, 2, 8}},
    53  		{"apdex failed", "my_scope", false, []float64{0, 0, 1, 1, 1, 0}},
    54  		{"one", "my_scope", false, []float64{1, 2, 1, 2, 2, 4}},
    55  		{"two", "my_scope", false, []float64{1, 4, 2, 4, 4, 16}},
    56  		{"count 123", "", false, []float64{123, 0, 0, 0, 0, 0}},
    57  		{"count 1", "", false, []float64{1, 0, 0, 0, 0, 0}},
    58  	})
    59  
    60  	js, err := mt.Data("12345", end)
    61  	if nil != err {
    62  		t.Error(err)
    63  	}
    64  	// The JSON metric order is not deterministic, so we merely test that it
    65  	// is valid JSON.
    66  	if err := isValidJSON(js); nil != err {
    67  		t.Error(err, string(js))
    68  	}
    69  }
    70  
    71  func TestApplyRules(t *testing.T) {
    72  	js := `[
    73  	{
    74  		"ignore":false,
    75  		"each_segment":false,
    76  		"terminate_chain":true,
    77  		"replacement":"been_renamed",
    78  		"replace_all":false,
    79  		"match_expression":"one$",
    80  		"eval_order":1
    81  	},
    82  	{
    83  		"ignore":true,
    84  		"each_segment":false,
    85  		"terminate_chain":true,
    86  		"replace_all":false,
    87  		"match_expression":"ignore_me",
    88  		"eval_order":1
    89  	},
    90  	{
    91  		"ignore":false,
    92  		"each_segment":false,
    93  		"terminate_chain":true,
    94  		"replacement":"merge_me",
    95  		"replace_all":false,
    96  		"match_expression":"merge_me[0-9]+$",
    97  		"eval_order":1
    98  	}
    99  	]`
   100  	var rules metricRules
   101  	err := json.Unmarshal([]byte(js), &rules)
   102  	if nil != err {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	mt := newMetricTable(20, start)
   107  	mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
   108  	mt.addDuration("one", "scope1", 2*time.Second, 1*time.Second, unforced)
   109  	mt.addDuration("one", "scope2", 2*time.Second, 1*time.Second, unforced)
   110  	mt.addDuration("ignore_me", "", 2*time.Second, 1*time.Second, unforced)
   111  	mt.addDuration("ignore_me", "scope1", 2*time.Second, 1*time.Second, unforced)
   112  	mt.addDuration("ignore_me", "scope2", 2*time.Second, 1*time.Second, unforced)
   113  	mt.addDuration("merge_me1", "", 2*time.Second, 1*time.Second, unforced)
   114  	mt.addDuration("merge_me2", "", 2*time.Second, 1*time.Second, unforced)
   115  
   116  	applied := mt.ApplyRules(rules)
   117  	ExpectMetrics(t, applied, []WantMetric{
   118  		{"been_renamed", "", false, []float64{1, 2, 1, 2, 2, 4}},
   119  		{"been_renamed", "scope1", false, []float64{1, 2, 1, 2, 2, 4}},
   120  		{"been_renamed", "scope2", false, []float64{1, 2, 1, 2, 2, 4}},
   121  		{"merge_me", "", false, []float64{2, 4, 2, 2, 2, 8}},
   122  	})
   123  }
   124  
   125  func TestApplyEmptyRules(t *testing.T) {
   126  	js := `[]`
   127  	var rules metricRules
   128  	err := json.Unmarshal([]byte(js), &rules)
   129  	if nil != err {
   130  		t.Fatal(err)
   131  	}
   132  	mt := newMetricTable(20, start)
   133  	mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
   134  	mt.addDuration("one", "my_scope", 2*time.Second, 1*time.Second, unforced)
   135  	applied := mt.ApplyRules(rules)
   136  	ExpectMetrics(t, applied, []WantMetric{
   137  		{"one", "", false, []float64{1, 2, 1, 2, 2, 4}},
   138  		{"one", "my_scope", false, []float64{1, 2, 1, 2, 2, 4}},
   139  	})
   140  }
   141  
   142  func TestApplyNilRules(t *testing.T) {
   143  	var rules metricRules
   144  
   145  	mt := newMetricTable(20, start)
   146  	mt.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
   147  	mt.addDuration("one", "my_scope", 2*time.Second, 1*time.Second, unforced)
   148  	applied := mt.ApplyRules(rules)
   149  	ExpectMetrics(t, applied, []WantMetric{
   150  		{"one", "", false, []float64{1, 2, 1, 2, 2, 4}},
   151  		{"one", "my_scope", false, []float64{1, 2, 1, 2, 2, 4}},
   152  	})
   153  }
   154  
   155  func TestForced(t *testing.T) {
   156  	mt := newMetricTable(0, start)
   157  
   158  	if mt.numDropped != 0 {
   159  		t.Fatal(mt.numDropped)
   160  	}
   161  
   162  	mt.addDuration("unforced", "", 1*time.Second, 1*time.Second, unforced)
   163  	mt.addDuration("forced", "", 2*time.Second, 2*time.Second, forced)
   164  
   165  	if mt.numDropped != 1 {
   166  		t.Fatal(mt.numDropped)
   167  	}
   168  
   169  	ExpectMetrics(t, mt, []WantMetric{
   170  		{"forced", "", true, []float64{1, 2, 2, 2, 2, 4}},
   171  	})
   172  
   173  }
   174  
   175  func TestMetricsMergeIntoEmpty(t *testing.T) {
   176  	src := newMetricTable(20, start)
   177  	src.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
   178  	src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   179  	dest := newMetricTable(20, start)
   180  	dest.merge(src, "")
   181  
   182  	ExpectMetrics(t, dest, []WantMetric{
   183  		{"one", "", false, []float64{1, 2, 1, 2, 2, 4}},
   184  		{"two", "", false, []float64{1, 2, 1, 2, 2, 4}},
   185  	})
   186  }
   187  
   188  func TestMetricsMergeFromEmpty(t *testing.T) {
   189  	src := newMetricTable(20, start)
   190  	dest := newMetricTable(20, start)
   191  	dest.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
   192  	dest.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   193  	dest.merge(src, "")
   194  
   195  	ExpectMetrics(t, dest, []WantMetric{
   196  		{"one", "", false, []float64{1, 2, 1, 2, 2, 4}},
   197  		{"two", "", false, []float64{1, 2, 1, 2, 2, 4}},
   198  	})
   199  }
   200  
   201  func TestMetricsMerge(t *testing.T) {
   202  	src := newMetricTable(20, start)
   203  	dest := newMetricTable(20, start)
   204  	dest.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
   205  	dest.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   206  	src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   207  	src.addDuration("three", "", 2*time.Second, 1*time.Second, unforced)
   208  
   209  	dest.merge(src, "")
   210  
   211  	ExpectMetrics(t, dest, []WantMetric{
   212  		{"one", "", false, []float64{1, 2, 1, 2, 2, 4}},
   213  		{"two", "", false, []float64{2, 4, 2, 2, 2, 8}},
   214  		{"three", "", false, []float64{1, 2, 1, 2, 2, 4}},
   215  	})
   216  }
   217  
   218  func TestMergeFailedSuccess(t *testing.T) {
   219  	src := newMetricTable(20, start)
   220  	dest := newMetricTable(20, end)
   221  	dest.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
   222  	dest.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   223  	src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   224  	src.addDuration("three", "", 2*time.Second, 1*time.Second, unforced)
   225  
   226  	if 0 != dest.failedHarvests {
   227  		t.Fatal(dest.failedHarvests)
   228  	}
   229  
   230  	dest.mergeFailed(src)
   231  
   232  	ExpectMetrics(t, dest, []WantMetric{
   233  		{"one", "", false, []float64{1, 2, 1, 2, 2, 4}},
   234  		{"two", "", false, []float64{2, 4, 2, 2, 2, 8}},
   235  		{"three", "", false, []float64{1, 2, 1, 2, 2, 4}},
   236  	})
   237  }
   238  
   239  func TestMergeFailedLimitReached(t *testing.T) {
   240  	src := newMetricTable(20, start)
   241  	dest := newMetricTable(20, end)
   242  	dest.addDuration("one", "", 2*time.Second, 1*time.Second, unforced)
   243  	dest.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   244  	src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   245  	src.addDuration("three", "", 2*time.Second, 1*time.Second, unforced)
   246  
   247  	src.failedHarvests = failedMetricAttemptsLimit
   248  
   249  	dest.mergeFailed(src)
   250  
   251  	ExpectMetrics(t, dest, []WantMetric{
   252  		{"one", "", false, []float64{1, 2, 1, 2, 2, 4}},
   253  		{"two", "", false, []float64{1, 2, 1, 2, 2, 4}},
   254  	})
   255  }
   256  
   257  func BenchmarkMetricTableCollectorJSON(b *testing.B) {
   258  	mt := newMetricTable(2000, time.Now())
   259  	md := metricData{
   260  		countSatisfied:  1234567812345678.1234567812345678,
   261  		totalTolerated:  1234567812345678.1234567812345678,
   262  		exclusiveFailed: 1234567812345678.1234567812345678,
   263  		min:             1234567812345678.1234567812345678,
   264  		max:             1234567812345678.1234567812345678,
   265  		sumSquares:      1234567812345678.1234567812345678,
   266  	}
   267  
   268  	for i := 0; i < 20; i++ {
   269  		scope := fmt.Sprintf("WebTransaction/Uri/myblog2/%d", i)
   270  
   271  		for j := 0; j < 20; j++ {
   272  			name := fmt.Sprintf("Datastore/statement/MySQL/City%d/insert", j)
   273  			mt.add(name, "", md, forced)
   274  			mt.add(name, scope, md, forced)
   275  
   276  			name = fmt.Sprintf("WebTransaction/Uri/myblog2/newPost_rum_%d.php", j)
   277  			mt.add(name, "", md, forced)
   278  			mt.add(name, scope, md, forced)
   279  		}
   280  	}
   281  
   282  	data, err := mt.CollectorJSON("12345", time.Now())
   283  	if nil != err {
   284  		b.Fatal(err)
   285  	}
   286  	if err := isValidJSON(data); nil != err {
   287  		b.Fatal(err, string(data))
   288  	}
   289  
   290  	b.ResetTimer()
   291  	b.ReportAllocs()
   292  
   293  	id := "12345"
   294  	now := time.Now()
   295  	for i := 0; i < b.N; i++ {
   296  		mt.CollectorJSON(id, now)
   297  	}
   298  }
   299  
   300  func BenchmarkAddingSameMetrics(b *testing.B) {
   301  	name := "my_name"
   302  	scope := "my_scope"
   303  	duration := 2 * time.Second
   304  	exclusive := 1 * time.Second
   305  
   306  	mt := newMetricTable(2000, time.Now())
   307  
   308  	b.ResetTimer()
   309  	b.ReportAllocs()
   310  
   311  	for i := 0; i < b.N; i++ {
   312  		mt.addDuration(name, scope, duration, exclusive, forced)
   313  		mt.addSingleCount(name, forced)
   314  	}
   315  }
   316  
   317  func TestMergedMetricsAreCopied(t *testing.T) {
   318  	src := newMetricTable(20, start)
   319  	dest := newMetricTable(20, start)
   320  
   321  	src.addSingleCount("zip", unforced)
   322  	dest.merge(src, "")
   323  	src.addSingleCount("zip", unforced)
   324  	ExpectMetrics(t, dest, []WantMetric{
   325  		{"zip", "", false, []float64{1, 0, 0, 0, 0, 0}},
   326  	})
   327  }
   328  
   329  func TestMergedWithScope(t *testing.T) {
   330  	src := newMetricTable(20, start)
   331  	dest := newMetricTable(20, start)
   332  
   333  	src.addSingleCount("one", unforced)
   334  	src.addDuration("two", "", 2*time.Second, 1*time.Second, unforced)
   335  	dest.addDuration("two", "my_scope", 2*time.Second, 1*time.Second, unforced)
   336  	dest.merge(src, "my_scope")
   337  
   338  	ExpectMetrics(t, dest, []WantMetric{
   339  		{"one", "my_scope", false, []float64{1, 0, 0, 0, 0, 0}},
   340  		{"two", "my_scope", false, []float64{2, 4, 2, 2, 2, 8}},
   341  	})
   342  }