github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/promtail/client/multi.go (about) 1 package client 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 "sync" 8 9 "github.com/go-kit/log" 10 11 "github.com/grafana/loki/clients/pkg/promtail/api" 12 ) 13 14 // MultiClient is client pushing to one or more loki instances. 15 type MultiClient struct { 16 clients []Client 17 entries chan api.Entry 18 wg sync.WaitGroup 19 20 once sync.Once 21 } 22 23 // NewMulti creates a new client 24 func NewMulti(metrics *Metrics, streamLagLabels []string, logger log.Logger, cfgs ...Config) (Client, error) { 25 var fake struct{} 26 27 if len(cfgs) == 0 { 28 return nil, errors.New("at least one client config should be provided") 29 } 30 clientsCheck := make(map[string]struct{}) 31 clients := make([]Client, 0, len(cfgs)) 32 for _, cfg := range cfgs { 33 client, err := New(metrics, cfg, streamLagLabels, logger) 34 if err != nil { 35 return nil, err 36 } 37 38 // Don't allow duplicate clients, we have client specific metrics that need at least one unique label value (name). 39 if _, ok := clientsCheck[client.Name()]; ok { 40 return nil, fmt.Errorf("duplicate client configs are not allowed, found duplicate for URL: %s", cfg.URL) 41 } 42 43 clientsCheck[client.Name()] = fake 44 clients = append(clients, client) 45 } 46 multi := &MultiClient{ 47 clients: clients, 48 entries: make(chan api.Entry), 49 } 50 multi.start() 51 return multi, nil 52 } 53 54 func (m *MultiClient) start() { 55 m.wg.Add(1) 56 go func() { 57 defer m.wg.Done() 58 for e := range m.entries { 59 for _, c := range m.clients { 60 c.Chan() <- e 61 } 62 } 63 }() 64 } 65 66 func (m *MultiClient) Chan() chan<- api.Entry { 67 return m.entries 68 } 69 70 // Stop implements Client 71 func (m *MultiClient) Stop() { 72 m.once.Do(func() { close(m.entries) }) 73 m.wg.Wait() 74 for _, c := range m.clients { 75 c.Stop() 76 } 77 } 78 79 // StopNow implements Client 80 func (m *MultiClient) StopNow() { 81 for _, c := range m.clients { 82 c.StopNow() 83 } 84 } 85 86 func (m *MultiClient) Name() string { 87 var sb strings.Builder 88 sb.WriteString("multi:") 89 for i, c := range m.clients { 90 sb.WriteString(c.Name()) 91 if i != len(m.clients)-1 { 92 sb.WriteString(",") 93 } 94 } 95 return sb.String() 96 }