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  }