diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..a4a8ff5d7 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at smalleni@redhat.com +or rsevilla@redhat.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/pkg/measurements/pod_latency.go b/pkg/measurements/pod_latency.go index 34c7eb9a5..865013bd1 100644 --- a/pkg/measurements/pod_latency.go +++ b/pkg/measurements/pod_latency.go @@ -38,23 +38,28 @@ const ( ) type podMetric struct { - Timestamp time.Time `json:"timestamp"` - scheduled time.Time - SchedulingLatency int `json:"schedulingLatency"` - initialized time.Time - InitializedLatency int `json:"initializedLatency"` - containersReady time.Time - ContainersReadyLatency int `json:"containersReadyLatency"` - podReady time.Time - PodReadyLatency int `json:"podReadyLatency"` - MetricName string `json:"metricName"` - JobName string `json:"jobName"` - JobConfig config.Job `json:"jobConfig"` - UUID string `json:"uuid"` - Namespace string `json:"namespace"` - Name string `json:"podName"` - NodeName string `json:"nodeName"` - Metadata interface{} `json:"metadata,omitempty"` + Timestamp time.Time `json:"timestamp"` + CreationTimestampV2 time.Time `json:"creationTimestampV2"` + scheduled time.Time + SchedulingLatency int `json:"schedulingLatency"` + SchedulingLatencyV2 int `json:"schedulingLatency_v2"` + initialized time.Time + InitializedLatency int `json:"initializedLatency"` + InitializedLatencyV2 int `json:"initializedLatency_v2"` + containersReady time.Time + ContainersReadyLatency int `json:"containersReadyLatency"` + ContainersReadyLatencyV2 int `json:"containersReadyLatency_v2"` + podReady time.Time + PodReadyLatency int `json:"podReadyLatency"` + PodReadyLatencyV2 int `json:"podReadyLatency_v2"` + MetricName string `json:"metricName"` + JobName string `json:"jobName"` + JobConfig config.Job `json:"jobConfig"` + UUID string `json:"uuid"` + Namespace string `json:"namespace"` + Name string `json:"podName"` + NodeName string `json:"nodeName"` + Metadata interface{} `json:"metadata,omitempty"` } type podLatency struct { @@ -76,14 +81,15 @@ func (p *podLatency) handleCreatePod(obj interface{}) { if _, exists := p.metrics[string(pod.UID)]; !exists { if strings.Contains(pod.Namespace, factory.jobConfig.Namespace) { p.metrics[string(pod.UID)] = podMetric{ - Timestamp: now, - Namespace: pod.Namespace, - Name: pod.Name, - MetricName: podLatencyMeasurement, - UUID: globalCfg.UUID, - JobConfig: jobConfig, - JobName: factory.jobConfig.Name, - Metadata: factory.metadata, + Timestamp: now, + CreationTimestampV2: pod.CreationTimestamp.Time.UTC(), + Namespace: pod.Namespace, + Name: pod.Name, + MetricName: podLatencyMeasurement, + UUID: globalCfg.UUID, + JobConfig: jobConfig, + JobName: factory.jobConfig.Name, + Metadata: factory.metadata, } } } @@ -202,25 +208,53 @@ func (p *podLatency) normalizeMetrics() { continue } // latencyTime should be always larger than zero, however, in some cases, it might be a - // negative value due to the precision of timestamp can only get to the level of second, - // the microsecond and nanosecond have been discarded purposely in kubelet, this is - // because apiserver does not support RFC339NANO. + // negative value due to the precision of timestamp can only get to the level of second + // and also the creation timestamp we capture using time.Now().UTC() might even have a + // delay over 1s in some cases. The microsecond and nanosecond have been discarded purposely + // in kubelet, this is because apiserver does not support RFC339NANO. The newly introduced + // v2 latencies are currently under AB testing which blindly trust kubernetes as source of + // truth and will prevent us from those over 1s delays as well as <0 cases. + + creationTimeStampsDiff := int(m.Timestamp.Sub(m.CreationTimestampV2).Milliseconds()) + if creationTimeStampsDiff >= 1000 { + log.Tracef("Difference between V1 and V2 creation timestamps for pod %+v is >=1s and is %+v seconds", m.Name, float64(creationTimeStampsDiff)/1000) + } + m.ContainersReadyLatency = int(m.containersReady.Sub(m.Timestamp).Milliseconds()) + m.ContainersReadyLatencyV2 = int(m.containersReady.Sub(m.CreationTimestampV2).Milliseconds()) if m.ContainersReadyLatency < 0 { + log.Tracef("ContainersReadyLatency for pod %+v falling under negative case. So explicitly setting it to 0", m.Name) m.ContainersReadyLatency = 0 } + log.Tracef("ContainersReadyLatency: %+v for pod %+v", m.ContainersReadyLatency, m.Name) + log.Tracef("ContainersReadyLatencyV2: %+v for pod %+v", m.ContainersReadyLatencyV2, m.Name) + m.SchedulingLatency = int(m.scheduled.Sub(m.Timestamp).Milliseconds()) + m.SchedulingLatencyV2 = int(m.scheduled.Sub(m.CreationTimestampV2).Milliseconds()) if m.SchedulingLatency < 0 { + log.Tracef("SchedulingLatency for pod %+v falling under negative case. So explicitly setting it to 0", m.Name) m.SchedulingLatency = 0 } + log.Tracef("SchedulingLatency: %+v for pod %+v", m.SchedulingLatency, m.Name) + log.Tracef("SchedulingLatencyV2: %+v for pod %+v", m.SchedulingLatencyV2, m.Name) + m.InitializedLatency = int(m.initialized.Sub(m.Timestamp).Milliseconds()) + m.InitializedLatencyV2 = int(m.initialized.Sub(m.CreationTimestampV2).Milliseconds()) if m.InitializedLatency < 0 { + log.Tracef("InitializedLatency for pod %+v falling under negative case. So explicitly setting it to 0", m.Name) m.InitializedLatency = 0 } + log.Tracef("InitializedLatency: %+v for pod %+v", m.InitializedLatency, m.Name) + log.Tracef("InitializedLatencyV2: %+v for pod %+v", m.InitializedLatencyV2, m.Name) + m.PodReadyLatency = int(m.podReady.Sub(m.Timestamp).Milliseconds()) + m.PodReadyLatencyV2 = int(m.podReady.Sub(m.CreationTimestampV2).Milliseconds()) if m.PodReadyLatency < 0 { + log.Tracef("PodReadyLatency for pod %+v falling under negative case. So explicitly setting it to 0", m.Name) m.PodReadyLatency = 0 } + log.Tracef("PodReadyLatency: %+v for pod %+v", m.PodReadyLatency, m.Name) + log.Tracef("PodReadyLatencyV2: %+v for pod %+v", m.PodReadyLatencyV2, m.Name) p.normLatencies = append(p.normLatencies, m) } } @@ -232,9 +266,13 @@ func (p *podLatency) calcQuantiles() { jc.Objects = nil for _, normLatency := range p.normLatencies { quantileMap[v1.PodScheduled] = append(quantileMap[v1.PodScheduled], normLatency.(podMetric).SchedulingLatency) + quantileMap["PodScheduledV2"] = append(quantileMap["PodScheduledV2"], normLatency.(podMetric).SchedulingLatencyV2) quantileMap[v1.ContainersReady] = append(quantileMap[v1.ContainersReady], normLatency.(podMetric).ContainersReadyLatency) + quantileMap["ContainersReadyV2"] = append(quantileMap["ContainersReadyV2"], normLatency.(podMetric).ContainersReadyLatencyV2) quantileMap[v1.PodInitialized] = append(quantileMap[v1.PodInitialized], normLatency.(podMetric).InitializedLatency) + quantileMap["InitializedV2"] = append(quantileMap["InitializedV2"], normLatency.(podMetric).InitializedLatencyV2) quantileMap[v1.PodReady] = append(quantileMap[v1.PodReady], normLatency.(podMetric).PodReadyLatency) + quantileMap["ReadyV2"] = append(quantileMap["ReadyV2"], normLatency.(podMetric).PodReadyLatencyV2) } for quantileName, v := range quantileMap { podQ := metrics.LatencyQuantiles{