Skip to content

Commit

Permalink
libpod/events: Update event time format and add timeNano
Browse files Browse the repository at this point in the history
- Use unix timestamp for event time
- Add a timeNano field for event time in nanoseconds

Fixes: #14993

Signed-off-by: Chee Hau Lim <[email protected]>
  • Loading branch information
ch33hau committed May 15, 2023
1 parent 189b09d commit ec0668a
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 41 deletions.
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()
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

0 comments on commit ec0668a

Please sign in to comment.