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 }