github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/actor/v2action/logging.go (about) 1 package v2action 2 3 import ( 4 "time" 5 6 "github.com/cloudfoundry/noaa" 7 noaaErrors "github.com/cloudfoundry/noaa/errors" 8 "github.com/cloudfoundry/sonde-go/events" 9 ) 10 11 const StagingLog = "STG" 12 13 type NOAATimeoutError struct{} 14 15 func (NOAATimeoutError) Error() string { 16 return "Timeout trying to connect to NOAA" 17 } 18 19 type LogMessage struct { 20 message string 21 messageType events.LogMessage_MessageType 22 timestamp time.Time 23 sourceType string 24 sourceInstance string 25 } 26 27 func (log LogMessage) Message() string { 28 return log.message 29 } 30 31 func (log LogMessage) Type() string { 32 if log.messageType == events.LogMessage_OUT { 33 return "OUT" 34 } 35 return "ERR" 36 } 37 38 func (log LogMessage) Staging() bool { 39 return log.sourceType == StagingLog 40 } 41 42 func (log LogMessage) Timestamp() time.Time { 43 return log.timestamp 44 } 45 46 func (log LogMessage) SourceType() string { 47 return log.sourceType 48 } 49 50 func (log LogMessage) SourceInstance() string { 51 return log.sourceInstance 52 } 53 54 func NewLogMessage(message string, messageType int, timestamp time.Time, sourceType string, sourceInstance string) *LogMessage { 55 return &LogMessage{ 56 message: message, 57 messageType: events.LogMessage_MessageType(messageType), 58 timestamp: timestamp, 59 sourceType: sourceType, 60 sourceInstance: sourceInstance, 61 } 62 } 63 64 func (Actor) GetStreamingLogs(appGUID string, client NOAAClient, config Config) (<-chan *LogMessage, <-chan error) { 65 // Do not pass in token because client should have a TokenRefresher set 66 eventStream, errStream := client.TailingLogs(appGUID, "") 67 68 messages := make(chan *LogMessage) 69 errs := make(chan error) 70 71 go func() { 72 defer close(messages) 73 defer close(errs) 74 75 dance: 76 for { 77 select { 78 case event, ok := <-eventStream: 79 if !ok { 80 break dance 81 } 82 83 messages <- &LogMessage{ 84 message: string(event.GetMessage()), 85 messageType: event.GetMessageType(), 86 timestamp: time.Unix(0, event.GetTimestamp()), 87 sourceInstance: event.GetSourceInstance(), 88 sourceType: event.GetSourceType(), 89 } 90 case err, ok := <-errStream: 91 if !ok { 92 break dance 93 } 94 95 if _, ok := err.(noaaErrors.RetryError); ok { 96 break 97 } 98 99 if err != nil { 100 errs <- err 101 } 102 } 103 } 104 }() 105 106 return messages, errs 107 } 108 109 func (actor Actor) GetRecentLogsForApplicationByNameAndSpace(appName string, spaceGUID string, client NOAAClient, config Config) ([]LogMessage, Warnings, error) { 110 app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) 111 if err != nil { 112 return nil, allWarnings, err 113 } 114 115 noaaMessages, err := client.RecentLogs(app.GUID, "") 116 if err != nil { 117 return nil, allWarnings, err 118 } 119 120 noaaMessages = noaa.SortRecent(noaaMessages) 121 122 var logMessages []LogMessage 123 124 for _, message := range noaaMessages { 125 logMessages = append(logMessages, LogMessage{ 126 message: string(message.GetMessage()), 127 messageType: message.GetMessageType(), 128 timestamp: time.Unix(0, message.GetTimestamp()), 129 sourceType: message.GetSourceType(), 130 sourceInstance: message.GetSourceInstance(), 131 }) 132 } 133 134 return logMessages, allWarnings, nil 135 } 136 137 func (actor Actor) GetStreamingLogsForApplicationByNameAndSpace(appName string, spaceGUID string, client NOAAClient, config Config) (<-chan *LogMessage, <-chan error, Warnings, error) { 138 app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) 139 if err != nil { 140 return nil, nil, allWarnings, err 141 } 142 143 messages, logErrs := actor.GetStreamingLogs(app.GUID, client, config) 144 145 return messages, logErrs, allWarnings, err 146 }