github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/promtail/targets/manager.go (about)

     1  package targets
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/go-kit/log"
     7  	"github.com/go-kit/log/level"
     8  	"github.com/pkg/errors"
     9  	"github.com/prometheus/client_golang/prometheus"
    10  
    11  	"github.com/grafana/loki/clients/pkg/promtail/api"
    12  	"github.com/grafana/loki/clients/pkg/promtail/positions"
    13  	"github.com/grafana/loki/clients/pkg/promtail/scrapeconfig"
    14  	"github.com/grafana/loki/clients/pkg/promtail/targets/cloudflare"
    15  	"github.com/grafana/loki/clients/pkg/promtail/targets/docker"
    16  	"github.com/grafana/loki/clients/pkg/promtail/targets/file"
    17  	"github.com/grafana/loki/clients/pkg/promtail/targets/gcplog"
    18  	"github.com/grafana/loki/clients/pkg/promtail/targets/gelf"
    19  	"github.com/grafana/loki/clients/pkg/promtail/targets/heroku"
    20  	"github.com/grafana/loki/clients/pkg/promtail/targets/journal"
    21  	"github.com/grafana/loki/clients/pkg/promtail/targets/kafka"
    22  	"github.com/grafana/loki/clients/pkg/promtail/targets/lokipush"
    23  	"github.com/grafana/loki/clients/pkg/promtail/targets/stdin"
    24  	"github.com/grafana/loki/clients/pkg/promtail/targets/syslog"
    25  	"github.com/grafana/loki/clients/pkg/promtail/targets/target"
    26  	"github.com/grafana/loki/clients/pkg/promtail/targets/windows"
    27  )
    28  
    29  const (
    30  	FileScrapeConfigs    = "fileScrapeConfigs"
    31  	JournalScrapeConfigs = "journalScrapeConfigs"
    32  	SyslogScrapeConfigs  = "syslogScrapeConfigs"
    33  	GcplogScrapeConfigs  = "gcplogScrapeConfigs"
    34  	PushScrapeConfigs    = "pushScrapeConfigs"
    35  	WindowsEventsConfigs = "windowsEventsConfigs"
    36  	KafkaConfigs         = "kafkaConfigs"
    37  	GelfConfigs          = "gelfConfigs"
    38  	CloudflareConfigs    = "cloudflareConfigs"
    39  	DockerConfigs        = "dockerConfigs"
    40  	DockerSDConfigs      = "dockerSDConfigs"
    41  	HerokuDrainConfigs   = "herokuDrainConfigs"
    42  )
    43  
    44  type targetManager interface {
    45  	Ready() bool
    46  	Stop()
    47  	ActiveTargets() map[string][]target.Target
    48  	AllTargets() map[string][]target.Target
    49  }
    50  
    51  // TargetManagers manages a list of target managers.
    52  type TargetManagers struct {
    53  	targetManagers []targetManager
    54  	positions      positions.Positions
    55  }
    56  
    57  // NewTargetManagers makes a new TargetManagers
    58  func NewTargetManagers(
    59  	app stdin.Shutdownable,
    60  	reg prometheus.Registerer,
    61  	logger log.Logger,
    62  	positionsConfig positions.Config,
    63  	client api.EntryHandler,
    64  	scrapeConfigs []scrapeconfig.Config,
    65  	targetConfig *file.Config,
    66  ) (*TargetManagers, error) {
    67  	if targetConfig.Stdin {
    68  		level.Debug(logger).Log("msg", "configured to read from stdin")
    69  		stdin, err := stdin.NewStdinTargetManager(reg, logger, app, client, scrapeConfigs)
    70  		if err != nil {
    71  			return nil, err
    72  		}
    73  		return &TargetManagers{targetManagers: []targetManager{stdin}}, nil
    74  	}
    75  
    76  	var targetManagers []targetManager
    77  	targetScrapeConfigs := make(map[string][]scrapeconfig.Config, 4)
    78  
    79  	for _, cfg := range scrapeConfigs {
    80  		switch {
    81  		case cfg.HasServiceDiscoveryConfig():
    82  			targetScrapeConfigs[FileScrapeConfigs] = append(targetScrapeConfigs[FileScrapeConfigs], cfg)
    83  		case cfg.JournalConfig != nil:
    84  			targetScrapeConfigs[JournalScrapeConfigs] = append(targetScrapeConfigs[JournalScrapeConfigs], cfg)
    85  		case cfg.SyslogConfig != nil:
    86  			targetScrapeConfigs[SyslogScrapeConfigs] = append(targetScrapeConfigs[SyslogScrapeConfigs], cfg)
    87  		case cfg.GcplogConfig != nil:
    88  			targetScrapeConfigs[GcplogScrapeConfigs] = append(targetScrapeConfigs[GcplogScrapeConfigs], cfg)
    89  		case cfg.PushConfig != nil:
    90  			targetScrapeConfigs[PushScrapeConfigs] = append(targetScrapeConfigs[PushScrapeConfigs], cfg)
    91  		case cfg.WindowsConfig != nil:
    92  			targetScrapeConfigs[WindowsEventsConfigs] = append(targetScrapeConfigs[WindowsEventsConfigs], cfg)
    93  		case cfg.KafkaConfig != nil:
    94  			targetScrapeConfigs[KafkaConfigs] = append(targetScrapeConfigs[KafkaConfigs], cfg)
    95  		case cfg.GelfConfig != nil:
    96  			targetScrapeConfigs[GelfConfigs] = append(targetScrapeConfigs[GelfConfigs], cfg)
    97  		case cfg.CloudflareConfig != nil:
    98  			targetScrapeConfigs[CloudflareConfigs] = append(targetScrapeConfigs[CloudflareConfigs], cfg)
    99  		case cfg.DockerSDConfigs != nil:
   100  			targetScrapeConfigs[DockerSDConfigs] = append(targetScrapeConfigs[DockerSDConfigs], cfg)
   101  		case cfg.HerokuDrainConfig != nil:
   102  			targetScrapeConfigs[HerokuDrainConfigs] = append(targetScrapeConfigs[HerokuDrainConfigs], cfg)
   103  		default:
   104  			return nil, fmt.Errorf("no valid target scrape config defined for %q", cfg.JobName)
   105  		}
   106  	}
   107  
   108  	var positionFile positions.Positions
   109  
   110  	// position file is a singleton, we use a function to keep it so.
   111  	getPositionFile := func() (positions.Positions, error) {
   112  		if positionFile == nil {
   113  			var err error
   114  			positionFile, err = positions.New(logger, positionsConfig)
   115  			if err != nil {
   116  				return nil, err
   117  			}
   118  		}
   119  		return positionFile, nil
   120  	}
   121  
   122  	var (
   123  		fileMetrics        *file.Metrics
   124  		syslogMetrics      *syslog.Metrics
   125  		gcplogMetrics      *gcplog.Metrics
   126  		gelfMetrics        *gelf.Metrics
   127  		cloudflareMetrics  *cloudflare.Metrics
   128  		dockerMetrics      *docker.Metrics
   129  		journalMetrics     *journal.Metrics
   130  		herokuDrainMetrics *heroku.Metrics
   131  	)
   132  	if len(targetScrapeConfigs[FileScrapeConfigs]) > 0 {
   133  		fileMetrics = file.NewMetrics(reg)
   134  	}
   135  	if len(targetScrapeConfigs[SyslogScrapeConfigs]) > 0 {
   136  		syslogMetrics = syslog.NewMetrics(reg)
   137  	}
   138  	if len(targetScrapeConfigs[GcplogScrapeConfigs]) > 0 {
   139  		gcplogMetrics = gcplog.NewMetrics(reg)
   140  	}
   141  	if len(targetScrapeConfigs[GelfConfigs]) > 0 {
   142  		gelfMetrics = gelf.NewMetrics(reg)
   143  	}
   144  	if len(targetScrapeConfigs[CloudflareConfigs]) > 0 {
   145  		cloudflareMetrics = cloudflare.NewMetrics(reg)
   146  	}
   147  	if len(targetScrapeConfigs[DockerConfigs]) > 0 || len(targetScrapeConfigs[DockerSDConfigs]) > 0 {
   148  		dockerMetrics = docker.NewMetrics(reg)
   149  	}
   150  	if len(targetScrapeConfigs[JournalScrapeConfigs]) > 0 {
   151  		journalMetrics = journal.NewMetrics(reg)
   152  	}
   153  	if len(targetScrapeConfigs[HerokuDrainConfigs]) > 0 {
   154  		herokuDrainMetrics = heroku.NewMetrics(reg)
   155  	}
   156  
   157  	for target, scrapeConfigs := range targetScrapeConfigs {
   158  		switch target {
   159  		case FileScrapeConfigs:
   160  			pos, err := getPositionFile()
   161  			if err != nil {
   162  				return nil, err
   163  			}
   164  			fileTargetManager, err := file.NewFileTargetManager(
   165  				fileMetrics,
   166  				logger,
   167  				pos,
   168  				client,
   169  				scrapeConfigs,
   170  				targetConfig,
   171  			)
   172  			if err != nil {
   173  				return nil, errors.Wrap(err, "failed to make file target manager")
   174  			}
   175  			targetManagers = append(targetManagers, fileTargetManager)
   176  		case JournalScrapeConfigs:
   177  			pos, err := getPositionFile()
   178  			if err != nil {
   179  				return nil, err
   180  			}
   181  			journalTargetManager, err := journal.NewJournalTargetManager(
   182  				journalMetrics,
   183  				logger,
   184  				pos,
   185  				client,
   186  				scrapeConfigs,
   187  			)
   188  			if err != nil {
   189  				return nil, errors.Wrap(err, "failed to make journal target manager")
   190  			}
   191  			targetManagers = append(targetManagers, journalTargetManager)
   192  		case SyslogScrapeConfigs:
   193  			syslogTargetManager, err := syslog.NewSyslogTargetManager(
   194  				syslogMetrics,
   195  				logger,
   196  				client,
   197  				scrapeConfigs,
   198  			)
   199  			if err != nil {
   200  				return nil, errors.Wrap(err, "failed to make syslog target manager")
   201  			}
   202  			targetManagers = append(targetManagers, syslogTargetManager)
   203  		case GcplogScrapeConfigs:
   204  			pubsubTargetManager, err := gcplog.NewGcplogTargetManager(
   205  				gcplogMetrics,
   206  				logger,
   207  				client,
   208  				scrapeConfigs,
   209  			)
   210  			if err != nil {
   211  				return nil, errors.Wrap(err, "failed to make syslog target manager")
   212  			}
   213  			targetManagers = append(targetManagers, pubsubTargetManager)
   214  		case PushScrapeConfigs:
   215  			pushTargetManager, err := lokipush.NewPushTargetManager(
   216  				reg,
   217  				logger,
   218  				client,
   219  				scrapeConfigs,
   220  			)
   221  			if err != nil {
   222  				return nil, errors.Wrap(err, "failed to make Loki Push API target manager")
   223  			}
   224  			targetManagers = append(targetManagers, pushTargetManager)
   225  		case HerokuDrainConfigs:
   226  			herokuDrainTargetManager, err := heroku.NewHerokuDrainTargetManager(herokuDrainMetrics, reg, logger, client, scrapeConfigs)
   227  			if err != nil {
   228  				return nil, errors.Wrap(err, "failed to make Heroku drain target manager")
   229  			}
   230  			targetManagers = append(targetManagers, herokuDrainTargetManager)
   231  		case WindowsEventsConfigs:
   232  			windowsTargetManager, err := windows.NewTargetManager(reg, logger, client, scrapeConfigs)
   233  			if err != nil {
   234  				return nil, errors.Wrap(err, "failed to make windows target manager")
   235  			}
   236  			targetManagers = append(targetManagers, windowsTargetManager)
   237  		case KafkaConfigs:
   238  			kafkaTargetManager, err := kafka.NewTargetManager(reg, logger, client, scrapeConfigs)
   239  			if err != nil {
   240  				return nil, errors.Wrap(err, "failed to make kafka target manager")
   241  			}
   242  			targetManagers = append(targetManagers, kafkaTargetManager)
   243  		case GelfConfigs:
   244  			gelfTargetManager, err := gelf.NewTargetManager(gelfMetrics, logger, client, scrapeConfigs)
   245  			if err != nil {
   246  				return nil, errors.Wrap(err, "failed to make gelf target manager")
   247  			}
   248  			targetManagers = append(targetManagers, gelfTargetManager)
   249  		case CloudflareConfigs:
   250  			pos, err := getPositionFile()
   251  			if err != nil {
   252  				return nil, err
   253  			}
   254  			cfTargetManager, err := cloudflare.NewTargetManager(cloudflareMetrics, logger, pos, client, scrapeConfigs)
   255  			if err != nil {
   256  				return nil, errors.Wrap(err, "failed to make cloudflare target manager")
   257  			}
   258  			targetManagers = append(targetManagers, cfTargetManager)
   259  		case DockerConfigs:
   260  			pos, err := getPositionFile()
   261  			if err != nil {
   262  				return nil, err
   263  			}
   264  			cfTargetManager, err := docker.NewTargetManager(dockerMetrics, logger, pos, client, scrapeConfigs)
   265  			if err != nil {
   266  				return nil, errors.Wrap(err, "failed to make Docker target manager")
   267  			}
   268  			targetManagers = append(targetManagers, cfTargetManager)
   269  		case DockerSDConfigs:
   270  			pos, err := getPositionFile()
   271  			if err != nil {
   272  				return nil, err
   273  			}
   274  			cfTargetManager, err := docker.NewTargetManager(dockerMetrics, logger, pos, client, scrapeConfigs)
   275  			if err != nil {
   276  				return nil, errors.Wrap(err, "failed to make Docker service discovery target manager")
   277  			}
   278  			targetManagers = append(targetManagers, cfTargetManager)
   279  		default:
   280  			return nil, errors.New("unknown scrape config")
   281  		}
   282  	}
   283  
   284  	return &TargetManagers{
   285  		targetManagers: targetManagers,
   286  		positions:      positionFile,
   287  	}, nil
   288  }
   289  
   290  // ActiveTargets returns active targets per jobs
   291  func (tm *TargetManagers) ActiveTargets() map[string][]target.Target {
   292  	result := map[string][]target.Target{}
   293  	for _, t := range tm.targetManagers {
   294  		for job, targets := range t.ActiveTargets() {
   295  			result[job] = append(result[job], targets...)
   296  		}
   297  	}
   298  	return result
   299  }
   300  
   301  // AllTargets returns all targets per jobs
   302  func (tm *TargetManagers) AllTargets() map[string][]target.Target {
   303  	result := map[string][]target.Target{}
   304  	for _, t := range tm.targetManagers {
   305  		for job, targets := range t.AllTargets() {
   306  			result[job] = append(result[job], targets...)
   307  		}
   308  	}
   309  	return result
   310  }
   311  
   312  // Ready if there's at least one ready target manager.
   313  func (tm *TargetManagers) Ready() bool {
   314  	for _, t := range tm.targetManagers {
   315  		if t.Ready() {
   316  			return true
   317  		}
   318  	}
   319  	return false
   320  }
   321  
   322  // Stop the TargetManagers.
   323  func (tm *TargetManagers) Stop() {
   324  	for _, t := range tm.targetManagers {
   325  		t.Stop()
   326  	}
   327  	if tm.positions != nil {
   328  		tm.positions.Stop()
   329  	}
   330  }