github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/actor/sharedaction/logging.go (about)

     1  package sharedaction
     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 (log LogMessage) Message() string {
    30  	return log.message
    31  }
    32  
    33  func (log LogMessage) Type() string {
    34  	return log.messageType
    35  }
    36  
    37  func (log LogMessage) Staging() bool {
    38  	return log.sourceType == StagingLog
    39  }
    40  
    41  func (log LogMessage) Timestamp() time.Time {
    42  	return log.timestamp
    43  }
    44  
    45  func (log LogMessage) SourceType() string {
    46  	return log.sourceType
    47  }
    48  
    49  func (log LogMessage) SourceInstance() string {
    50  	return log.sourceInstance
    51  }
    52  
    53  func NewLogMessage(message string, messageType string, timestamp time.Time, sourceType string, sourceInstance string) *LogMessage {
    54  	return &LogMessage{
    55  		message:        message,
    56  		messageType:    messageType,
    57  		timestamp:      timestamp,
    58  		sourceType:     sourceType,
    59  		sourceInstance: sourceInstance,
    60  	}
    61  }
    62  
    63  type LogMessages []*LogMessage
    64  
    65  func (lm LogMessages) Len() int { return len(lm) }
    66  
    67  func (lm LogMessages) Less(i, j int) bool {
    68  	return lm[i].timestamp.Before(lm[j].timestamp)
    69  }
    70  
    71  func (lm LogMessages) Swap(i, j int) {
    72  	lm[i], lm[j] = lm[j], lm[i]
    73  }
    74  
    75  type channelWriter struct {
    76  	errChannel chan error
    77  }
    78  
    79  func (c channelWriter) Write(bytes []byte) (n int, err error) {
    80  	c.errChannel <- errors.New(strings.Trim(string(bytes), "\n"))
    81  
    82  	return len(bytes), nil
    83  }
    84  
    85  func GetStreamingLogs(appGUID string, client LogCacheClient) (<-chan LogMessage, <-chan error, context.CancelFunc) {
    86  	logrus.Info("Start Tailing Logs")
    87  
    88  	outgoingLogStream := make(chan LogMessage, 1000)
    89  	outgoingErrStream := make(chan error, 1000)
    90  	ctx, cancelFunc := context.WithCancel(context.Background())
    91  	go func() {
    92  		defer close(outgoingLogStream)
    93  		defer close(outgoingErrStream)
    94  
    95  		logcache.Walk(
    96  			ctx,
    97  			appGUID,
    98  			logcache.Visitor(func(envelopes []*loggregator_v2.Envelope) bool {
    99  				logMessages := convertEnvelopesToLogMessages(envelopes)
   100  				for _, logMessage := range logMessages {
   101  					select {
   102  					case <-ctx.Done():
   103  						return false
   104  					default:
   105  						outgoingLogStream <- *logMessage
   106  					}
   107  				}
   108  
   109  				return true
   110  			}),
   111  			client.Read,
   112  			logcache.WithWalkStartTime(time.Now().Add(-5*time.Second)),
   113  			logcache.WithWalkEnvelopeTypes(logcache_v1.EnvelopeType_LOG),
   114  			logcache.WithWalkBackoff(logcache.NewAlwaysRetryBackoff(250*time.Millisecond)),
   115  			logcache.WithWalkLogger(log.New(channelWriter{
   116  				errChannel: outgoingErrStream,
   117  			}, "", 0)),
   118  		)
   119  	}()
   120  
   121  	return outgoingLogStream, outgoingErrStream, cancelFunc
   122  }
   123  
   124  func GetRecentLogs(appGUID string, client LogCacheClient) ([]LogMessage, error) {
   125  	envelopes, err := client.Read(
   126  		context.Background(),
   127  		appGUID,
   128  		time.Time{},
   129  		logcache.WithEnvelopeTypes(logcache_v1.EnvelopeType_LOG),
   130  		logcache.WithLimit(RecentLogsLines),
   131  		logcache.WithDescending(),
   132  	)
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  
   137  	logMessages := convertEnvelopesToLogMessages(envelopes)
   138  	var reorderedLogMessages []LogMessage
   139  	for i := len(logMessages) - 1; i >= 0; i-- {
   140  		reorderedLogMessages = append(reorderedLogMessages, *logMessages[i])
   141  	}
   142  
   143  	return reorderedLogMessages, nil
   144  }
   145  
   146  func convertEnvelopesToLogMessages(envelopes []*loggregator_v2.Envelope) []*LogMessage {
   147  	var logMessages []*LogMessage
   148  	for _, envelope := range envelopes {
   149  		logEnvelope, ok := envelope.GetMessage().(*loggregator_v2.Envelope_Log)
   150  		if !ok {
   151  			continue
   152  		}
   153  		log := logEnvelope.Log
   154  
   155  		logMessages = append(logMessages, NewLogMessage(
   156  			string(log.Payload),
   157  			loggregator_v2.Log_Type_name[int32(log.Type)],
   158  			time.Unix(0, envelope.GetTimestamp()),
   159  			envelope.GetTags()["source_type"],
   160  			envelope.GetInstanceId(),
   161  		))
   162  	}
   163  	return logMessages
   164  }