diff --git a/install/helm/agones/templates/crds/fleet.yaml b/install/helm/agones/templates/crds/fleet.yaml index a3a1d3fbd6..e6da262e57 100644 --- a/install/helm/agones/templates/crds/fleet.yaml +++ b/install/helm/agones/templates/crds/fleet.yaml @@ -157,6 +157,9 @@ spec: allocatedReplicas: type: integer minimum: 0 + allocations: + type: integer + minimum: 0 players: type: object nullable: true diff --git a/install/yaml/install.yaml b/install/yaml/install.yaml index 81c2b12967..7a56fb1bf5 100644 --- a/install/yaml/install.yaml +++ b/install/yaml/install.yaml @@ -6583,6 +6583,9 @@ spec: allocatedReplicas: type: integer minimum: 0 + allocations: + type: integer + minimum: 0 players: type: object nullable: true diff --git a/pkg/apis/agones/v1/fleet.go b/pkg/apis/agones/v1/fleet.go index c1c877b164..7b659cc149 100644 --- a/pkg/apis/agones/v1/fleet.go +++ b/pkg/apis/agones/v1/fleet.go @@ -96,6 +96,8 @@ type FleetStatus struct { ReservedReplicas int32 `json:"reservedReplicas"` // AllocatedReplicas are the number of Allocated GameServer replicas AllocatedReplicas int32 `json:"allocatedReplicas"` + // Allocations is a counter of the number of allocations observed. + Allocations int64 `json:"allocations"` // [Stage:Alpha] // [FeatureFlag:PlayerTracking] // Players are the current total player capacity and count for this Fleet diff --git a/pkg/client/applyconfiguration/agones/v1/fleetstatus.go b/pkg/client/applyconfiguration/agones/v1/fleetstatus.go index 8ef8c8eafe..acae7b5a2a 100644 --- a/pkg/client/applyconfiguration/agones/v1/fleetstatus.go +++ b/pkg/client/applyconfiguration/agones/v1/fleetstatus.go @@ -25,6 +25,7 @@ type FleetStatusApplyConfiguration struct { ReadyReplicas *int32 `json:"readyReplicas,omitempty"` ReservedReplicas *int32 `json:"reservedReplicas,omitempty"` AllocatedReplicas *int32 `json:"allocatedReplicas,omitempty"` + Allocations *int64 `json:"allocations,omitempty"` Players *AggregatedPlayerStatusApplyConfiguration `json:"players,omitempty"` Counters map[string]AggregatedCounterStatusApplyConfiguration `json:"counters,omitempty"` Lists map[string]AggregatedListStatusApplyConfiguration `json:"lists,omitempty"` @@ -68,6 +69,14 @@ func (b *FleetStatusApplyConfiguration) WithAllocatedReplicas(value int32) *Flee return b } +// WithAllocations sets the Allocations field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Allocations field is set to the value of the last call. +func (b *FleetStatusApplyConfiguration) WithAllocations(value int64) *FleetStatusApplyConfiguration { + b.Allocations = &value + return b +} + // WithPlayers sets the Players field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Players field is set to the value of the last call. diff --git a/pkg/fleets/controller.go b/pkg/fleets/controller.go index 1e9113ce56..6833bbae96 100644 --- a/pkg/fleets/controller.go +++ b/pkg/fleets/controller.go @@ -18,6 +18,9 @@ import ( "context" "encoding/json" "fmt" + "maps" + "sync" + "sync/atomic" "time" "agones.dev/agones/pkg/apis/agones" @@ -64,12 +67,14 @@ type Extensions struct { type Controller struct { baseLogger *logrus.Entry crdGetter apiextclientv1.CustomResourceDefinitionInterface + gameServerSynced cache.InformerSynced gameServerSetGetter getterv1.GameServerSetsGetter gameServerSetLister listerv1.GameServerSetLister gameServerSetSynced cache.InformerSynced fleetGetter getterv1.FleetsGetter fleetLister listerv1.FleetLister fleetSynced cache.InformerSynced + allocs *allocTracker workerqueue *workerqueue.WorkerQueue recorder record.EventRecorder } @@ -82,6 +87,9 @@ func NewController( agonesClient versioned.Interface, agonesInformerFactory externalversions.SharedInformerFactory) *Controller { + gameServers := agonesInformerFactory.Agones().V1().GameServers() + gsInformer := gameServers.Informer() + gameServerSets := agonesInformerFactory.Agones().V1().GameServerSets() gsSetInformer := gameServerSets.Informer() @@ -90,12 +98,14 @@ func NewController( c := &Controller{ crdGetter: extClient.ApiextensionsV1().CustomResourceDefinitions(), + gameServerSynced: gsInformer.HasSynced, gameServerSetGetter: agonesClient.AgonesV1(), gameServerSetLister: gameServerSets.Lister(), gameServerSetSynced: gsSetInformer.HasSynced, fleetGetter: agonesClient.AgonesV1(), fleetLister: fleets.Lister(), fleetSynced: fInformer.HasSynced, + allocs: newAllocTracker(), } c.baseLogger = runtime.NewLoggerWithType(c) @@ -112,6 +122,11 @@ func NewController( UpdateFunc: func(_, newObj interface{}) { c.workerqueue.Enqueue(newObj) }, + DeleteFunc: func(obj interface{}) { + fleet := obj.(*agonesv1.Fleet) + + c.allocs.remove(fleet.ObjectMeta.Namespace, fleet.ObjectMeta.Name) + }, }) _, _ = gsSetInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -125,6 +140,25 @@ func NewController( }, }) + _, _ = gsInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + UpdateFunc: func(oldObj, newObj interface{}) { + oldGs := oldObj.(*agonesv1.GameServer) + newGs := newObj.(*agonesv1.GameServer) + + if oldGs.Status.State == agonesv1.GameServerStateAllocated || newGs.Status.State != agonesv1.GameServerStateAllocated { + // Count only the transition of a GameServer into the Allocated state. + return + } + fleet, ok := newGs.Labels[agonesv1.FleetNameLabel] + if !ok || fleet == "" { + // The game server is not attached to a fleet. Nothing to do. + return + } + + c.allocs.inc(newGs.Namespace, fleet, 1) + }, + }) + return c } @@ -221,11 +255,13 @@ func (c *Controller) Run(ctx context.Context, workers int) error { } c.baseLogger.Debug("Wait for cache sync") - if !cache.WaitForCacheSync(ctx.Done(), c.gameServerSetSynced, c.fleetSynced) { + if !cache.WaitForCacheSync(ctx.Done(), c.gameServerSynced, c.gameServerSetSynced, c.fleetSynced) { return errors.New("failed to wait for caches to sync") } c.workerqueue.Run(ctx, workers) + + c.flushAllocations() return nil } @@ -723,8 +759,18 @@ func (c *Controller) updateFleetStatus(ctx context.Context, fleet *agonesv1.Flee } } + allocs := c.allocs.get(fleet.ObjectMeta.Namespace, fleet.ObjectMeta.Name) + fCopy.Status.Allocations += allocs + _, err = c.fleetGetter.Fleets(fCopy.ObjectMeta.Namespace).UpdateStatus(ctx, fCopy, metav1.UpdateOptions{}) - return errors.Wrapf(err, "error updating status of fleet %s", fCopy.ObjectMeta.Name) + if err != nil { + return errors.Wrapf(err, "error updating status of fleet %s", fCopy.ObjectMeta.Name) + } + + // The update was successful, the allocation count must be decremented to reflect this. + c.allocs.dec(fleet.ObjectMeta.Namespace, fleet.ObjectMeta.Name, allocs) + + return nil } // filterGameServerSetByActive returns the active GameServerSet (or nil if it @@ -760,6 +806,107 @@ func (c *Controller) filterGameServerSetByActive(fleet *agonesv1.Fleet, list []* return active, rest } +func (c *Controller) flushAllocations() { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + c.allocs.forEach(func(ns, fleetName string, count int64) { + fCopy, err := c.fleetGetter.Fleets(ns).Get(ctx, fleetName, metav1.GetOptions{}) + if err != nil { + return + } + + fCopy.Status.Allocations += count + + _, _ = c.fleetGetter.Fleets(ns).UpdateStatus(ctx, fCopy, metav1.UpdateOptions{}) + }) +} + +type allocTracker struct { + counts map[string]*atomic.Int64 + mu sync.RWMutex +} + +func newAllocTracker() *allocTracker { + return &allocTracker{counts: map[string]*atomic.Int64{}} +} + +func (t *allocTracker) get(ns, fleetName string) int64 { + key := cache.ObjectName{Namespace: ns, Name: fleetName}.String() + + t.mu.RLock() + defer t.mu.RUnlock() + + counts, ok := t.counts[key] + if !ok { + return 0 + } + return counts.Load() +} + +func (t *allocTracker) inc(ns, fleetName string, v int64) { + key := cache.ObjectName{Namespace: ns, Name: fleetName}.String() + + t.mu.RLock() + count, ok := t.counts[key] + if ok { + count.Add(v) + t.mu.RUnlock() + return + } + t.mu.RUnlock() + + t.mu.Lock() + defer t.mu.Unlock() + + count, ok = t.counts[key] + if !ok { + count = &atomic.Int64{} + t.counts[key] = count + } + count.Add(v) +} + +func (t *allocTracker) dec(ns, fleetName string, v int64) { + key := cache.ObjectName{Namespace: ns, Name: fleetName}.String() + v = -1 * v + + t.mu.RLock() + defer t.mu.RUnlock() + + // We do not decrement something that does not exist. This would + // lead to some fairly confusing results. + count, ok := t.counts[key] + if ok { + count.Add(v) + } +} + +func (t *allocTracker) remove(ns, fleetName string) { + key := cache.ObjectName{Namespace: ns, Name: fleetName}.String() + + t.mu.Lock() + defer t.mu.Unlock() + + delete(t.counts, key) +} + +func (t *allocTracker) forEach(fn func(ns, fleetName string, count int64)) { + t.mu.Lock() + counts := make(map[string]*atomic.Int64, len(t.counts)) + maps.Copy(counts, t.counts) + t.mu.Unlock() + + for key, count := range counts { + if count.Load() == 0 { + continue + } + + ns, fleetName, _ := cache.SplitMetaNamespaceKey(key) + fn(ns, fleetName, count.Load()) + } +} + // mergeCounters adds the contents of AggregatedCounterStatus c2 into c1. func mergeCounters(c1, c2 map[string]agonesv1.AggregatedCounterStatus) map[string]agonesv1.AggregatedCounterStatus { if c1 == nil { diff --git a/pkg/fleets/controller_test.go b/pkg/fleets/controller_test.go index 7f8aaf63a5..d6906a520e 100644 --- a/pkg/fleets/controller_test.go +++ b/pkg/fleets/controller_test.go @@ -310,6 +310,37 @@ func TestControllerSyncFleet(t *testing.T) { agtesting.AssertNoEvent(t, m.FakeRecorder.Events) }) + t.Run("fleets update allocation counter", func(t *testing.T) { + f := defaultFixture() + f.Spec.Strategy.Type = appsv1.RollingUpdateDeploymentStrategyType + + c, m := newFakeController() + gsSet := f.GameServerSet() + gsSet.ObjectMeta.Name = "gsSet1" + gsSet.ObjectMeta.UID = "4321" + gsSet.Spec.Replicas = f.Spec.Replicas + + m.AgonesClient.AddReactor("list", "fleets", func(_ k8stesting.Action) (bool, runtime.Object, error) { + return true, &agonesv1.FleetList{Items: []agonesv1.Fleet{*f}}, nil + }) + m.AgonesClient.AddReactor("get", "fleets", func(_ k8stesting.Action) (bool, runtime.Object, error) { + return true, f, nil + }) + + m.AgonesClient.AddReactor("list", "gameserversets", func(_ k8stesting.Action) (bool, runtime.Object, error) { + return true, &agonesv1.GameServerSetList{Items: []agonesv1.GameServerSet{*gsSet}}, nil + }) + + ctx, cancel := agtesting.StartInformers(m, c.fleetSynced, c.gameServerSetSynced) + defer cancel() + + c.allocs.inc("default", "fleet-1", 1) + + err := c.syncFleet(ctx, "default/fleet-1") + assert.Nil(t, err) + assert.Equal(t, int64(1), f.Status.Allocations) + }) + t.Run("error on getting fleet", func(t *testing.T) { c, _ := newFakeController() c.fleetLister = &fakeFleetListerWithErr{} diff --git a/pkg/metrics/controller.go b/pkg/metrics/controller.go index f548c0bfbb..d066ee3201 100644 --- a/pkg/metrics/controller.go +++ b/pkg/metrics/controller.go @@ -456,6 +456,9 @@ func (c *Controller) recordGameServerStatusChanges(old, next interface{}) { if newGs.Status.State != oldGs.Status.State { RecordWithTags(context.Background(), []tag.Mutator{tag.Upsert(keyType, string(newGs.Status.State)), tag.Upsert(keyFleetName, fleetName), tag.Upsert(keyNamespace, newGs.GetNamespace())}, gameServerTotalStats.M(1)) + if newGs.Status.State == agonesv1.GameServerStateAllocated { + RecordWithTags(context.Background(), []tag.Mutator{tag.Upsert(keyFleetName, fleetName), tag.Upsert(keyNamespace, newGs.GetNamespace())}, gameServerAllocationsTotalStats.M(1)) + } // Calculate the duration of the current state duration, err := c.calcDuration(oldGs, newGs) diff --git a/pkg/metrics/controller_metrics.go b/pkg/metrics/controller_metrics.go index 313deca1c4..e83a9e0836 100644 --- a/pkg/metrics/controller_metrics.go +++ b/pkg/metrics/controller_metrics.go @@ -33,6 +33,7 @@ const ( fleetListsName = "fleet_lists" gameServersCountName = "gameservers_count" gameServersTotalName = "gameservers_total" + gameServersAllocationsTotalName = "gameservers_allocations_total" gameServersPlayerConnectedTotalName = "gameserver_player_connected_total" gameServersPlayerCapacityTotalName = "gameserver_player_capacity_total" nodeCountName = "nodes_count" @@ -47,24 +48,25 @@ var ( // fleetViews are metric views associated with Fleets fleetViews = append([]string{fleetRolloutPercent, fleetReplicaCountName, gameServersCountName, gameServersTotalName, gameServersPlayerConnectedTotalName, gameServersPlayerCapacityTotalName, gameServerStateDurationName, fleetCountersName, fleetListsName}, fleetAutoscalerViews...) - stateDurationSeconds = []float64{0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384} - fleetRolloutPercentStats = stats.Int64("fleets/rollout_percent", "The current fleet rollout percentage", "1") - fleetsReplicasCountStats = stats.Int64("fleets/replicas_count", "The count of replicas per fleet", "1") - fasBufferLimitsCountStats = stats.Int64("fas/buffer_limits", "The buffer limits of autoscalers", "1") - fasBufferSizeStats = stats.Int64("fas/buffer_size", "The buffer size value of autoscalers", "1") - fasCurrentReplicasStats = stats.Int64("fas/current_replicas_count", "The current replicas cout as seen by autoscalers", "1") - fasDesiredReplicasStats = stats.Int64("fas/desired_replicas_count", "The desired replicas cout as seen by autoscalers", "1") - fasAbleToScaleStats = stats.Int64("fas/able_to_scale", "The fleet autoscaler can access the fleet to scale (0 indicates false, 1 indicates true)", "1") - fasLimitedStats = stats.Int64("fas/limited", "The fleet autoscaler is capped (0 indicates false, 1 indicates true)", "1") - fleetCountersStats = stats.Int64("fleets/counters", "Aggregated Counters counts and capacity across GameServers in the Fleet", "1") - fleetListsStats = stats.Int64("fleets/lists", "Aggregated Lists counts and capacity across GameServers in the Fleet", "1") - gameServerCountStats = stats.Int64("gameservers/count", "The count of gameservers", "1") - gameServerTotalStats = stats.Int64("gameservers/total", "The total of gameservers", "1") - gameServerPlayerConnectedTotal = stats.Int64("gameservers/player_connected", "The total number of players connected to gameservers", "1") - gameServerPlayerCapacityTotal = stats.Int64("gameservers/player_capacity", "The available player capacity for gameservers", "1") - nodesCountStats = stats.Int64("nodes/count", "The count of nodes in the cluster", "1") - gsPerNodesCountStats = stats.Int64("gameservers_node/count", "The count of gameservers per node in the cluster", "1") - gsStateDurationSec = stats.Float64("gameservers_state/duration", "The duration of gameservers to be in a particular state", stats.UnitSeconds) + stateDurationSeconds = []float64{0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384} + fleetRolloutPercentStats = stats.Int64("fleets/rollout_percent", "The current fleet rollout percentage", "1") + fleetsReplicasCountStats = stats.Int64("fleets/replicas_count", "The count of replicas per fleet", "1") + fasBufferLimitsCountStats = stats.Int64("fas/buffer_limits", "The buffer limits of autoscalers", "1") + fasBufferSizeStats = stats.Int64("fas/buffer_size", "The buffer size value of autoscalers", "1") + fasCurrentReplicasStats = stats.Int64("fas/current_replicas_count", "The current replicas cout as seen by autoscalers", "1") + fasDesiredReplicasStats = stats.Int64("fas/desired_replicas_count", "The desired replicas cout as seen by autoscalers", "1") + fasAbleToScaleStats = stats.Int64("fas/able_to_scale", "The fleet autoscaler can access the fleet to scale (0 indicates false, 1 indicates true)", "1") + fasLimitedStats = stats.Int64("fas/limited", "The fleet autoscaler is capped (0 indicates false, 1 indicates true)", "1") + fleetCountersStats = stats.Int64("fleets/counters", "Aggregated Counters counts and capacity across GameServers in the Fleet", "1") + fleetListsStats = stats.Int64("fleets/lists", "Aggregated Lists counts and capacity across GameServers in the Fleet", "1") + gameServerCountStats = stats.Int64("gameservers/count", "The count of gameservers", "1") + gameServerTotalStats = stats.Int64("gameservers/total", "The total of gameservers", "1") + gameServerAllocationsTotalStats = stats.Int64("gameservers/allocations_total", "The total of gameserver allocations", "1") + gameServerPlayerConnectedTotal = stats.Int64("gameservers/player_connected", "The total number of players connected to gameservers", "1") + gameServerPlayerCapacityTotal = stats.Int64("gameservers/player_capacity", "The available player capacity for gameservers", "1") + nodesCountStats = stats.Int64("nodes/count", "The count of nodes in the cluster", "1") + gsPerNodesCountStats = stats.Int64("gameservers_node/count", "The count of gameservers per node in the cluster", "1") + gsStateDurationSec = stats.Float64("gameservers_state/duration", "The duration of gameservers to be in a particular state", stats.UnitSeconds) stateViews = []*view.View{ { @@ -151,6 +153,13 @@ var ( Aggregation: view.Count(), TagKeys: []tag.Key{keyType, keyFleetName, keyNamespace}, }, + { + Name: gameServersAllocationsTotalName, + Measure: gameServerAllocationsTotalStats, + Description: "The total of gameserver allocations", + Aggregation: view.Count(), + TagKeys: []tag.Key{keyFleetName, keyNamespace}, + }, { Name: gameServersPlayerConnectedTotalName, Measure: gameServerPlayerConnectedTotal, diff --git a/pkg/metrics/controller_test.go b/pkg/metrics/controller_test.go index e2827d54ad..48de7698cb 100644 --- a/pkg/metrics/controller_test.go +++ b/pkg/metrics/controller_test.go @@ -428,6 +428,44 @@ func TestControllerGameServersTotal(t *testing.T) { }) } +func TestControllerGameServerAllocationsTotal(t *testing.T) { + mu.Lock() + defer mu.Unlock() + resetMetrics() + reader := metricexport.NewReader() + c := newFakeController() + defer c.close() + c.run(t) + + // deleted gs should not be counted + gs := gameServerWithFleetAndState("deleted", agonesv1.GameServerStateCreating) + c.gsWatch.Add(gs) + c.gsWatch.Delete(gs) + + generateGsEvents(15, agonesv1.GameServerStateAllocated, "test", c.gsWatch) + generateGsEvents(19, agonesv1.GameServerStateAllocated, "", c.gsWatch) + + expected := 34 + assert.Eventually(t, func() bool { + list, err := c.gameServerLister.GameServers(gs.ObjectMeta.Namespace).List(labels.Everything()) + if err != nil || list == nil { + return false + } + require.NoError(t, err) + return len(list) == expected + }, 10*time.Second, time.Second) + // While these values are tested above, the following test checks will provide a more detailed diff output + // in the case where the assert.Eventually(...) case fails, which makes failing tests easier to debug. + + list, err := c.gameServerLister.GameServers(gs.ObjectMeta.Namespace).List(labels.Everything()) + require.NoError(t, err) + require.Len(t, list, expected) + assertMetricData(t, c, func() {}, reader, gameServersAllocationsTotalName, []expectedMetricData{ + {labels: []string{"test", defaultNs}, val: int64(15)}, + {labels: []string{"none", defaultNs}, val: int64(19)}, + }) +} + func TestControllerFleetOnDeleting(t *testing.T) { mu.Lock() defer mu.Unlock() diff --git a/pkg/metrics/exporter_test.go b/pkg/metrics/exporter_test.go index 447fef0cbe..be2e434992 100644 --- a/pkg/metrics/exporter_test.go +++ b/pkg/metrics/exporter_test.go @@ -100,6 +100,7 @@ func TestMetrics_Endpoint_ExposesAllMetrics(t *testing.T) { setupFleetWithCountersAndLists, setupGameServerPlayerConnect, setupGameServerStateDuration, + setupGameServerAllocation, } for _, stepFn := range setupSteps { @@ -274,6 +275,21 @@ func setupGameServerPlayerConnect(t *testing.T, ctrl *fakeController) { ctrl.collect() } +func setupGameServerAllocation(t *testing.T, ctrl *fakeController) { + gs := gameServerWithFleetAndState("test-fleet", agonesv1.GameServerStateCreating) + ctrl.gsWatch.Add(gs) + gs = gs.DeepCopy() + gs.Status.State = agonesv1.GameServerStateAllocated + ctrl.gsWatch.Modify(gs) + + require.EventuallyWithT(t, func(collect *assert.CollectT) { + gs, err := ctrl.gameServerLister.GameServers(gs.ObjectMeta.Namespace).Get(gs.ObjectMeta.Name) + require.NoError(collect, err) + assert.Equal(collect, gs.Status.State, agonesv1.GameServerStateAllocated) + }, 5*time.Second, time.Second) + ctrl.collect() +} + func setupGameServerStateDuration(_ *testing.T, ctrl *fakeController) { creationTimestamp := metav1.Now() currentTime := creationTimestamp.Local() diff --git a/site/content/en/docs/Guides/metrics.md b/site/content/en/docs/Guides/metrics.md index 3c21352d8b..280c304bd0 100644 --- a/site/content/en/docs/Guides/metrics.md +++ b/site/content/en/docs/Guides/metrics.md @@ -45,6 +45,7 @@ Follow the [Google Cloud Monitoring installation steps](#google-cloud-monitoring +{{% feature expiryVersion="1.58.0" %}} | Name | Description | Type | |-------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------| | agones_gameservers_count | The number of gameservers per fleet and status | gauge | @@ -75,7 +76,40 @@ Follow the [Google Cloud Monitoring installation steps](#google-cloud-monitoring | agones_k8s_client_workqueue_retries_total | Total number of items retried to the work queue | counter | | agones_k8s_client_workqueue_longest_running_processor | How long the longest running workqueue processor has been running in microseconds | gauge | | agones_k8s_client_workqueue_unfinished_work_seconds | How long unfinished work has been sitting in the workqueue in seconds | gauge | - +{{% /feature %}} +{{% feature publishVersion="1.58.0" %}} +| Name | Description | Type | +|-------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------| +| agones_gameservers_count | The number of gameservers per fleet and status | gauge | +| agones_gameserver_allocations_duration_seconds | The distribution of gameserver allocation requests latencies | histogram | +| agones_gameserver_allocations_retry_total | The count of gameserver allocation retry until it succeeds | histogram | +| agones_gameserver_creation_duration | The time gameserver takes to be created in seconds | histogram | +| agones_gameservers_total | The total of gameservers per fleet and status | counter | +| agones_gameservers_allocations_total | The total of gameserver allocations | counter | +| agones_gameserver_player_connected_total | The total number of players connected to gameservers (Only available when [player tracking]({{< relref "player-tracking.md" >}}) is enabled) | gauge | +| agones_gameserver_player_capacity_total | The available capacity for players on gameservers (Only available when [player tracking]({{< relref "player-tracking.md" >}}) is enabled) | gauge | +| agones_fleets_replicas_count | The number of replicas per fleet (total, desired, ready, reserved, allocated) | gauge | +| agones_fleet_counters | Aggregate Metrics for Counters within a Fleet, including total capacity and count values (Only available when [Counters and Lists]({{< relref "counters-and-lists.md" >}})) are enabled) | gauge | +| agones_fleet_lists | Aggregate Metrics for Lists within a Fleet, including total capacity and List lengths (Only available when [Counters and Lists]({{< relref "counters-and-lists.md" >}})) are enabled) | gauge | +| agones_fleet_autoscalers_able_to_scale | The fleet autoscaler can access the fleet to scale | gauge | +| agones_fleet_autoscalers_buffer_limits | The limits of buffer based fleet autoscalers (min, max) | gauge | +| agones_fleet_autoscalers_buffer_size | The buffer size of fleet autoscalers (count or percentage) | gauge | +| agones_fleet_autoscalers_current_replicas_count | The current replicas count as seen by autoscalers | gauge | +| agones_fleet_autoscalers_desired_replicas_count | The desired replicas count as seen by autoscalers | gauge | +| agones_fleet_autoscalers_limited | The fleet autoscaler is outside the limits set by MinReplicas and MaxReplicas. | gauge | +| agones_gameservers_node_count | The distribution of gameservers per node | histogram | +| agones_nodes_count | The count of nodes empty and with gameservers | gauge | +| agones_gameserver_state_duration | The distribution of gameserver state duration in seconds. Note: this metric could have some missing samples by design. Do not use the `_total` counter as the real value for state changes. | histogram | +| agones_k8s_client_http_request_total | The total of HTTP requests to the Kubernetes API by status code | counter | +| agones_k8s_client_http_request_duration_seconds | The distribution of HTTP requests latencies to the Kubernetes API by status code | histogram | +| agones_k8s_client_workqueue_depth | Current depth of the work queue | gauge | +| agones_k8s_client_workqueue_latency_seconds | How long an item stays in the work queue | histogram | +| agones_k8s_client_workqueue_items_total | Total number of items added to the work queue | counter | +| agones_k8s_client_workqueue_work_duration_seconds | How long processing an item from the work queue takes | histogram | +| agones_k8s_client_workqueue_retries_total | Total number of items retried to the work queue | counter | +| agones_k8s_client_workqueue_longest_running_processor | How long the longest running workqueue processor has been running in microseconds | gauge | +| agones_k8s_client_workqueue_unfinished_work_seconds | How long unfinished work has been sitting in the workqueue in seconds | gauge | +{{% /feature %}} ### Dropping Metric Labels diff --git a/site/content/en/docs/Reference/agones_crd_api_reference.html b/site/content/en/docs/Reference/agones_crd_api_reference.html index 4c0c4754db..3221e512a2 100644 --- a/site/content/en/docs/Reference/agones_crd_api_reference.html +++ b/site/content/en/docs/Reference/agones_crd_api_reference.html @@ -3,7 +3,7 @@ description="Detailed list of Agones Custom Resource Definitions available" +++ -{{% feature expiryVersion="1.57.0" %}} +{{% feature expiryVersion="1.58.0" %}}
Packages:
metadatastrategymetadatatemplatemetadatastrategyprotocoltemplateaddressesreservedUntilmetadatatemplatemetadataaddressesLabelSelectorpolicySelectormetadatastartendlastScaleTimeservicemetadatagen-crd-api-reference-docs.
{{% /feature %}}
-{{% feature publishVersion="1.57.0" %}}
+{{% feature publishVersion="1.58.0" %}}
Packages: