github.com/elopio/cli@v6.21.2-0.20160902224010-ea909d1fdb2f+incompatible/cf/api/logs/noaa_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 12 "github.com/cloudfoundry/noaa" 13 noaa_errors "github.com/cloudfoundry/noaa/errors" 14 "github.com/cloudfoundry/sonde-go/events" 15 ) 16 17 type NoaaLogsRepository struct { 18 config coreconfig.Reader 19 consumer NoaaConsumer 20 tokenRefresher authentication.TokenRefresher 21 messageQueue *NoaaMessageQueue 22 BufferTime time.Duration 23 } 24 25 func NewNoaaLogsRepository(config coreconfig.Reader, consumer NoaaConsumer, tr authentication.TokenRefresher) *NoaaLogsRepository { 26 return &NoaaLogsRepository{ 27 config: config, 28 consumer: consumer, 29 tokenRefresher: tr, 30 messageQueue: NewNoaaMessageQueue(), 31 BufferTime: defaultBufferTime, 32 } 33 } 34 35 func (repo *NoaaLogsRepository) Close() { 36 _ = repo.consumer.Close() 37 } 38 39 func loggableMessagesFromNoaaMessages(messages []*events.LogMessage) []Loggable { 40 loggableMessages := make([]Loggable, len(messages)) 41 42 for i, m := range messages { 43 loggableMessages[i] = NewNoaaLogMessage(m) 44 } 45 46 return loggableMessages 47 } 48 49 func (repo *NoaaLogsRepository) RecentLogsFor(appGUID string) ([]Loggable, error) { 50 logs, err := repo.consumer.RecentLogs(appGUID, repo.config.AccessToken()) 51 52 switch err.(type) { 53 case nil: // do nothing 54 case *noaa_errors.UnauthorizedError: 55 _, _ = repo.tokenRefresher.RefreshAuthToken() 56 return repo.RecentLogsFor(appGUID) 57 default: 58 return loggableMessagesFromNoaaMessages(logs), err 59 } 60 61 return loggableMessagesFromNoaaMessages(noaa.SortRecent(logs)), err 62 } 63 64 func (repo *NoaaLogsRepository) TailLogsFor(appGUID string, onConnect func(), logChan chan<- Loggable, errChan chan<- error) { 65 ticker := time.NewTicker(repo.BufferTime) 66 endpoint := repo.config.DopplerEndpoint() 67 if endpoint == "" { 68 errChan <- errors.New(T("Loggregator endpoint missing from config file")) 69 return 70 } 71 72 repo.consumer.SetOnConnectCallback(onConnect) 73 c, e := repo.consumer.TailingLogsWithoutReconnect(appGUID, repo.config.AccessToken()) 74 75 go func() { 76 for { 77 select { 78 case msg, ok := <-c: 79 if !ok { 80 ticker.Stop() 81 repo.flushMessages(logChan) 82 close(logChan) 83 close(errChan) 84 return 85 } 86 87 repo.messageQueue.PushMessage(msg) 88 case err := <-e: 89 switch err.(type) { 90 case nil: 91 case *noaa_errors.UnauthorizedError: 92 _, _ = repo.tokenRefresher.RefreshAuthToken() 93 ticker.Stop() 94 repo.TailLogsFor(appGUID, onConnect, logChan, errChan) 95 return 96 default: 97 errChan <- err 98 99 ticker.Stop() 100 close(logChan) 101 close(errChan) 102 return 103 } 104 } 105 } 106 }() 107 108 go func() { 109 for range ticker.C { 110 repo.flushMessages(logChan) 111 } 112 }() 113 } 114 115 func (repo *NoaaLogsRepository) flushMessages(c chan<- Loggable) { 116 repo.messageQueue.EnumerateAndClear(func(m *events.LogMessage) { 117 c <- NewNoaaLogMessage(m) 118 }) 119 }