github.com/mweagle/Sparta@v1.15.0/aws/cloudwatch/logs/util.go (about)

     1  package cloudwatchlogs
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/aws/aws-sdk-go/aws"
     7  	"github.com/aws/aws-sdk-go/aws/session"
     8  	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
     9  	"github.com/sirupsen/logrus"
    10  )
    11  
    12  func tailParams(logGroupName string, filter string, lastEvent int64) *cloudwatchlogs.FilterLogEventsInput {
    13  	params := &cloudwatchlogs.FilterLogEventsInput{
    14  		LogGroupName: aws.String(logGroupName),
    15  	}
    16  	if filter != "" {
    17  		params.FilterPattern = aws.String(filter)
    18  	}
    19  	if lastEvent != 0 {
    20  		params.StartTime = aws.Int64(lastEvent)
    21  	}
    22  	return params
    23  }
    24  
    25  // TailWithContext is a utility function that support tailing the given log stream
    26  // name using the optional filter. It returns a channel for log messages
    27  func TailWithContext(reqContext aws.Context,
    28  	closeChan chan bool,
    29  	awsSession *session.Session,
    30  	logGroupName string,
    31  	filter string,
    32  	logger *logrus.Logger) <-chan *cloudwatchlogs.FilteredLogEvent {
    33  
    34  	// Milliseconds...
    35  	lastSeenTimestamp := time.Now().Add(0).Unix() * 1000
    36  	logger.WithField("TS", lastSeenTimestamp).Debug("Started polling")
    37  	outputChannel := make(chan *cloudwatchlogs.FilteredLogEvent)
    38  	tailHandler := func(res *cloudwatchlogs.FilterLogEventsOutput, lastPage bool) bool {
    39  		maxTime := int64(0)
    40  		for _, eachEvent := range res.Events {
    41  			if maxTime < *eachEvent.Timestamp {
    42  				maxTime = *eachEvent.Timestamp
    43  			}
    44  			logger.WithField("ID", *eachEvent.EventId).Debug("Event")
    45  			outputChannel <- eachEvent
    46  		}
    47  		if maxTime != 0 {
    48  			lastSeenTimestamp = maxTime + 1
    49  		}
    50  		return !lastPage
    51  	}
    52  
    53  	cwlogsSvc := cloudwatchlogs.New(awsSession)
    54  	tickerChan := time.NewTicker(time.Millisecond * 333).C //AWS cloudwatch logs limit is 5tx/sec
    55  	go func() {
    56  		for {
    57  			select {
    58  			case <-closeChan:
    59  				logger.Debug("Exiting polling loop")
    60  				return
    61  			case <-tickerChan:
    62  				logParam := tailParams(logGroupName, filter, lastSeenTimestamp)
    63  				error := cwlogsSvc.FilterLogEventsPagesWithContext(reqContext, logParam, tailHandler)
    64  				if error != nil {
    65  					// Just pump the thing back through the channel...
    66  					errorEvent := &cloudwatchlogs.FilteredLogEvent{
    67  						EventId:   aws.String("N/A"),
    68  						Message:   aws.String(error.Error()),
    69  						Timestamp: aws.Int64(time.Now().Unix() * 1000),
    70  					}
    71  					outputChannel <- errorEvent
    72  				}
    73  			}
    74  		}
    75  	}()
    76  	return outputChannel
    77  }