github.com/AbhinandanKurakure/podman/v3@v3.4.10/libpod/events/logfile.go (about)

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