/* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package metrics import ( "fmt" "math" "time" e2elog "k8s.io/kubernetes/test/e2e/framework/log" ) const ( // SingleCallTimeout is how long to try single API calls (like 'get' or 'list'). Used to prevent // transient failures from failing tests. // TODO: client should not apply this timeout to Watch calls. Increased from 30s until that is fixed. SingleCallTimeout = 5 * time.Minute ) // VerifyLatencyWithinThreshold verifies whether 50, 90 and 99th percentiles of a latency metric are // within the expected threshold. func VerifyLatencyWithinThreshold(threshold, actual LatencyMetric, metricName string) error { if actual.Perc50 > threshold.Perc50 { return fmt.Errorf("too high %v latency 50th percentile: %v", metricName, actual.Perc50) } if actual.Perc90 > threshold.Perc90 { return fmt.Errorf("too high %v latency 90th percentile: %v", metricName, actual.Perc90) } if actual.Perc99 > threshold.Perc99 { return fmt.Errorf("too high %v latency 99th percentile: %v", metricName, actual.Perc99) } return nil } // PodLatencyData encapsulates pod startup latency information. type PodLatencyData struct { // Name of the pod Name string // Node this pod was running on Node string // Latency information related to pod startuptime Latency time.Duration } // LatencySlice is an array of PodLatencyData which encapsulates pod startup latency information. type LatencySlice []PodLatencyData func (a LatencySlice) Len() int { return len(a) } func (a LatencySlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a LatencySlice) Less(i, j int) bool { return a[i].Latency < a[j].Latency } // ExtractLatencyMetrics returns latency metrics for each percentile(50th, 90th and 99th). func ExtractLatencyMetrics(latencies []PodLatencyData) LatencyMetric { length := len(latencies) perc50 := latencies[int(math.Ceil(float64(length*50)/100))-1].Latency perc90 := latencies[int(math.Ceil(float64(length*90)/100))-1].Latency perc99 := latencies[int(math.Ceil(float64(length*99)/100))-1].Latency perc100 := latencies[length-1].Latency return LatencyMetric{Perc50: perc50, Perc90: perc90, Perc99: perc99, Perc100: perc100} } // PrintLatencies outputs latencies to log with readable format. func PrintLatencies(latencies []PodLatencyData, header string) { metrics := ExtractLatencyMetrics(latencies) e2elog.Logf("10%% %s: %v", header, latencies[(len(latencies)*9)/10:]) e2elog.Logf("perc50: %v, perc90: %v, perc99: %v", metrics.Perc50, metrics.Perc90, metrics.Perc99) }