github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/libpod/events/logfile.go (about) 1 package events 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 8 "github.com/containers/storage" 9 "github.com/pkg/errors" 10 ) 11 12 // EventLogFile is the structure for event writing to a logfile. It contains the eventer 13 // options and the event itself. Methods for reading and writing are also defined from it. 14 type EventLogFile struct { 15 options EventerOptions 16 } 17 18 // Writes to the log file 19 func (e EventLogFile) Write(ee Event) error { 20 // We need to lock events file 21 lock, err := storage.GetLockfile(e.options.LogFilePath + ".lock") 22 if err != nil { 23 return err 24 } 25 lock.Lock() 26 defer lock.Unlock() 27 f, err := os.OpenFile(e.options.LogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0700) 28 if err != nil { 29 return err 30 } 31 defer f.Close() 32 eventJSONString, err := ee.ToJSONString() 33 if err != nil { 34 return err 35 } 36 if _, err := f.WriteString(fmt.Sprintf("%s\n", eventJSONString)); err != nil { 37 return err 38 } 39 return nil 40 41 } 42 43 // Reads from the log file 44 func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error { 45 defer close(options.EventChannel) 46 eventOptions, err := generateEventOptions(options.Filters, options.Since, options.Until) 47 if err != nil { 48 return errors.Wrapf(err, "unable to generate event options") 49 } 50 t, err := e.getTail(options) 51 if err != nil { 52 return err 53 } 54 funcDone := make(chan bool) 55 copy := true 56 go func() { 57 select { 58 case <-funcDone: 59 // Do nothing 60 case <-ctx.Done(): 61 copy = false 62 t.Kill(errors.New("hangup by client")) 63 } 64 }() 65 for line := range t.Lines { 66 select { 67 case <-ctx.Done(): 68 // the consumer has cancelled 69 return nil 70 default: 71 // fallthrough 72 } 73 74 event, err := newEventFromJSONString(line.Text) 75 if err != nil { 76 return err 77 } 78 switch event.Type { 79 case Image, Volume, Pod, System, Container, Network: 80 // no-op 81 default: 82 return errors.Errorf("event type %s is not valid in %s", event.Type.String(), e.options.LogFilePath) 83 } 84 include := true 85 for _, filter := range eventOptions { 86 include = include && filter(event) 87 } 88 if include && copy { 89 options.EventChannel <- event 90 } 91 } 92 funcDone <- true 93 return nil 94 } 95 96 // String returns a string representation of the logger 97 func (e EventLogFile) String() string { 98 return LogFile.String() 99 }