Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[corechecks/containerlifecycle] Add Pod finished timestamp to containerlifecycle pod events #16153

Merged
merged 6 commits into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ require (
code.cloudfoundry.org/garden v0.0.0-20210208153517-580cadd489d2
code.cloudfoundry.org/lager v2.0.0+incompatible
github.com/CycloneDX/cyclonedx-go v0.7.0
github.com/DataDog/agent-payload/v5 v5.0.77
github.com/DataDog/agent-payload/v5 v5.0.78
github.com/DataDog/appsec-internal-go v0.0.0-20230215162203-5149228be86a
github.com/DataDog/datadog-agent/pkg/obfuscate v0.44.0-rc.4
github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.44.0-rc.4
Expand Down
4 changes: 2 additions & 2 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions pkg/collector/corechecks/containerlifecycle/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type event interface {
withSource(string)
withContainerExitCode(*int32)
withContainerExitTimestamp(*int64)
withPodExitTimestamp(*int64)
toPayloadModel() (*model.EventsPayload, error)
toEventModel() (*model.Event, error)
}
Expand All @@ -31,6 +32,7 @@ type eventTransformer struct {
source string
contExitCode *int32
contExitTS *int64
podExitTS *int64
}

func newEvent() event {
Expand Down Expand Up @@ -61,6 +63,10 @@ func (e *eventTransformer) withContainerExitTimestamp(exitTS *int64) {
e.contExitTS = exitTS
}

func (e *eventTransformer) withPodExitTimestamp(exitTS *int64) {
e.podExitTS = exitTS
}

func (e *eventTransformer) toPayloadModel() (*model.EventsPayload, error) {
payload := &model.EventsPayload{Version: types.PayloadV1}
kind, err := e.kind()
Expand Down Expand Up @@ -112,6 +118,10 @@ func (e *eventTransformer) toEventModel() (*model.Event, error) {
Source: e.source,
}

if e.podExitTS != nil {
pod.ExitTimestamp = e.podExitTS
}

event.TypedEvent = &model.Event_Pod{Pod: pod}
default:
return nil, fmt.Errorf("unknown kind %q", e.objectKind)
Expand Down
15 changes: 13 additions & 2 deletions pkg/collector/corechecks/containerlifecycle/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,13 @@ func (p *processor) processEvents(evBundle workloadmeta.EventBundle) {
log.Debugf("Couldn't process container %q: %v", container.ID, err)
}
case workloadmeta.KindKubernetesPod:
err := p.processPod(event.Entity)
pod, ok := event.Entity.(*workloadmeta.KubernetesPod)
if !ok {
log.Debugf("Expected workloadmeta.KubernetesPod got %T, skipping", event.Entity)
continue
}

err := p.processPod(pod)
if err != nil {
log.Debugf("Couldn't process pod %q: %v", event.Entity.GetID().ID, err)
}
Expand Down Expand Up @@ -99,13 +105,18 @@ func (p *processor) processContainer(container *workloadmeta.Container, sources
}

// processPod enqueue pod events
func (p *processor) processPod(pod workloadmeta.Entity) error {
func (p *processor) processPod(pod *workloadmeta.KubernetesPod) error {
event := newEvent()
event.withObjectKind(types.ObjectKindPod)
event.withEventType(types.EventNameDelete)
event.withObjectID(pod.GetID().ID)
event.withSource(string(workloadmeta.SourceNodeOrchestrator))

if !pod.FinishedAt.IsZero() {
ts := pod.FinishedAt.Unix()
event.withPodExitTimestamp(&ts)
}

return p.podsQueue.add(event)
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/workloadmeta/collectors/internal/kubelet/kubelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ func extractEnvFromSpec(envSpec []kubelet.EnvVar) map[string]string {

func (c *collector) parseExpires(expiredIDs []string) []workloadmeta.CollectorEvent {
events := make([]workloadmeta.CollectorEvent, 0, len(expiredIDs))
podTerminatedTime := time.Now()

for _, expiredID := range expiredIDs {
prefix, id := containers.SplitEntityName(expiredID)
Expand All @@ -310,6 +311,7 @@ func (c *collector) parseExpires(expiredIDs []string) []workloadmeta.CollectorEv
Kind: workloadmeta.KindKubernetesPod,
ID: id,
},
FinishedAt: podTerminatedTime,
}
} else {
entity = &workloadmeta.Container{
Expand Down
4 changes: 4 additions & 0 deletions pkg/workloadmeta/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ type KubernetesPod struct {
QOSClass string
KubeServices []string
NamespaceLabels map[string]string
FinishedAt time.Time
}

// GetID implements Entity#GetID.
Expand Down Expand Up @@ -531,6 +532,9 @@ func (p KubernetesPod) String(verbose bool) string {
_, _ = fmt.Fprintln(&sb, "PVCs:", sliceToString(p.PersistentVolumeClaimNames))
_, _ = fmt.Fprintln(&sb, "Kube Services:", sliceToString(p.KubeServices))
_, _ = fmt.Fprintln(&sb, "Namespace Labels:", mapToString(p.NamespaceLabels))
if !p.FinishedAt.IsZero() {
_, _ = fmt.Fprintln(&sb, "Finished At:", p.FinishedAt)
}
}

return sb.String()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Each section from every release note are combined when the
# CHANGELOG.rst is rendered. So the text needs to be worded so that
# it does not depend on any information only available in another
# section. This may mean repeating some details, but each section
# must be readable independently of the other.
#
# Each section note must be formatted as reStructuredText.
---
enhancements:
- |
Add Pod exit timestamp to container-lifecycle check.