mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-10-29 08:21:46 +00:00
It seems that bumping the version of golang and golangci-lint new format changes are required. Signed-off-by: Fabiano Fidêncio <fabiano.fidencio@intel.com>
203 lines
4.8 KiB
Go
203 lines
4.8 KiB
Go
//
|
|
// Copyright (c) 2017-2018 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// TimeDelta is a time duration type used to record the difference between two
|
|
// timestamps.
|
|
type TimeDelta time.Duration
|
|
|
|
// NewTimeDelta create a new TimeDelta from the specified duration.
|
|
func NewTimeDelta(d time.Duration) TimeDelta {
|
|
return TimeDelta(d)
|
|
}
|
|
|
|
// String implements the Stringer interface to avoid the "clever" default for
|
|
// time.Duration which converts the value into a human-readable format (which
|
|
// varies on the value). We just want a fixed nanosecond format.
|
|
func (t TimeDelta) String() string {
|
|
return fmt.Sprintf("%d", t)
|
|
}
|
|
|
|
// MapSS is a hack for the xml package which is unable to marshal map types
|
|
// without help.
|
|
//
|
|
// See MapSS.MarshalXML()
|
|
type MapSS map[string]string
|
|
|
|
// Version of LogEntry contents (in semver.org format).
|
|
// XXX: Update whenever LogEntry changes!
|
|
const logEntryFormatVersion = "0.0.2"
|
|
|
|
// LogEntry is the main type used by the tool. It encapsulates a number of
|
|
// fields that all system components are expected to set, but also includes
|
|
// additional fields generated by this program.
|
|
//
|
|
// Notes:
|
|
//
|
|
// - An anonymous field is not used to distinguish between the two
|
|
// categories of fields because that extra layer becomes visible when the
|
|
// struct is converted to various formats (specifically CSV, text and YAML).
|
|
//
|
|
// - XXX: If you change this struct, update logEntryFormatVersion!
|
|
type LogEntry struct {
|
|
// Used to store additional (non-standard) fields
|
|
Data MapSS
|
|
|
|
Time time.Time
|
|
|
|
// Name of the file this entry belongs to
|
|
Filename string
|
|
|
|
Level string
|
|
Msg string
|
|
|
|
// System component type and name that generated the log entry
|
|
Source string
|
|
Name string
|
|
|
|
// Container ID. This is set for most, but not all log records.
|
|
//
|
|
// Excluded log records include:
|
|
//
|
|
// - runtime log entries where the specified CLI command does not
|
|
// operate on a container (or a single container).
|
|
//
|
|
// - proxy log entries which contain kernel boot output from the
|
|
// guest.
|
|
//
|
|
// - early startup agent log entries.
|
|
Container string
|
|
|
|
// Sandbox ID. This is set for most, but not all log records.
|
|
//
|
|
// Excluded log records include:
|
|
//
|
|
// - runtime log entries where the specified CLI command does not
|
|
// operate on a container (or a single container).
|
|
Sandbox string
|
|
|
|
// Line number in Filename this entry refers to
|
|
Line uint64
|
|
|
|
// Log entry number (1-indexed)
|
|
Count uint64
|
|
|
|
// difference between this record and the previous one
|
|
TimeDelta TimeDelta
|
|
|
|
Pid int
|
|
}
|
|
|
|
// Fields lists the names of the fields in a LogEntry.
|
|
func (le LogEntry) Fields() []string {
|
|
var fields []string
|
|
|
|
v := reflect.ValueOf(le)
|
|
|
|
for i := 0; i < v.NumField(); i++ {
|
|
field := v.Type().Field(i).Name
|
|
fields = append(fields, field)
|
|
}
|
|
|
|
return fields
|
|
}
|
|
|
|
// Check runs basic checks on the LogEntry to ensure it is valid.
|
|
func (le LogEntry) Check(ignoreMissingFields bool) error {
|
|
if le.Filename == "" {
|
|
return fmt.Errorf("missing filename: %+v", le)
|
|
}
|
|
|
|
if le.Filename != stdinFile {
|
|
if !strings.HasPrefix(le.Filename, "/") {
|
|
return fmt.Errorf("filename not absolute: %+v", le)
|
|
}
|
|
}
|
|
|
|
if le.Line == 0 {
|
|
return fmt.Errorf("missing line number: %+v", le)
|
|
}
|
|
|
|
if le.Time == (time.Time{}) {
|
|
return fmt.Errorf("missing timestamp: %+v", le)
|
|
}
|
|
|
|
if !ignoreMissingFields {
|
|
if le.Pid == 0 {
|
|
return fmt.Errorf("missing pid: %+v", le)
|
|
}
|
|
|
|
if le.Level == "" {
|
|
return fmt.Errorf("missing log level: %+v", le)
|
|
}
|
|
|
|
if le.Source == "" {
|
|
return fmt.Errorf("missing component source: %+v", le)
|
|
}
|
|
|
|
if le.Name == "" {
|
|
return fmt.Errorf("missing component name: %+v", le)
|
|
}
|
|
}
|
|
|
|
if le.Pid < 0 {
|
|
return fmt.Errorf("invalid pid: %+v", le)
|
|
}
|
|
|
|
// Note: le.Container and le.Sandbox cannot be checked since they are not
|
|
// present in all entries.
|
|
|
|
m := map[string]string{
|
|
"Level": le.Level,
|
|
"Source": le.Source,
|
|
"Name": le.Name,
|
|
}
|
|
|
|
for k, v := range m {
|
|
fields := strings.Fields(v)
|
|
if len(fields) > 1 {
|
|
return fmt.Errorf("field %q cannot be multi-word: %+v", k, le)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LogEntries is a type that encapsulates a list of LogEntry elements.
|
|
// Strictly, this type could refer to the slice itself. However, some
|
|
// formatting packages (such as those for XML and TOML) require that the
|
|
// object to encode is a struct - not an array slice.
|
|
type LogEntries struct {
|
|
FormatVersion string
|
|
Entries []LogEntry
|
|
}
|
|
|
|
// Len is required by sort.Sort.
|
|
func (e LogEntries) Len() int {
|
|
return len(e.Entries)
|
|
}
|
|
|
|
// Swap is required by sort.Sort
|
|
func (e LogEntries) Swap(i, j int) {
|
|
entries := e.Entries
|
|
entries[i], entries[j] = entries[j], entries[i]
|
|
}
|
|
|
|
// Less is required by sort.Sort. Allows time-based sorting.
|
|
func (e LogEntries) Less(i, j int) bool {
|
|
entries := e.Entries
|
|
|
|
return entries[i].Time.Before(entries[j].Time)
|
|
}
|