Skip to content

Commit

Permalink
Updates to the Metrics
Browse files Browse the repository at this point in the history
Fix tests.
  • Loading branch information
aLekSer committed Apr 12, 2020
1 parent f604b3f commit e4c126a
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 212 deletions.
12 changes: 6 additions & 6 deletions pkg/gameserverallocations/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ func init() {

// default set of tags for latency metric
var latencyTags = []tag.Mutator{
tag.Insert(keyMultiCluster, "none"),
tag.Insert(keyClusterName, "none"),
tag.Insert(keySchedulingStrategy, "none"),
tag.Insert(keyFleetName, "none"),
tag.Insert(keyNodeName, "none"),
tag.Insert(keyStatus, "none"),
tag.Insert(keyMultiCluster, ""),
tag.Insert(keyClusterName, ""),
tag.Insert(keySchedulingStrategy, ""),
tag.Insert(keyFleetName, ""),
tag.Insert(keyNodeName, ""),
tag.Insert(keyStatus, ""),
}

type metrics struct {
Expand Down
196 changes: 152 additions & 44 deletions pkg/metrics/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,76 @@
package metrics

import (
"context"
"strings"
"testing"

"go.opencensus.io/metric/metricdata"
"go.opencensus.io/metric/metricexport"
"k8s.io/apimachinery/pkg/util/intstr"

agonesv1 "agones.dev/agones/pkg/apis/agones/v1"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/util/intstr"
)

func TestControllerGameServerCount(t *testing.T) {
type metricExporter struct {
metrics []*metricdata.Metric
}

func (e *metricExporter) ExportMetrics(ctx context.Context, metrics []*metricdata.Metric) error {
e.metrics = metrics
return nil
}

func serialize(args []string) string {
return strings.Join(args, "|")
}

registry := prometheus.NewRegistry()
_, err := RegisterPrometheusExporter(registry)
assert.Nil(t, err)
type expectedMetricData struct {
labels []string
val interface{}
}

func assertMetricData(t *testing.T, exporter *metricExporter, metricName string, expected []expectedMetricData) {

expectedValuesAsMap := make(map[string]expectedMetricData)
for _, e := range expected {
expectedValuesAsMap[serialize(e.labels)] = e
}

var wantedMetric *metricdata.Metric
for _, m := range exporter.metrics {
if m.Descriptor.Name == metricName {
wantedMetric = m
}
}
assert.NotNil(t, wantedMetric, "No metric found with name: %s", metricName)

assert.Equal(t, len(expectedValuesAsMap), len(expected), "Multiple entries in 'expected' slice have the exact same labels")
assert.Equal(t, len(wantedMetric.TimeSeries), len(expectedValuesAsMap), "number of timeseries does not match")
for _, tsd := range wantedMetric.TimeSeries {
actualLabelValues := make([]string, len(tsd.LabelValues))
for i, k := range tsd.LabelValues {
actualLabelValues[i] = k.Value
}
e, ok := expectedValuesAsMap[serialize(actualLabelValues)]
assert.True(t, ok, "no TimeSeries found with labels: %v", actualLabelValues)

assert.Equal(t, actualLabelValues, e.labels, "label values don't match")
assert.Equal(t, len(tsd.Points), 1, "assertMetricDataValues can only handle a single Point in a TimeSeries")
assert.Equal(t, tsd.Points[0].Value, e.val, "metric: %s, tags: %v, values don't match; got: %v, want: %v", metricName, tsd.LabelValues, tsd.Points[0].Value, e.val)
}
}

func resetMetrics() {
unRegisterViews()
registerViews()
}

func TestControllerGameServerCount(t *testing.T) {
resetMetrics()
exporter := &metricExporter{}
reader := metricexport.NewReader()

c := newFakeController()
defer c.close()
Expand All @@ -40,29 +95,31 @@ func TestControllerGameServerCount(t *testing.T) {
gs1.Status.State = agonesv1.GameServerStateReady
c.gsWatch.Modify(gs1)

c.run(t)
c.sync()
c.collect()
report()

gs1 = gs1.DeepCopy()
gs1.Status.State = agonesv1.GameServerStateShutdown
c.gsWatch.Modify(gs1)
c.gsWatch.Add(gameServerWithFleetAndState("", agonesv1.GameServerStatePortAllocation))
c.gsWatch.Add(gameServerWithFleetAndState("", agonesv1.GameServerStatePortAllocation))

c.run(t)
c.sync()
c.collect()
report()

assert.Nil(t, testutil.GatherAndCompare(registry, strings.NewReader(gsCountExpected), "agones_gameservers_count"))
reader.ReadAndExport(exporter)
assertMetricData(t, exporter, "gameservers_count", []expectedMetricData{
{labels: []string{"test-fleet", "Ready"}, val: int64(0)},
{labels: []string{"test-fleet", "Shutdown"}, val: int64(1)},
{labels: []string{"none", "PortAllocation"}, val: int64(2)},
})
}

func TestControllerGameServersTotal(t *testing.T) {

registry := prometheus.NewRegistry()
_, err := RegisterPrometheusExporter(registry)
assert.Nil(t, err)

resetMetrics()
exporter := &metricExporter{}
reader := metricexport.NewReader()
c := newFakeController()
defer c.close()
c.run(t)
Expand All @@ -82,17 +139,24 @@ func TestControllerGameServersTotal(t *testing.T) {
generateGsEvents(1, agonesv1.GameServerStateUnhealthy, "", c.gsWatch)

c.sync()
report()

assert.Nil(t, testutil.GatherAndCompare(registry, strings.NewReader(gsTotalExpected), "agones_gameservers_total"))
reader.ReadAndExport(exporter)
assertMetricData(t, exporter, "gameservers_total", []expectedMetricData{
{labels: []string{"test", "Creating"}, val: int64(16)},
{labels: []string{"test", "Scheduled"}, val: int64(15)},
{labels: []string{"test", "Starting"}, val: int64(10)},
{labels: []string{"test", "Unhealthy"}, val: int64(1)},
{labels: []string{"none", "Creating"}, val: int64(19)},
{labels: []string{"none", "Scheduled"}, val: int64(18)},
{labels: []string{"none", "Starting"}, val: int64(16)},
{labels: []string{"none", "Unhealthy"}, val: int64(1)},
})
}

func TestControllerFleetReplicasCount(t *testing.T) {

registry := prometheus.NewRegistry()
_, err := RegisterPrometheusExporter(registry)
assert.Nil(t, err)

resetMetrics()
exporter := &metricExporter{}
reader := metricexport.NewReader()
c := newFakeController()
defer c.close()
c.run(t)
Expand All @@ -108,16 +172,24 @@ func TestControllerFleetReplicasCount(t *testing.T) {
c.fleetWatch.Delete(fd)

c.sync()
report()

assert.Nil(t, testutil.GatherAndCompare(registry, strings.NewReader(fleetReplicasCountExpected), "agones_fleets_replicas_count"))
reader.ReadAndExport(exporter)
assertMetricData(t, exporter, "fleets_replicas_count", []expectedMetricData{
{labels: []string{"fleet-deleted", "allocated"}, val: int64(0)},
{labels: []string{"fleet-deleted", "desired"}, val: int64(0)},
{labels: []string{"fleet-deleted", "ready"}, val: int64(0)},
{labels: []string{"fleet-deleted", "total"}, val: int64(0)},
{labels: []string{"fleet-test", "allocated"}, val: int64(2)},
{labels: []string{"fleet-test", "desired"}, val: int64(5)},
{labels: []string{"fleet-test", "ready"}, val: int64(1)},
{labels: []string{"fleet-test", "total"}, val: int64(8)},
})
}

func TestControllerFleetAutoScalerState(t *testing.T) {
registry := prometheus.NewRegistry()
_, err := RegisterPrometheusExporter(registry)
assert.Nil(t, err)

resetMetrics()
exporter := &metricExporter{}
reader := metricexport.NewReader()
c := newFakeController()
defer c.close()
c.run(t)
Expand Down Expand Up @@ -145,34 +217,70 @@ func TestControllerFleetAutoScalerState(t *testing.T) {
c.fasWatch.Delete(fasDeleted)

c.sync()
report()

assert.Nil(t, testutil.GatherAndCompare(registry, strings.NewReader(fasStateExpected),
"agones_fleet_autoscalers_able_to_scale", "agones_fleet_autoscalers_buffer_limits", "agones_fleet_autoscalers_buffer_size",
"agones_fleet_autoscalers_current_replicas_count", "agones_fleet_autoscalers_desired_replicas_count", "agones_fleet_autoscalers_limited"))

reader.ReadAndExport(exporter)
assertMetricData(t, exporter, "fleet_autoscalers_able_to_scale", []expectedMetricData{
{labels: []string{"first-fleet", "name-switch"}, val: int64(0)},
{labels: []string{"second-fleet", "name-switch"}, val: int64(1)},
{labels: []string{"deleted-fleet", "deleted"}, val: int64(0)},
})
assertMetricData(t, exporter, "fleet_autoscalers_buffer_limits", []expectedMetricData{
{labels: []string{"first-fleet", "name-switch", "max"}, val: int64(50)},
{labels: []string{"first-fleet", "name-switch", "min"}, val: int64(10)},
{labels: []string{"second-fleet", "name-switch", "max"}, val: int64(50)},
{labels: []string{"second-fleet", "name-switch", "min"}, val: int64(10)},
{labels: []string{"deleted-fleet", "deleted", "max"}, val: int64(150)},
{labels: []string{"deleted-fleet", "deleted", "min"}, val: int64(15)},
})
assertMetricData(t, exporter, "fleet_autoscalers_buffer_size", []expectedMetricData{
{labels: []string{"first-fleet", "name-switch", "count"}, val: int64(10)},
{labels: []string{"second-fleet", "name-switch", "count"}, val: int64(10)},
{labels: []string{"deleted-fleet", "deleted", "percentage"}, val: int64(50)},
})
assertMetricData(t, exporter, "fleet_autoscalers_current_replicas_count", []expectedMetricData{
{labels: []string{"first-fleet", "name-switch"}, val: int64(0)},
{labels: []string{"second-fleet", "name-switch"}, val: int64(20)},
{labels: []string{"deleted-fleet", "deleted"}, val: int64(0)},
})
assertMetricData(t, exporter, "fleet_autoscalers_desired_replicas_count", []expectedMetricData{
{labels: []string{"first-fleet", "name-switch"}, val: int64(0)},
{labels: []string{"second-fleet", "name-switch"}, val: int64(10)},
{labels: []string{"deleted-fleet", "deleted"}, val: int64(0)},
})
assertMetricData(t, exporter, "fleet_autoscalers_limited", []expectedMetricData{
{labels: []string{"first-fleet", "name-switch"}, val: int64(0)},
{labels: []string{"second-fleet", "name-switch"}, val: int64(1)},
{labels: []string{"deleted-fleet", "deleted"}, val: int64(0)},
})
}

func TestControllerGameServersNodeState(t *testing.T) {
registry := prometheus.NewRegistry()
_, err := RegisterPrometheusExporter(registry)
assert.Nil(t, err)

resetMetrics()
c := newFakeController()
defer c.close()

c.nodeWatch.Add(nodeWithName("node1"))
c.nodeWatch.Add(nodeWithName("node2"))
c.nodeWatch.Add(nodeWithName("node3"))
c.gsWatch.Add(gameServerWithNode("node1"))
c.gsWatch.Add(gameServerWithNode("node2"))
c.gsWatch.Add(gameServerWithNode("node2"))

c.run(t)
c.sync()
c.collect()
report()

if err := testutil.GatherAndCompare(registry, strings.NewReader(nodeCountExpected), "agones_nodes_count", "agones_gameservers_node_count"); err != nil {
t.Fatal(err)
}
exporter := &metricExporter{}
reader := metricexport.NewReader()
reader.ReadAndExport(exporter)
assertMetricData(t, exporter, "gameservers_node_count", []expectedMetricData{
{labels: []string{}, val: &metricdata.Distribution{
Count: 3,
Sum: 3,
SumOfSquaredDeviation: 2,
BucketOptions: &metricdata.BucketOptions{Bounds: []float64{0.00001, 1.00001, 2.00001, 3.00001, 4.00001, 5.00001, 6.00001, 7.00001, 8.00001, 9.00001, 10.00001, 11.00001, 12.00001, 13.00001, 14.00001, 15.00001, 16.00001, 32.00001, 40.00001, 50.00001, 60.00001, 70.00001, 80.00001, 90.00001, 100.00001, 110.00001, 120.00001}},
Buckets: []metricdata.Bucket{{Count: 1}, {Count: 1}, {Count: 1}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}, {Count: 0}}}},
})
assertMetricData(t, exporter, "nodes_count", []expectedMetricData{
{labels: []string{"true"}, val: int64(1)},
{labels: []string{"false"}, val: int64(2)},
})
}
2 changes: 1 addition & 1 deletion pkg/metrics/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import (
"time"

"cloud.google.com/go/compute/metadata"
"contrib.go.opencensus.io/exporter/prometheus"
"contrib.go.opencensus.io/exporter/stackdriver"
"github.com/pkg/errors"
prom "github.com/prometheus/client_golang/prometheus"
"go.opencensus.io/exporter/prometheus"
"go.opencensus.io/stats/view"
"google.golang.org/genproto/googleapis/api/monitoredres"
)
Expand Down
Loading

0 comments on commit e4c126a

Please sign in to comment.