k8s.io/apiserver@v0.31.1/pkg/util/flowcontrol/metrics/metrics.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package metrics 18 19 import ( 20 "context" 21 "strconv" 22 "strings" 23 "sync" 24 "time" 25 26 epmetrics "k8s.io/apiserver/pkg/endpoints/metrics" 27 apirequest "k8s.io/apiserver/pkg/endpoints/request" 28 compbasemetrics "k8s.io/component-base/metrics" 29 "k8s.io/component-base/metrics/legacyregistry" 30 basemetricstestutil "k8s.io/component-base/metrics/testutil" 31 ) 32 33 const ( 34 namespace = "apiserver" 35 subsystem = "flowcontrol" 36 ) 37 38 const ( 39 requestKind = "request_kind" 40 priorityLevel = "priority_level" 41 flowSchema = "flow_schema" 42 phase = "phase" 43 LabelNamePhase = "phase" 44 LabelValueWaiting = "waiting" 45 LabelValueExecuting = "executing" 46 ) 47 48 var ( 49 queueLengthBuckets = []float64{0, 10, 25, 50, 100, 250, 500, 1000} 50 requestDurationSecondsBuckets = []float64{0, 0.005, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 15, 30} 51 ) 52 53 var registerMetrics sync.Once 54 55 // Register all metrics. 56 func Register() { 57 registerMetrics.Do(func() { 58 for _, metric := range metrics { 59 legacyregistry.MustRegister(metric) 60 } 61 }) 62 } 63 64 type resettable interface { 65 Reset() 66 } 67 68 // Reset all resettable metrics to zero 69 func Reset() { 70 for _, metric := range metrics { 71 if rm, ok := metric.(resettable); ok { 72 rm.Reset() 73 } 74 } 75 } 76 77 // GatherAndCompare the given metrics with the given Prometheus syntax expected value 78 func GatherAndCompare(expected string, metricNames ...string) error { 79 return basemetricstestutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(expected), metricNames...) 80 } 81 82 // Registerables is a slice of Registerable 83 type Registerables []compbasemetrics.Registerable 84 85 // Append adds more 86 func (rs Registerables) Append(more ...compbasemetrics.Registerable) Registerables { 87 return append(rs, more...) 88 } 89 90 var ( 91 apiserverRejectedRequestsTotal = compbasemetrics.NewCounterVec( 92 &compbasemetrics.CounterOpts{ 93 Namespace: namespace, 94 Subsystem: subsystem, 95 Name: "rejected_requests_total", 96 Help: "Number of requests rejected by API Priority and Fairness subsystem", 97 StabilityLevel: compbasemetrics.BETA, 98 }, 99 []string{priorityLevel, flowSchema, "reason"}, 100 ) 101 apiserverDispatchedRequestsTotal = compbasemetrics.NewCounterVec( 102 &compbasemetrics.CounterOpts{ 103 Namespace: namespace, 104 Subsystem: subsystem, 105 Name: "dispatched_requests_total", 106 Help: "Number of requests executed by API Priority and Fairness subsystem", 107 StabilityLevel: compbasemetrics.BETA, 108 }, 109 []string{priorityLevel, flowSchema}, 110 ) 111 // PriorityLevelExecutionSeatsGaugeVec creates observers of seats occupied throughout execution for priority levels 112 PriorityLevelExecutionSeatsGaugeVec = NewTimingRatioHistogramVec( 113 &compbasemetrics.TimingHistogramOpts{ 114 Namespace: namespace, 115 Subsystem: subsystem, 116 Name: "priority_level_seat_utilization", 117 Help: "Observations, at the end of every nanosecond, of utilization of seats for any stage of execution (but only initial stage for WATCHes)", 118 // Buckets for both 0.99 and 1.0 mean PromQL's histogram_quantile will reveal saturation 119 Buckets: []float64{0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 1}, 120 ConstLabels: map[string]string{phase: "executing"}, 121 StabilityLevel: compbasemetrics.ALPHA, 122 }, 123 priorityLevel, 124 ) 125 // PriorityLevelConcurrencyGaugeVec creates gauges of concurrency broken down by phase, priority level 126 PriorityLevelConcurrencyGaugeVec = NewTimingRatioHistogramVec( 127 &compbasemetrics.TimingHistogramOpts{ 128 Namespace: namespace, 129 Subsystem: subsystem, 130 Name: "priority_level_request_utilization", 131 Help: "Observations, at the end of every nanosecond, of number of requests (as a fraction of the relevant limit) waiting or in any stage of execution (but only initial stage for WATCHes)", 132 // For executing: the denominator will be seats, so this metric will skew low. 133 // For waiting: total queue capacity is generally quite generous, so this metric will skew low. 134 Buckets: []float64{0, 0.001, 0.003, 0.01, 0.03, 0.1, 0.25, 0.5, 0.75, 1}, 135 StabilityLevel: compbasemetrics.ALPHA, 136 }, 137 LabelNamePhase, priorityLevel, 138 ) 139 // readWriteConcurrencyGaugeVec creates ratioed gauges of requests/limit broken down by phase and mutating vs readonly 140 readWriteConcurrencyGaugeVec = NewTimingRatioHistogramVec( 141 &compbasemetrics.TimingHistogramOpts{ 142 Namespace: namespace, 143 Subsystem: subsystem, 144 Name: "read_vs_write_current_requests", 145 Help: "Observations, at the end of every nanosecond, of the number of requests (as a fraction of the relevant limit) waiting or in regular stage of execution", 146 // This metric will skew low for the same reason as the priority level metrics 147 // and also because APF has a combined limit for mutating and readonly. 148 Buckets: []float64{0, 0.001, 0.01, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 1}, 149 StabilityLevel: compbasemetrics.ALPHA, 150 }, 151 LabelNamePhase, requestKind, 152 ) 153 apiserverCurrentR = compbasemetrics.NewGaugeVec( 154 &compbasemetrics.GaugeOpts{ 155 Namespace: namespace, 156 Subsystem: subsystem, 157 Name: "current_r", 158 Help: "R(time of last change)", 159 StabilityLevel: compbasemetrics.ALPHA, 160 }, 161 []string{priorityLevel}, 162 ) 163 apiserverDispatchR = compbasemetrics.NewGaugeVec( 164 &compbasemetrics.GaugeOpts{ 165 Namespace: namespace, 166 Subsystem: subsystem, 167 Name: "dispatch_r", 168 Help: "R(time of last dispatch)", 169 StabilityLevel: compbasemetrics.ALPHA, 170 }, 171 []string{priorityLevel}, 172 ) 173 apiserverLatestS = compbasemetrics.NewGaugeVec( 174 &compbasemetrics.GaugeOpts{ 175 Namespace: namespace, 176 Subsystem: subsystem, 177 Name: "latest_s", 178 Help: "S(most recently dispatched request)", 179 StabilityLevel: compbasemetrics.ALPHA, 180 }, 181 []string{priorityLevel}, 182 ) 183 apiserverNextSBounds = compbasemetrics.NewGaugeVec( 184 &compbasemetrics.GaugeOpts{ 185 Namespace: namespace, 186 Subsystem: subsystem, 187 Name: "next_s_bounds", 188 Help: "min and max, over queues, of S(oldest waiting request in queue)", 189 StabilityLevel: compbasemetrics.ALPHA, 190 }, 191 []string{priorityLevel, "bound"}, 192 ) 193 apiserverNextDiscountedSBounds = compbasemetrics.NewGaugeVec( 194 &compbasemetrics.GaugeOpts{ 195 Namespace: namespace, 196 Subsystem: subsystem, 197 Name: "next_discounted_s_bounds", 198 Help: "min and max, over queues, of S(oldest waiting request in queue) - estimated work in progress", 199 StabilityLevel: compbasemetrics.ALPHA, 200 }, 201 []string{priorityLevel, "bound"}, 202 ) 203 apiserverCurrentInqueueRequests = compbasemetrics.NewGaugeVec( 204 &compbasemetrics.GaugeOpts{ 205 Namespace: namespace, 206 Subsystem: subsystem, 207 Name: "current_inqueue_requests", 208 Help: "Number of requests currently pending in queues of the API Priority and Fairness subsystem", 209 StabilityLevel: compbasemetrics.BETA, 210 }, 211 []string{priorityLevel, flowSchema}, 212 ) 213 apiserverCurrentInqueueSeats = compbasemetrics.NewGaugeVec( 214 &compbasemetrics.GaugeOpts{ 215 Namespace: namespace, 216 Subsystem: subsystem, 217 Name: "current_inqueue_seats", 218 Help: "Number of seats currently pending in queues of the API Priority and Fairness subsystem", 219 StabilityLevel: compbasemetrics.ALPHA, 220 }, 221 []string{priorityLevel, flowSchema}, 222 ) 223 apiserverRequestQueueLength = compbasemetrics.NewHistogramVec( 224 &compbasemetrics.HistogramOpts{ 225 Namespace: namespace, 226 Subsystem: subsystem, 227 Name: "request_queue_length_after_enqueue", 228 Help: "Length of queue in the API Priority and Fairness subsystem, as seen by each request after it is enqueued", 229 Buckets: queueLengthBuckets, 230 StabilityLevel: compbasemetrics.ALPHA, 231 }, 232 []string{priorityLevel, flowSchema}, 233 ) 234 apiserverRequestConcurrencyLimit = compbasemetrics.NewGaugeVec( 235 &compbasemetrics.GaugeOpts{ 236 Namespace: namespace, 237 Subsystem: subsystem, 238 Name: "request_concurrency_limit", 239 Help: "Nominal number of execution seats configured for each priority level", 240 // Remove this metric once all suppported releases have the equal nominal_limit_seats metric 241 DeprecatedVersion: "1.30.0", 242 StabilityLevel: compbasemetrics.ALPHA, 243 }, 244 []string{priorityLevel}, 245 ) 246 apiserverCurrentExecutingRequests = compbasemetrics.NewGaugeVec( 247 &compbasemetrics.GaugeOpts{ 248 Namespace: namespace, 249 Subsystem: subsystem, 250 Name: "current_executing_requests", 251 Help: "Number of requests in initial (for a WATCH) or any (for a non-WATCH) execution stage in the API Priority and Fairness subsystem", 252 StabilityLevel: compbasemetrics.BETA, 253 }, 254 []string{priorityLevel, flowSchema}, 255 ) 256 apiserverCurrentExecutingSeats = compbasemetrics.NewGaugeVec( 257 &compbasemetrics.GaugeOpts{ 258 Namespace: namespace, 259 Subsystem: subsystem, 260 Name: "current_executing_seats", 261 Help: "Concurrency (number of seats) occupied by the currently executing (initial stage for a WATCH, any stage otherwise) requests in the API Priority and Fairness subsystem", 262 StabilityLevel: compbasemetrics.BETA, 263 }, 264 []string{priorityLevel, flowSchema}, 265 ) 266 apiserverRequestConcurrencyInUse = compbasemetrics.NewGaugeVec( 267 &compbasemetrics.GaugeOpts{ 268 Namespace: namespace, 269 Subsystem: subsystem, 270 Name: "request_concurrency_in_use", 271 Help: "Concurrency (number of seats) occupied by the currently executing (initial stage for a WATCH, any stage otherwise) requests in the API Priority and Fairness subsystem", 272 // Remove this metric once all suppported releases have the equal current_executing_seats metric 273 DeprecatedVersion: "1.31.0", 274 StabilityLevel: compbasemetrics.ALPHA, 275 }, 276 []string{priorityLevel, flowSchema}, 277 ) 278 apiserverRequestWaitingSeconds = compbasemetrics.NewHistogramVec( 279 &compbasemetrics.HistogramOpts{ 280 Namespace: namespace, 281 Subsystem: subsystem, 282 Name: "request_wait_duration_seconds", 283 Help: "Length of time a request spent waiting in its queue", 284 Buckets: requestDurationSecondsBuckets, 285 StabilityLevel: compbasemetrics.BETA, 286 }, 287 []string{priorityLevel, flowSchema, "execute"}, 288 ) 289 apiserverRequestExecutionSeconds = compbasemetrics.NewHistogramVec( 290 &compbasemetrics.HistogramOpts{ 291 Namespace: namespace, 292 Subsystem: subsystem, 293 Name: "request_execution_seconds", 294 Help: "Duration of initial stage (for a WATCH) or any (for a non-WATCH) stage of request execution in the API Priority and Fairness subsystem", 295 Buckets: requestDurationSecondsBuckets, 296 StabilityLevel: compbasemetrics.ALPHA, 297 }, 298 []string{priorityLevel, flowSchema, "type"}, 299 ) 300 watchCountSamples = compbasemetrics.NewHistogramVec( 301 &compbasemetrics.HistogramOpts{ 302 Namespace: namespace, 303 Subsystem: subsystem, 304 Name: "watch_count_samples", 305 Help: "count of watchers for mutating requests in API Priority and Fairness", 306 Buckets: []float64{0, 1, 10, 100, 1000, 10000}, 307 StabilityLevel: compbasemetrics.ALPHA, 308 }, 309 []string{priorityLevel, flowSchema}, 310 ) 311 apiserverEpochAdvances = compbasemetrics.NewCounterVec( 312 &compbasemetrics.CounterOpts{ 313 Namespace: namespace, 314 Subsystem: subsystem, 315 Name: "epoch_advance_total", 316 Help: "Number of times the queueset's progress meter jumped backward", 317 StabilityLevel: compbasemetrics.ALPHA, 318 }, 319 []string{priorityLevel, "success"}, 320 ) 321 apiserverWorkEstimatedSeats = compbasemetrics.NewHistogramVec( 322 &compbasemetrics.HistogramOpts{ 323 Namespace: namespace, 324 Subsystem: subsystem, 325 Name: "work_estimated_seats", 326 Help: "Number of estimated seats (maximum of initial and final seats) associated with requests in API Priority and Fairness", 327 // the upper bound comes from the maximum number of seats a request 328 // can occupy which is currently set at 10. 329 Buckets: []float64{1, 2, 4, 10}, 330 StabilityLevel: compbasemetrics.ALPHA, 331 }, 332 []string{priorityLevel, flowSchema}, 333 ) 334 apiserverDispatchWithNoAccommodation = compbasemetrics.NewCounterVec( 335 &compbasemetrics.CounterOpts{ 336 Namespace: namespace, 337 Subsystem: subsystem, 338 Name: "request_dispatch_no_accommodation_total", 339 Help: "Number of times a dispatch attempt resulted in a non accommodation due to lack of available seats", 340 StabilityLevel: compbasemetrics.ALPHA, 341 }, 342 []string{priorityLevel, flowSchema}, 343 ) 344 apiserverNominalConcurrencyLimits = compbasemetrics.NewGaugeVec( 345 &compbasemetrics.GaugeOpts{ 346 Namespace: namespace, 347 Subsystem: subsystem, 348 Name: "nominal_limit_seats", 349 Help: "Nominal number of execution seats configured for each priority level", 350 StabilityLevel: compbasemetrics.BETA, 351 }, 352 []string{priorityLevel}, 353 ) 354 apiserverMinimumConcurrencyLimits = compbasemetrics.NewGaugeVec( 355 &compbasemetrics.GaugeOpts{ 356 Namespace: namespace, 357 Subsystem: subsystem, 358 Name: "lower_limit_seats", 359 Help: "Configured lower bound on number of execution seats available to each priority level", 360 StabilityLevel: compbasemetrics.ALPHA, 361 }, 362 []string{priorityLevel}, 363 ) 364 apiserverMaximumConcurrencyLimits = compbasemetrics.NewGaugeVec( 365 &compbasemetrics.GaugeOpts{ 366 Namespace: namespace, 367 Subsystem: subsystem, 368 Name: "upper_limit_seats", 369 Help: "Configured upper bound on number of execution seats available to each priority level", 370 StabilityLevel: compbasemetrics.ALPHA, 371 }, 372 []string{priorityLevel}, 373 ) 374 ApiserverSeatDemands = NewTimingRatioHistogramVec( 375 &compbasemetrics.TimingHistogramOpts{ 376 Namespace: namespace, 377 Subsystem: subsystem, 378 Name: "demand_seats", 379 Help: "Observations, at the end of every nanosecond, of (the number of seats each priority level could use) / (nominal number of seats for that level)", 380 // Rationale for the bucket boundaries: 381 // For 0--1, evenly spaced and not too many; 382 // For 1--2, roughly powers of sqrt(sqrt(2)); 383 // For 2--6, roughly powers of sqrt(2); 384 // We need coverage over 1, but do not want too many buckets. 385 Buckets: []float64{0.2, 0.4, 0.6, 0.8, 1, 1.2, 1.4, 1.7, 2, 2.8, 4, 6}, 386 StabilityLevel: compbasemetrics.ALPHA, 387 }, 388 priorityLevel, 389 ) 390 apiserverSeatDemandHighWatermarks = compbasemetrics.NewGaugeVec( 391 &compbasemetrics.GaugeOpts{ 392 Namespace: namespace, 393 Subsystem: subsystem, 394 Name: "demand_seats_high_watermark", 395 Help: "High watermark, over last adjustment period, of demand_seats", 396 StabilityLevel: compbasemetrics.ALPHA, 397 }, 398 []string{priorityLevel}, 399 ) 400 apiserverSeatDemandAverages = compbasemetrics.NewGaugeVec( 401 &compbasemetrics.GaugeOpts{ 402 Namespace: namespace, 403 Subsystem: subsystem, 404 Name: "demand_seats_average", 405 Help: "Time-weighted average, over last adjustment period, of demand_seats", 406 StabilityLevel: compbasemetrics.ALPHA, 407 }, 408 []string{priorityLevel}, 409 ) 410 apiserverSeatDemandStandardDeviations = compbasemetrics.NewGaugeVec( 411 &compbasemetrics.GaugeOpts{ 412 Namespace: namespace, 413 Subsystem: subsystem, 414 Name: "demand_seats_stdev", 415 Help: "Time-weighted standard deviation, over last adjustment period, of demand_seats", 416 StabilityLevel: compbasemetrics.ALPHA, 417 }, 418 []string{priorityLevel}, 419 ) 420 apiserverSeatDemandSmootheds = compbasemetrics.NewGaugeVec( 421 &compbasemetrics.GaugeOpts{ 422 Namespace: namespace, 423 Subsystem: subsystem, 424 Name: "demand_seats_smoothed", 425 Help: "Smoothed seat demands", 426 StabilityLevel: compbasemetrics.ALPHA, 427 }, 428 []string{priorityLevel}, 429 ) 430 apiserverSeatDemandTargets = compbasemetrics.NewGaugeVec( 431 &compbasemetrics.GaugeOpts{ 432 Namespace: namespace, 433 Subsystem: subsystem, 434 Name: "target_seats", 435 Help: "Seat allocation targets", 436 StabilityLevel: compbasemetrics.ALPHA, 437 }, 438 []string{priorityLevel}, 439 ) 440 apiserverFairFracs = compbasemetrics.NewGauge( 441 &compbasemetrics.GaugeOpts{ 442 Namespace: namespace, 443 Subsystem: subsystem, 444 Name: "seat_fair_frac", 445 Help: "Fair fraction of server's concurrency to allocate to each priority level that can use it", 446 StabilityLevel: compbasemetrics.ALPHA, 447 }) 448 apiserverCurrentConcurrencyLimits = compbasemetrics.NewGaugeVec( 449 &compbasemetrics.GaugeOpts{ 450 Namespace: namespace, 451 Subsystem: subsystem, 452 Name: "current_limit_seats", 453 Help: "current derived number of execution seats available to each priority level", 454 StabilityLevel: compbasemetrics.ALPHA, 455 }, 456 []string{priorityLevel}, 457 ) 458 459 metrics = Registerables{ 460 apiserverRejectedRequestsTotal, 461 apiserverDispatchedRequestsTotal, 462 apiserverCurrentR, 463 apiserverDispatchR, 464 apiserverLatestS, 465 apiserverNextSBounds, 466 apiserverNextDiscountedSBounds, 467 apiserverCurrentInqueueRequests, 468 apiserverCurrentInqueueSeats, 469 apiserverRequestQueueLength, 470 apiserverRequestConcurrencyLimit, 471 apiserverRequestConcurrencyInUse, 472 apiserverCurrentExecutingSeats, 473 apiserverCurrentExecutingRequests, 474 apiserverRequestWaitingSeconds, 475 apiserverRequestExecutionSeconds, 476 watchCountSamples, 477 apiserverEpochAdvances, 478 apiserverWorkEstimatedSeats, 479 apiserverDispatchWithNoAccommodation, 480 apiserverNominalConcurrencyLimits, 481 apiserverMinimumConcurrencyLimits, 482 apiserverMaximumConcurrencyLimits, 483 apiserverSeatDemandHighWatermarks, 484 apiserverSeatDemandAverages, 485 apiserverSeatDemandStandardDeviations, 486 apiserverSeatDemandSmootheds, 487 apiserverSeatDemandTargets, 488 apiserverFairFracs, 489 apiserverCurrentConcurrencyLimits, 490 }. 491 Append(PriorityLevelExecutionSeatsGaugeVec.metrics()...). 492 Append(PriorityLevelConcurrencyGaugeVec.metrics()...). 493 Append(readWriteConcurrencyGaugeVec.metrics()...). 494 Append(ApiserverSeatDemands.metrics()...) 495 ) 496 497 type indexOnce struct { 498 labelValues []string 499 once sync.Once 500 gauge RatioedGauge 501 } 502 503 func (io *indexOnce) getGauge() RatioedGauge { 504 io.once.Do(func() { 505 io.gauge = readWriteConcurrencyGaugeVec.NewForLabelValuesSafe(0, 1, io.labelValues) 506 }) 507 return io.gauge 508 } 509 510 var waitingReadonly = indexOnce{labelValues: []string{LabelValueWaiting, epmetrics.ReadOnlyKind}} 511 var executingReadonly = indexOnce{labelValues: []string{LabelValueExecuting, epmetrics.ReadOnlyKind}} 512 var waitingMutating = indexOnce{labelValues: []string{LabelValueWaiting, epmetrics.MutatingKind}} 513 var executingMutating = indexOnce{labelValues: []string{LabelValueExecuting, epmetrics.MutatingKind}} 514 515 // GetWaitingReadonlyConcurrency returns the gauge of number of readonly requests waiting / limit on those. 516 var GetWaitingReadonlyConcurrency = waitingReadonly.getGauge 517 518 // GetExecutingReadonlyConcurrency returns the gauge of number of executing readonly requests / limit on those. 519 var GetExecutingReadonlyConcurrency = executingReadonly.getGauge 520 521 // GetWaitingMutatingConcurrency returns the gauge of number of mutating requests waiting / limit on those. 522 var GetWaitingMutatingConcurrency = waitingMutating.getGauge 523 524 // GetExecutingMutatingConcurrency returns the gauge of number of executing mutating requests / limit on those. 525 var GetExecutingMutatingConcurrency = executingMutating.getGauge 526 527 // AddRequestsInQueues adds the given delta to the gauge of the # of requests in the queues of the specified flowSchema and priorityLevel 528 func AddRequestsInQueues(ctx context.Context, priorityLevel, flowSchema string, delta int) { 529 apiserverCurrentInqueueRequests.WithLabelValues(priorityLevel, flowSchema).Add(float64(delta)) 530 } 531 532 // AddSeatsInQueues adds the given delta to the gauge of the # of seats in the queues of the specified flowSchema and priorityLevel 533 func AddSeatsInQueues(ctx context.Context, priorityLevel, flowSchema string, delta int) { 534 apiserverCurrentInqueueSeats.WithLabelValues(priorityLevel, flowSchema).Add(float64(delta)) 535 } 536 537 // AddRequestsExecuting adds the given delta to the gauge of executing requests of the given flowSchema and priorityLevel 538 func AddRequestsExecuting(ctx context.Context, priorityLevel, flowSchema string, delta int) { 539 apiserverCurrentExecutingRequests.WithLabelValues(priorityLevel, flowSchema).Add(float64(delta)) 540 } 541 542 // SetCurrentR sets the current-R (virtualTime) gauge for the given priority level 543 func SetCurrentR(priorityLevel string, r float64) { 544 apiserverCurrentR.WithLabelValues(priorityLevel).Set(r) 545 } 546 547 // SetLatestS sets the latest-S (virtual time of dispatched request) gauge for the given priority level 548 func SetDispatchMetrics(priorityLevel string, r, s, sMin, sMax, discountedSMin, discountedSMax float64) { 549 apiserverDispatchR.WithLabelValues(priorityLevel).Set(r) 550 apiserverLatestS.WithLabelValues(priorityLevel).Set(s) 551 apiserverNextSBounds.WithLabelValues(priorityLevel, "min").Set(sMin) 552 apiserverNextSBounds.WithLabelValues(priorityLevel, "max").Set(sMax) 553 apiserverNextDiscountedSBounds.WithLabelValues(priorityLevel, "min").Set(discountedSMin) 554 apiserverNextDiscountedSBounds.WithLabelValues(priorityLevel, "max").Set(discountedSMax) 555 } 556 557 // AddSeatConcurrencyInUse adds the given delta to the gauge of seats in use by 558 // the currently executing requests of the given flowSchema and priorityLevel 559 func AddSeatConcurrencyInUse(priorityLevel, flowSchema string, delta int) { 560 apiserverCurrentExecutingSeats.WithLabelValues(priorityLevel, flowSchema).Add(float64(delta)) 561 apiserverRequestConcurrencyInUse.WithLabelValues(priorityLevel, flowSchema).Add(float64(delta)) 562 } 563 564 // AddReject increments the # of rejected requests for flow control 565 func AddReject(ctx context.Context, priorityLevel, flowSchema, reason string) { 566 apiserverRejectedRequestsTotal.WithContext(ctx).WithLabelValues(priorityLevel, flowSchema, reason).Add(1) 567 } 568 569 // AddDispatch increments the # of dispatched requests for flow control 570 func AddDispatch(ctx context.Context, priorityLevel, flowSchema string) { 571 apiserverDispatchedRequestsTotal.WithContext(ctx).WithLabelValues(priorityLevel, flowSchema).Add(1) 572 } 573 574 // ObserveQueueLength observes the queue length for flow control 575 func ObserveQueueLength(ctx context.Context, priorityLevel, flowSchema string, length int) { 576 apiserverRequestQueueLength.WithContext(ctx).WithLabelValues(priorityLevel, flowSchema).Observe(float64(length)) 577 } 578 579 // ObserveWaitingDuration observes the queue length for flow control 580 func ObserveWaitingDuration(ctx context.Context, priorityLevel, flowSchema, execute string, waitTime time.Duration) { 581 apiserverRequestWaitingSeconds.WithContext(ctx).WithLabelValues(priorityLevel, flowSchema, execute).Observe(waitTime.Seconds()) 582 } 583 584 // ObserveExecutionDuration observes the execution duration for flow control 585 func ObserveExecutionDuration(ctx context.Context, priorityLevel, flowSchema string, executionTime time.Duration) { 586 reqType := "regular" 587 if requestInfo, ok := apirequest.RequestInfoFrom(ctx); ok && requestInfo.Verb == "watch" { 588 reqType = requestInfo.Verb 589 } 590 apiserverRequestExecutionSeconds.WithContext(ctx).WithLabelValues(priorityLevel, flowSchema, reqType).Observe(executionTime.Seconds()) 591 } 592 593 // ObserveWatchCount notes a sampling of a watch count 594 func ObserveWatchCount(ctx context.Context, priorityLevel, flowSchema string, count int) { 595 watchCountSamples.WithLabelValues(priorityLevel, flowSchema).Observe(float64(count)) 596 } 597 598 // AddEpochAdvance notes an advance of the progress meter baseline for a given priority level 599 func AddEpochAdvance(ctx context.Context, priorityLevel string, success bool) { 600 apiserverEpochAdvances.WithContext(ctx).WithLabelValues(priorityLevel, strconv.FormatBool(success)).Inc() 601 } 602 603 // ObserveWorkEstimatedSeats notes a sampling of estimated seats associated with a request 604 func ObserveWorkEstimatedSeats(priorityLevel, flowSchema string, seats int) { 605 apiserverWorkEstimatedSeats.WithLabelValues(priorityLevel, flowSchema).Observe(float64(seats)) 606 } 607 608 // AddDispatchWithNoAccommodation keeps track of number of times dispatch attempt results 609 // in a non accommodation due to lack of available seats. 610 func AddDispatchWithNoAccommodation(priorityLevel, flowSchema string) { 611 apiserverDispatchWithNoAccommodation.WithLabelValues(priorityLevel, flowSchema).Inc() 612 } 613 614 func SetPriorityLevelConfiguration(priorityLevel string, nominalCL, minCL, maxCL int) { 615 apiserverRequestConcurrencyLimit.WithLabelValues(priorityLevel).Set(float64(nominalCL)) 616 apiserverNominalConcurrencyLimits.WithLabelValues(priorityLevel).Set(float64(nominalCL)) 617 apiserverMinimumConcurrencyLimits.WithLabelValues(priorityLevel).Set(float64(minCL)) 618 apiserverMaximumConcurrencyLimits.WithLabelValues(priorityLevel).Set(float64(maxCL)) 619 } 620 621 func NotePriorityLevelConcurrencyAdjustment(priorityLevel string, seatDemandHWM, seatDemandAvg, seatDemandStdev, seatDemandSmoothed, seatDemandTarget float64, currentCL int) { 622 apiserverSeatDemandHighWatermarks.WithLabelValues(priorityLevel).Set(seatDemandHWM) 623 apiserverSeatDemandAverages.WithLabelValues(priorityLevel).Set(seatDemandAvg) 624 apiserverSeatDemandStandardDeviations.WithLabelValues(priorityLevel).Set(seatDemandStdev) 625 apiserverSeatDemandSmootheds.WithLabelValues(priorityLevel).Set(seatDemandSmoothed) 626 apiserverSeatDemandTargets.WithLabelValues(priorityLevel).Set(seatDemandTarget) 627 apiserverCurrentConcurrencyLimits.WithLabelValues(priorityLevel).Set(float64(currentCL)) 628 } 629 630 func SetFairFrac(fairFrac float64) { 631 apiserverFairFracs.Set(fairFrac) 632 }