github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/promtail/targets/docker/targetmanager.go (about) 1 package docker 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/go-kit/log" 8 "github.com/go-kit/log/level" 9 "github.com/prometheus/common/model" 10 "github.com/prometheus/prometheus/discovery" 11 12 "github.com/grafana/loki/clients/pkg/logentry/stages" 13 "github.com/grafana/loki/clients/pkg/promtail/api" 14 "github.com/grafana/loki/clients/pkg/promtail/positions" 15 "github.com/grafana/loki/clients/pkg/promtail/scrapeconfig" 16 "github.com/grafana/loki/clients/pkg/promtail/targets/target" 17 18 "github.com/grafana/loki/pkg/util" 19 ) 20 21 const ( 22 // See github.com/prometheus/prometheus/discovery/moby 23 dockerLabel = model.MetaLabelPrefix + "docker_" 24 dockerLabelContainerPrefix = dockerLabel + "container_" 25 dockerLabelContainerID = dockerLabelContainerPrefix + "id" 26 dockerLabelLogStream = dockerLabelContainerPrefix + "log_stream" 27 ) 28 29 type TargetManager struct { 30 metrics *Metrics 31 logger log.Logger 32 positions positions.Positions 33 cancel context.CancelFunc 34 done chan struct{} 35 manager *discovery.Manager 36 pushClient api.EntryHandler 37 groups map[string]*targetGroup 38 } 39 40 func NewTargetManager( 41 metrics *Metrics, 42 logger log.Logger, 43 positions positions.Positions, 44 pushClient api.EntryHandler, 45 scrapeConfigs []scrapeconfig.Config, 46 ) (*TargetManager, error) { 47 ctx, cancel := context.WithCancel(context.Background()) 48 tm := &TargetManager{ 49 metrics: metrics, 50 logger: logger, 51 cancel: cancel, 52 done: make(chan struct{}), 53 positions: positions, 54 manager: discovery.NewManager(ctx, log.With(logger, "component", "docker_discovery")), 55 pushClient: pushClient, 56 groups: make(map[string]*targetGroup), 57 } 58 configs := map[string]discovery.Configs{} 59 for _, cfg := range scrapeConfigs { 60 if cfg.DockerSDConfigs != nil { 61 pipeline, err := stages.NewPipeline( 62 log.With(logger, "component", "docker_pipeline"), 63 cfg.PipelineStages, 64 &cfg.JobName, 65 metrics.reg, 66 ) 67 if err != nil { 68 return nil, err 69 } 70 71 for _, sdConfig := range cfg.DockerSDConfigs { 72 syncerKey := fmt.Sprintf("%s/%s:%d", cfg.JobName, sdConfig.Host, sdConfig.Port) 73 _, ok := tm.groups[syncerKey] 74 if !ok { 75 tm.groups[syncerKey] = &targetGroup{ 76 metrics: metrics, 77 logger: logger, 78 positions: positions, 79 targets: make(map[string]*Target), 80 entryHandler: pipeline.Wrap(pushClient), 81 defaultLabels: model.LabelSet{}, 82 relabelConfig: cfg.RelabelConfigs, 83 host: sdConfig.Host, 84 } 85 } 86 configs[syncerKey] = append(configs[syncerKey], sdConfig) 87 } 88 } else { 89 level.Debug(tm.logger).Log("msg", "Docker service discovery configs are empty") 90 } 91 } 92 93 go tm.run(ctx) 94 go util.LogError("running target manager", tm.manager.Run) 95 96 return tm, tm.manager.ApplyConfig(configs) 97 } 98 99 // run listens on the service discovery and adds new targets. 100 func (tm *TargetManager) run(ctx context.Context) { 101 defer close(tm.done) 102 for { 103 select { 104 case targetGroups := <-tm.manager.SyncCh(): 105 for jobName, groups := range targetGroups { 106 tg, ok := tm.groups[jobName] 107 if !ok { 108 level.Debug(tm.logger).Log("msg", "unknown target for job", "job", jobName) 109 continue 110 } 111 tg.sync(groups) 112 } 113 case <-ctx.Done(): 114 return 115 } 116 } 117 } 118 119 // Ready returns true if at least one Docker target is active. 120 func (tm *TargetManager) Ready() bool { 121 for _, s := range tm.groups { 122 if s.Ready() { 123 return true 124 } 125 } 126 return false 127 } 128 129 func (tm *TargetManager) Stop() { 130 tm.cancel() 131 <-tm.done 132 for _, s := range tm.groups { 133 s.Stop() 134 } 135 } 136 137 func (tm *TargetManager) ActiveTargets() map[string][]target.Target { 138 result := make(map[string][]target.Target, len(tm.groups)) 139 for k, s := range tm.groups { 140 result[k] = s.ActiveTargets() 141 } 142 return result 143 } 144 145 func (tm *TargetManager) AllTargets() map[string][]target.Target { 146 result := make(map[string][]target.Target, len(tm.groups)) 147 for k, s := range tm.groups { 148 result[k] = s.AllTargets() 149 } 150 return result 151 }