github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/actor/loggingaction/logging.go (about)

     1  package loggingaction
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"log"
     7  	"strings"
     8  	"time"
     9  
    10  	"code.cloudfoundry.org/go-loggregator/rpc/loggregator_v2"
    11  	logcache "code.cloudfoundry.org/log-cache/pkg/client"
    12  	"code.cloudfoundry.org/log-cache/pkg/rpc/logcache_v1"
    13  	"github.com/sirupsen/logrus"
    14  )
    15  
    16  const (
    17  	StagingLog      = "STG"
    18  	RecentLogsLines = 100
    19  )
    20  
    21  type LogMessage struct {
    22  	Message        string
    23  	MessageType    string
    24  	Timestamp      time.Time
    25  	SourceType     string
    26  	SourceInstance string
    27  }
    28  
    29  func (l LogMessage) Staging() bool {
    30  	return l.SourceType == StagingLog
    31  }
    32  
    33  type channelWriter struct {
    34  	errChannel chan error
    35  }
    36  
    37  func (c channelWriter) Write(bytes []byte) (n int, err error) {
    38  	c.errChannel <- errors.New(strings.Trim(string(bytes), "\n"))
    39  
    40  	return len(bytes), nil
    41  }
    42  
    43  func GetStreamingLogs(appGUID string, client LogCacheClient) (<-chan LogMessage, <-chan error, context.CancelFunc) {
    44  	logrus.Info("Start Tailing Logs")
    45  
    46  	outgoingLogStream := make(chan LogMessage, 1000)
    47  	outgoingErrStream := make(chan error, 1000)
    48  	ctx, cancelFunc := context.WithCancel(context.Background())
    49  	go func() {
    50  		defer close(outgoingLogStream)
    51  		defer close(outgoingErrStream)
    52  
    53  		logcache.Walk(
    54  			ctx,
    55  			appGUID,
    56  			logcache.Visitor(func(envelopes []*loggregator_v2.Envelope) bool {
    57  				logMessages := convertEnvelopesToLogMessages(envelopes)
    58  				for _, logMessage := range logMessages {
    59  					select {
    60  					case <-ctx.Done():
    61  						return false
    62  					default:
    63  						outgoingLogStream <- logMessage
    64  					}
    65  				}
    66  
    67  				return true
    68  			}),
    69  			client.Read,
    70  			logcache.WithWalkStartTime(time.Now().Add(-5*time.Second)),
    71  			logcache.WithWalkEnvelopeTypes(logcache_v1.EnvelopeType_LOG),
    72  			logcache.WithWalkBackoff(logcache.NewAlwaysRetryBackoff(250*time.Millisecond)),
    73  			logcache.WithWalkLogger(log.New(channelWriter{
    74  				errChannel: outgoingErrStream,
    75  			}, "", 0)),
    76  		)
    77  	}()
    78  
    79  	return outgoingLogStream, outgoingErrStream, cancelFunc
    80  }
    81  
    82  func convertEnvelopesToLogMessages(envelopes []*loggregator_v2.Envelope) []LogMessage {
    83  	var logMessages []LogMessage
    84  	for _, envelope := range envelopes {
    85  		logEnvelope, ok := envelope.GetMessage().(*loggregator_v2.Envelope_Log)
    86  		if !ok {
    87  			continue
    88  		}
    89  		log := logEnvelope.Log
    90  
    91  		logMessages = append(logMessages, LogMessage{
    92  			Message:        string(log.Payload),
    93  			MessageType:    loggregator_v2.Log_Type_name[int32(log.Type)],
    94  			Timestamp:      time.Unix(0, envelope.GetTimestamp()),
    95  			SourceType:     envelope.GetTags()["source_type"],
    96  			SourceInstance: envelope.GetInstanceId(),
    97  		})
    98  	}
    99  	return logMessages
   100  }
   101  
   102  func GetRecentLogs(appGUID string, client LogCacheClient) ([]LogMessage, error) {
   103  	envelopes, err := client.Read(
   104  		context.Background(),
   105  		appGUID,
   106  		time.Time{},
   107  		logcache.WithEnvelopeTypes(logcache_v1.EnvelopeType_LOG),
   108  		logcache.WithLimit(RecentLogsLines),
   109  		logcache.WithDescending(),
   110  	)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  
   115  	logMessages := convertEnvelopesToLogMessages(envelopes)
   116  	var reorderedLogMessages []LogMessage
   117  	for i := len(logMessages) - 1; i >= 0; i-- {
   118  		reorderedLogMessages = append(reorderedLogMessages, logMessages[i])
   119  	}
   120  
   121  	return reorderedLogMessages, nil
   122  }