github.com/elopio/cli@v6.21.2-0.20160902224010-ea909d1fdb2f+incompatible/cf/api/logs/loggregator_logs_repository.go (about) 1 package logs 2 3 import ( 4 "errors" 5 "time" 6 7 . "code.cloudfoundry.org/cli/cf/i18n" 8 9 "code.cloudfoundry.org/cli/cf/api/authentication" 10 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 11 consumer "github.com/cloudfoundry/loggregator_consumer" 12 "github.com/cloudfoundry/loggregatorlib/logmessage" 13 noaa_errors "github.com/cloudfoundry/noaa/errors" 14 ) 15 16 type LoggregatorLogsRepository struct { 17 consumer consumer.LoggregatorConsumer 18 config coreconfig.Reader 19 tokenRefresher authentication.TokenRefresher 20 messageQueue *LoggregatorMessageQueue 21 BufferTime time.Duration 22 } 23 24 func NewLoggregatorLogsRepository(config coreconfig.Reader, consumer consumer.LoggregatorConsumer, refresher authentication.TokenRefresher) *LoggregatorLogsRepository { 25 return &LoggregatorLogsRepository{ 26 config: config, 27 consumer: consumer, 28 tokenRefresher: refresher, 29 messageQueue: NewLoggregatorMessageQueue(), 30 BufferTime: defaultBufferTime, 31 } 32 } 33 34 func (repo *LoggregatorLogsRepository) Close() { 35 _ = repo.consumer.Close() 36 } 37 38 func loggableMessagesFromLoggregatorMessages(messages []*logmessage.LogMessage) []Loggable { 39 loggableMessages := make([]Loggable, len(messages)) 40 41 for i, m := range messages { 42 loggableMessages[i] = NewLoggregatorLogMessage(m) 43 } 44 45 return loggableMessages 46 } 47 48 func (repo *LoggregatorLogsRepository) RecentLogsFor(appGUID string) ([]Loggable, error) { 49 messages, err := repo.consumer.Recent(appGUID, repo.config.AccessToken()) 50 51 switch err.(type) { 52 case nil: // do nothing 53 case *noaa_errors.UnauthorizedError: 54 _, _ = repo.tokenRefresher.RefreshAuthToken() 55 return repo.RecentLogsFor(appGUID) 56 default: 57 return loggableMessagesFromLoggregatorMessages(messages), err 58 } 59 60 consumer.SortRecent(messages) 61 62 return loggableMessagesFromLoggregatorMessages(messages), nil 63 } 64 65 func (repo *LoggregatorLogsRepository) TailLogsFor(appGUID string, onConnect func(), logChan chan<- Loggable, errChan chan<- error) { 66 ticker := time.NewTicker(repo.BufferTime) 67 endpoint := repo.config.LoggregatorEndpoint() 68 if endpoint == "" { 69 errChan <- errors.New(T("Loggregator endpoint missing from config file")) 70 return 71 } 72 73 repo.consumer.SetOnConnectCallback(onConnect) 74 c, err := repo.consumer.Tail(appGUID, repo.config.AccessToken()) 75 76 switch err.(type) { 77 case nil: // do nothing 78 case *noaa_errors.UnauthorizedError: 79 _, _ = repo.tokenRefresher.RefreshAuthToken() 80 c, err = repo.consumer.Tail(appGUID, repo.config.AccessToken()) 81 default: 82 errChan <- err 83 return 84 } 85 86 if err != nil { 87 errChan <- err 88 return 89 } 90 91 go func() { 92 for range ticker.C { 93 repo.flushMessages(logChan) 94 } 95 }() 96 97 go func() { 98 for msg := range c { 99 repo.messageQueue.PushMessage(msg) 100 } 101 102 repo.flushMessages(logChan) 103 close(logChan) 104 }() 105 } 106 107 func (repo *LoggregatorLogsRepository) flushMessages(c chan<- Loggable) { 108 repo.messageQueue.EnumerateAndClear(func(m *logmessage.LogMessage) { 109 c <- NewLoggregatorLogMessage(m) 110 }) 111 }