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  }