agones.dev/agones@v1.53.0/pkg/metrics/gameservers_count.go (about) 1 // Copyright 2019 Google LLC All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package metrics 16 17 import ( 18 "context" 19 20 agonesv1 "agones.dev/agones/pkg/apis/agones/v1" 21 "go.opencensus.io/stats" 22 "go.opencensus.io/tag" 23 "k8s.io/apimachinery/pkg/util/errors" 24 ) 25 26 const defaultFleetTag = "none" 27 28 // GameServerCount is the count of gameserver per current state and per fleet name 29 type GameServerCount map[agonesv1.GameServerState]map[fleetKey]int64 30 31 type fleetKey struct { 32 name string 33 namespace string 34 } 35 36 // increment adds the count of gameservers for a given fleetName and state 37 func (c GameServerCount) increment(key fleetKey, state agonesv1.GameServerState) { 38 fleets, ok := c[state] 39 if !ok { 40 fleets = map[fleetKey]int64{} 41 c[state] = fleets 42 } 43 fleets[key]++ 44 } 45 46 // reset sets zero to the whole metrics set 47 func (c GameServerCount) reset() { 48 for _, fleets := range c { 49 for fleet := range fleets { 50 fleets[fleet] = 0 51 } 52 } 53 } 54 55 // record counts the list of gameserver per status and fleet name and record it to OpenCensus 56 func (c GameServerCount) record(gameservers []*agonesv1.GameServer) error { 57 // Currently there is no way to remove a metric so we have to reset our values to zero 58 // so that statuses that have no count anymore are zeroed. 59 // Otherwise OpenCensus will write the last value recorded to the prom endpoint. 60 // TL;DR we can't remove a gauge 61 c.reset() 62 63 // only record gameservers's fleet count 64 fleetNameMap := map[fleetKey]struct{}{} 65 66 // counts gameserver per state and fleet 67 for _, g := range gameservers { 68 fleetName := g.Labels[agonesv1.FleetNameLabel] 69 fleetNamespace := g.GetNamespace() 70 key := fleetKey{name: fleetName, namespace: fleetNamespace} 71 72 fleetNameMap[key] = struct{}{} 73 c.increment(key, g.Status.State) 74 } 75 76 errs := []error{} 77 deletedFleets := map[agonesv1.GameServerState][]fleetKey{} 78 for state, fleets := range c { 79 for fleet, count := range fleets { 80 if _, ok := fleetNameMap[fleet]; !ok { 81 if _, ok := deletedFleets[state]; !ok { 82 deletedFleets[state] = []fleetKey{} 83 } 84 deletedFleets[state] = append(deletedFleets[state], fleet) 85 } 86 87 if fleet.name == "" { 88 fleet.name = noneValue 89 } 90 if fleet.namespace == "" { 91 fleet.namespace = noneValue 92 } 93 94 if err := stats.RecordWithTags(context.Background(), []tag.Mutator{tag.Upsert(keyType, string(state)), 95 tag.Upsert(keyFleetName, fleet.name), tag.Upsert(keyNamespace, fleet.namespace)}, gameServerCountStats.M(count)); err != nil { 96 errs = append(errs, err) 97 } 98 } 99 } 100 101 for state, fleets := range deletedFleets { 102 for _, fleet := range fleets { 103 delete(c[state], fleet) 104 } 105 } 106 return errors.NewAggregate(errs) 107 }