github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/promtail/targets/docker/target_group.go (about) 1 package docker 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/docker/docker/client" 8 "github.com/go-kit/log" 9 "github.com/go-kit/log/level" 10 "github.com/prometheus/common/model" 11 "github.com/prometheus/prometheus/discovery/targetgroup" 12 "github.com/prometheus/prometheus/model/relabel" 13 14 "github.com/grafana/loki/clients/pkg/promtail/api" 15 "github.com/grafana/loki/clients/pkg/promtail/positions" 16 "github.com/grafana/loki/clients/pkg/promtail/targets/target" 17 ) 18 19 const DockerSource = "Docker" 20 21 // targetGroup manages all container targets of one Docker daemon. 22 type targetGroup struct { 23 metrics *Metrics 24 logger log.Logger 25 positions positions.Positions 26 entryHandler api.EntryHandler 27 defaultLabels model.LabelSet 28 relabelConfig []*relabel.Config 29 host string 30 client client.APIClient 31 32 mtx sync.Mutex 33 targets map[string]*Target 34 } 35 36 func (tg *targetGroup) sync(groups []*targetgroup.Group) { 37 tg.mtx.Lock() 38 defer tg.mtx.Unlock() 39 40 for _, group := range groups { 41 if group.Source != DockerSource { 42 continue 43 } 44 45 for _, t := range group.Targets { 46 containerID, ok := t[dockerLabelContainerID] 47 if !ok { 48 level.Debug(tg.logger).Log("msg", "Docker target did not include container ID") 49 continue 50 } 51 52 err := tg.addTarget(string(containerID), t) 53 if err != nil { 54 level.Error(tg.logger).Log("msg", "could not add target", "containerID", containerID, "err", err) 55 } 56 } 57 } 58 } 59 60 // addTarget checks whether the container with given id is already known. If not it's added to the this group 61 func (tg *targetGroup) addTarget(id string, discoveredLabels model.LabelSet) error { 62 if tg.client == nil { 63 var err error 64 opts := []client.Opt{ 65 client.WithHost(tg.host), 66 client.WithAPIVersionNegotiation(), 67 } 68 tg.client, err = client.NewClientWithOpts(opts...) 69 if err != nil { 70 level.Error(tg.logger).Log("msg", "could not create new Docker client", "err", err) 71 return err 72 } 73 } 74 75 if t, ok := tg.targets[id]; ok { 76 level.Debug(tg.logger).Log("msg", "container target already exists", "container", id) 77 t.startIfNotRunning() 78 return nil 79 } 80 81 t, err := NewTarget( 82 tg.metrics, 83 log.With(tg.logger, "target", fmt.Sprintf("docker/%s", id)), 84 tg.entryHandler, 85 tg.positions, 86 id, 87 discoveredLabels.Merge(tg.defaultLabels), 88 tg.relabelConfig, 89 tg.client, 90 ) 91 if err != nil { 92 return err 93 } 94 tg.targets[id] = t 95 level.Error(tg.logger).Log("msg", "added Docker target", "containerID", id) 96 return nil 97 } 98 99 // Ready returns true if at least one target is running. 100 func (tg *targetGroup) Ready() bool { 101 tg.mtx.Lock() 102 defer tg.mtx.Unlock() 103 104 for _, t := range tg.targets { 105 if t.Ready() { 106 return true 107 } 108 } 109 110 return true 111 } 112 113 // Stop all targets 114 func (tg *targetGroup) Stop() { 115 tg.mtx.Lock() 116 defer tg.mtx.Unlock() 117 118 for _, t := range tg.targets { 119 t.Stop() 120 } 121 tg.entryHandler.Stop() 122 } 123 124 // ActiveTargets return all targets that are ready. 125 func (tg *targetGroup) ActiveTargets() []target.Target { 126 tg.mtx.Lock() 127 defer tg.mtx.Unlock() 128 129 result := make([]target.Target, 0, len(tg.targets)) 130 for _, t := range tg.targets { 131 if t.Ready() { 132 result = append(result, t) 133 } 134 } 135 return result 136 } 137 138 // AllTargets returns all targets of this group. 139 func (tg *targetGroup) AllTargets() []target.Target { 140 result := make([]target.Target, 0, len(tg.targets)) 141 for _, t := range tg.targets { 142 result = append(result, t) 143 } 144 return result 145 }