agones.dev/agones@v1.54.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  }