github.com/franciscocpg/up@v0.1.10/platform/lambda/logs/log.go (about) 1 package logs 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/apex/log" 8 "github.com/aws/aws-sdk-go/aws/awserr" 9 "github.com/aws/aws-sdk-go/service/cloudwatchlogs" 10 ) 11 12 // Log implements log fetching and polling for CloudWatchLogs, 13 // and represents a single group. 14 type Log struct { 15 Config 16 GroupName string 17 Log log.Interface 18 err error 19 } 20 21 // Start consuming logs. 22 func (l *Log) Start() <-chan *Event { 23 ch := make(chan *Event) 24 go l.start(ch) 25 return ch 26 } 27 28 // start consuming and exit after pagination if Follow is not enabled. 29 func (l *Log) start(ch chan<- *Event) { 30 defer close(ch) 31 32 l.Log.Debug("enter") 33 defer l.Log.Debug("exit") 34 35 var start = l.StartTime.UnixNano() / int64(time.Millisecond) 36 var nextToken *string 37 var err error 38 39 for { 40 l.Log.WithField("start", start).Debug("request") 41 nextToken, start, err = l.fetch(nextToken, start, ch) 42 43 if err != nil { 44 l.err = fmt.Errorf("log %q: %s", l.GroupName, err) 45 break 46 } 47 48 if nextToken == nil && l.Follow { 49 time.Sleep(l.PollInterval) 50 l.Log.WithField("start", start).Debug("poll") 51 continue 52 } 53 54 if nextToken == nil { 55 break 56 } 57 } 58 } 59 60 // fetch logs relative to the given token and start time. We ignore when the log group is not found. 61 func (l *Log) fetch(nextToken *string, start int64, ch chan<- *Event) (*string, int64, error) { 62 res, err := l.Service.FilterLogEvents(&cloudwatchlogs.FilterLogEventsInput{ 63 LogGroupName: &l.GroupName, 64 FilterPattern: &l.FilterPattern, 65 StartTime: &start, 66 NextToken: nextToken, 67 }) 68 69 if e, ok := err.(awserr.Error); ok { 70 if e.Code() == "ResourceNotFoundException" { 71 l.Log.Debug("not found") 72 return nil, 0, nil 73 } 74 } 75 76 if err != nil { 77 return nil, 0, err 78 } 79 80 for _, event := range res.Events { 81 start = *event.Timestamp + 1 82 ch <- &Event{ 83 GroupName: l.GroupName, 84 Message: *event.Message, 85 } 86 } 87 88 return res.NextToken, start, nil 89 } 90 91 // Err returns the first error, if any, during processing. 92 func (l *Log) Err() error { 93 return l.err 94 }