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

libpod/events: Use unix timestamp for event time, and add a timeNano field for event time in nanoseconds #18549

Closed
Closed
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion cmd/podman/machine/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,10 @@ func eventSockDir() (string, error) {
func newMachineEvent(status events.Status, event events.Event) {
openEventSock.Do(initMachineEvents)

now := time.Now()
event.Time = now.Unix()
event.TimeNano = now.UnixNano()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively use events.new(status).

event.Status = status
event.Time = time.Now()
event.Type = events.Machine

payload, err := json.Marshal(event)
Expand Down
29 changes: 15 additions & 14 deletions docs/source/markdown/podman-events.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,21 @@ In the case where an ID is used, the ID may be in its full or shortened form. T

Format the output to JSON Lines or using the given Go template.

| **Placeholder** | **Description** |
|-----------------------|-----------------------------------------------|
| .Attributes | created_at, _by, labels, and more (map[]) |
| .ContainerExitCode | Exit code (int) |
| .ContainerInspectData | Payload of the container's inspect |
| .HealthStatus | Health Status (string) |
| .ID | Container ID (full 64-bit SHA) |
| .Image | Name of image being run (string) |
| .Name | Container name (string) |
| .Network | Name of network being used (string) |
| .PodID | ID of pod associated with container, if any |
| .Status | Event status (e.g., create, start, died, ...) |
| .Time | Event timestamp (string) |
| .Type | Event type (e.g., image, container, pod, ...) |
| **Placeholder** | **Description** |
|-----------------------|---------------------------------------------------|
| .Attributes | created_at, _by, labels, and more (map[]) |
| .ContainerExitCode | Exit code (int) |
| .ContainerInspectData | Payload of the container's inspect |
| .HealthStatus | Health Status (string) |
| .ID | Container ID (full 64-bit SHA) |
| .Image | Name of image being run (string) |
| .Name | Container name (string) |
| .Network | Name of network being used (string) |
| .PodID | ID of pod associated with container, if any |
| .Status | Event status (e.g., create, start, died, ...) |
| .Time | Event timestamp (int64) |
| .TimeNano | Event timestamp with nanosecond precision (int64) |
| .Type | Event type (e.g., image, container, pod, ...) |

#### **--help**

Expand Down
5 changes: 3 additions & 2 deletions libpod/events/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package events
import (
"context"
"errors"
"time"
)

// EventerType ...
Expand Down Expand Up @@ -36,7 +35,9 @@ type Event struct {
// Status describes the event that occurred
Status Status
// Time the event occurred
Time time.Time
Time int64 `json:"time,omitempty"`
// TimeNano the event occurred in nanoseconds
TimeNano int64 `json:"timeNano,omitempty"`
// Type of event that occurred
Type Type
// Health status of the current container
Expand Down
18 changes: 10 additions & 8 deletions libpod/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ func IsValidEventer(eventer string) bool {
// NewEvent creates an event struct and populates with
// the given status and time.
func NewEvent(status Status) Event {
now := time.Now()
return Event{
Status: status,
Time: time.Now(),
Status: status,
Time: now.Unix(),
TimeNano: now.UnixNano(),
}
}

Expand All @@ -76,7 +78,7 @@ func (e *Event) ToHumanReadable(truncate bool) string {
}
switch e.Type {
case Container, Pod:
humanFormat = fmt.Sprintf("%s %s %s %s (image=%s, name=%s", e.Time, e.Type, e.Status, id, e.Image, e.Name)
humanFormat = fmt.Sprintf("%s %s %s %s (image=%s, name=%s", time.Unix(0, e.TimeNano), e.Type, e.Status, id, e.Image, e.Name)
if e.PodID != "" {
humanFormat += fmt.Sprintf(", pod_id=%s", e.PodID)
}
Expand All @@ -91,17 +93,17 @@ func (e *Event) ToHumanReadable(truncate bool) string {
}
humanFormat += ")"
case Network:
humanFormat = fmt.Sprintf("%s %s %s %s (container=%s, name=%s)", e.Time, e.Type, e.Status, id, id, e.Network)
humanFormat = fmt.Sprintf("%s %s %s %s (container=%s, name=%s)", time.Unix(0, e.TimeNano), e.Type, e.Status, id, id, e.Network)
case Image:
humanFormat = fmt.Sprintf("%s %s %s %s %s", e.Time, e.Type, e.Status, id, e.Name)
humanFormat = fmt.Sprintf("%s %s %s %s %s", time.Unix(0, e.TimeNano), e.Type, e.Status, id, e.Name)
case System:
if e.Name != "" {
humanFormat = fmt.Sprintf("%s %s %s %s", e.Time, e.Type, e.Status, e.Name)
humanFormat = fmt.Sprintf("%s %s %s %s", time.Unix(0, e.TimeNano), e.Type, e.Status, e.Name)
} else {
humanFormat = fmt.Sprintf("%s %s %s", e.Time, e.Type, e.Status)
humanFormat = fmt.Sprintf("%s %s %s", time.Unix(0, e.TimeNano), e.Type, e.Status)
}
case Volume, Machine:
humanFormat = fmt.Sprintf("%s %s %s %s", e.Time, e.Type, e.Status, e.Name)
humanFormat = fmt.Sprintf("%s %s %s %s", time.Unix(0, e.TimeNano), e.Type, e.Status, e.Name)
}
return humanFormat
}
Expand Down
4 changes: 2 additions & 2 deletions libpod/events/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ func generateEventFilter(filter, filterValue string) (func(e *Event) bool, error

func generateEventSinceOption(timeSince time.Time) func(e *Event) bool {
return func(e *Event) bool {
return e.Time.After(timeSince)
return time.Unix(0, e.TimeNano).After(timeSince)
}
}

func generateEventUntilOption(timeUntil time.Time) func(e *Event) bool {
return func(e *Event) bool {
return e.Time.Before(timeUntil)
return time.Unix(0, e.TimeNano).Before(timeUntil)
}
}

Expand Down
5 changes: 3 additions & 2 deletions libpod/events/journal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (e EventJournalD) Write(ee Event) error {
m["SYSLOG_IDENTIFIER"] = "podman"
m["PODMAN_EVENT"] = ee.Status.String()
m["PODMAN_TYPE"] = ee.Type.String()
m["PODMAN_TIME"] = ee.Time.Format(time.RFC3339Nano)
m["PODMAN_TIME"] = time.Unix(0, ee.TimeNano).Format(time.RFC3339Nano)

// Add specialized information based on the podman type
switch ee.Type {
Expand Down Expand Up @@ -180,7 +180,8 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) {
return nil, err
}
newEvent.Type = eventType
newEvent.Time = eventTime
newEvent.Time = eventTime.Unix()
newEvent.TimeNano = eventTime.UnixNano()
newEvent.Status = eventStatus
newEvent.Name = entry.Fields["PODMAN_NAME"]

Expand Down
2 changes: 1 addition & 1 deletion libpod/events/logfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error {
if err != nil {
return err
}
if begin && event.Time.After(readTime) {
if begin && time.Unix(0, event.TimeNano).After(readTime) {
// If the rotation event happened _after_ we
// started reading, we need to ignore/skip
// subsequent event until the end of the
Expand Down
11 changes: 6 additions & 5 deletions libpod/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -738,11 +738,12 @@ func (r *Runtime) libimageEvents() {
for len(eventChannel) > 0 {
libimageEvent := <-eventChannel
e := events.Event{
ID: libimageEvent.ID,
Name: libimageEvent.Name,
Status: toLibpodEventStatus(libimageEvent),
Time: libimageEvent.Time,
Type: events.Image,
ID: libimageEvent.ID,
Name: libimageEvent.Name,
Status: toLibpodEventStatus(libimageEvent),
Time: libimageEvent.Time.Unix(),
TimeNano: libimageEvent.Time.UnixNano(),
Type: events.Image,
}
if err := r.eventer.Write(e); err != nil {
logrus.Errorf("Unable to write image event: %q", err)
Expand Down
8 changes: 4 additions & 4 deletions pkg/domain/entities/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package entities

import (
"strconv"
"time"

libpodEvents "github.com/containers/podman/v4/libpod/events"
dockerEvents "github.com/docker/docker/api/types/events"
Expand Down Expand Up @@ -44,7 +43,8 @@ func ConvertToLibpodEvent(e Event) *libpodEvents.Event {
Image: image,
Name: name,
Status: status,
Time: time.Unix(0, e.TimeNano),
Time: e.Time,
TimeNano: e.TimeNano,
Type: t,
HealthStatus: e.HealthStatus,
Details: libpodEvents.Details{
Expand Down Expand Up @@ -76,8 +76,8 @@ func ConvertToEntitiesEvent(e libpodEvents.Event) *Event {
Attributes: attributes,
},
Scope: "local",
Time: e.Time.Unix(),
TimeNano: e.Time.UnixNano(),
Time: e.Time,
TimeNano: e.TimeNano,
}
return &Event{
message,
Expand Down
23 changes: 21 additions & 2 deletions test/e2e/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"os"
"strconv"
"sync"
"time"

Expand Down Expand Up @@ -120,7 +121,10 @@ var _ = Describe("Podman events", func() {
})

It("podman events format", func() {
_, ec, _ := podmanTest.RunLsContainer("")
start := time.Now()
ctrName := "testCtr"
_, ec, _ := podmanTest.RunLsContainer(ctrName)
end := time.Now()
Expect(ec).To(Equal(0))

test := podmanTest.Podman([]string{"events", "--stream=false", "--format", "json"})
Expand All @@ -134,7 +138,13 @@ var _ = Describe("Podman events", func() {
err := json.Unmarshal([]byte(jsonArr[0]), &event)
Expect(err).ToNot(HaveOccurred())

test = podmanTest.Podman([]string{"events", "--stream=false", "--format", "{{json.}}"})
test = podmanTest.Podman([]string{
"events",
"--stream=false",
"--since", strconv.FormatInt(start.Unix(), 10),
"--filter", fmt.Sprintf("container=%s", ctrName),
"--format", "{{json.}}",
})
test.WaitWithDefaultTimeout()
Expect(test).To(Exit(0))

Expand All @@ -145,6 +155,15 @@ var _ = Describe("Podman events", func() {
err = json.Unmarshal([]byte(jsonArr[0]), &event)
Expect(err).ToNot(HaveOccurred())

Expect(event.Time).To(BeNumerically(">=", start.Unix()))
Expect(event.Time).To(BeNumerically("<=", end.Unix()))
Expect(event.TimeNano).To(BeNumerically(">=", start.UnixNano()))
Expect(event.TimeNano).To(BeNumerically("<=", end.UnixNano()))
Expect(time.Unix(0, event.TimeNano).Unix()).To(BeEquivalentTo(event.Time))

date := time.Unix(0, event.TimeNano).Format("2006-01-02")
Expect(event.ToHumanReadable(false)).To(HavePrefix(date))

test = podmanTest.Podman([]string{"events", "--stream=false", "--filter=type=container", "--format", "ID: {{.ID}}"})
test.WaitWithDefaultTimeout()
Expect(test).To(Exit(0))
Expand Down