github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/cmd/promtail/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"reflect"
     8  
     9  	// embed time zone data
    10  	_ "time/tzdata"
    11  
    12  	"k8s.io/klog"
    13  
    14  	"github.com/go-kit/log/level"
    15  	"github.com/grafana/dskit/flagext"
    16  	"github.com/prometheus/client_golang/prometheus"
    17  	"github.com/prometheus/common/version"
    18  	"github.com/weaveworks/common/logging"
    19  
    20  	"github.com/grafana/loki/clients/pkg/logentry/stages"
    21  	"github.com/grafana/loki/clients/pkg/promtail"
    22  	"github.com/grafana/loki/clients/pkg/promtail/client"
    23  	"github.com/grafana/loki/clients/pkg/promtail/config"
    24  
    25  	"github.com/grafana/loki/pkg/util"
    26  	_ "github.com/grafana/loki/pkg/util/build"
    27  	"github.com/grafana/loki/pkg/util/cfg"
    28  	util_log "github.com/grafana/loki/pkg/util/log"
    29  )
    30  
    31  func init() {
    32  	prometheus.MustRegister(version.NewCollector("promtail"))
    33  }
    34  
    35  type Config struct {
    36  	config.Config   `yaml:",inline"`
    37  	printVersion    bool
    38  	printConfig     bool
    39  	logConfig       bool
    40  	dryRun          bool
    41  	configFile      string
    42  	configExpandEnv bool
    43  	inspect         bool
    44  }
    45  
    46  func (c *Config) RegisterFlags(f *flag.FlagSet) {
    47  	f.BoolVar(&c.printVersion, "version", false, "Print this builds version information")
    48  	f.BoolVar(&c.printConfig, "print-config-stderr", false, "Dump the entire Loki config object to stderr")
    49  	f.BoolVar(&c.logConfig, "log-config-reverse-order", false, "Dump the entire Loki config object at Info log "+
    50  		"level with the order reversed, reversing the order makes viewing the entries easier in Grafana.")
    51  	f.BoolVar(&c.dryRun, "dry-run", false, "Start Promtail but print entries instead of sending them to Loki.")
    52  	f.BoolVar(&c.inspect, "inspect", false, "Allows for detailed inspection of pipeline stages")
    53  	f.StringVar(&c.configFile, "config.file", "", "yaml file to load")
    54  	f.BoolVar(&c.configExpandEnv, "config.expand-env", false, "Expands ${var} in config according to the values of the environment variables.")
    55  	c.Config.RegisterFlags(f)
    56  }
    57  
    58  // Clone takes advantage of pass-by-value semantics to return a distinct *Config.
    59  // This is primarily used to parse a different flag set without mutating the original *Config.
    60  func (c *Config) Clone() flagext.Registerer {
    61  	return func(c Config) *Config {
    62  		return &c
    63  	}(*c)
    64  }
    65  
    66  func main() {
    67  	// Load config, merging config file and CLI flags
    68  	var config Config
    69  	if err := cfg.DefaultUnmarshal(&config, os.Args[1:], flag.CommandLine); err != nil {
    70  		fmt.Println("Unable to parse config:", err)
    71  		os.Exit(1)
    72  	}
    73  
    74  	// Handle -version CLI flag
    75  	if config.printVersion {
    76  		fmt.Println(version.Print("promtail"))
    77  		os.Exit(0)
    78  	}
    79  
    80  	// Init the logger which will honor the log level set in cfg.Server
    81  	if reflect.DeepEqual(&config.Config.ServerConfig.Config.LogLevel, &logging.Level{}) {
    82  		fmt.Println("Invalid log level")
    83  		os.Exit(1)
    84  	}
    85  	util_log.InitLogger(&config.Config.ServerConfig.Config, prometheus.DefaultRegisterer)
    86  
    87  	// Use Stderr instead of files for the klog.
    88  	klog.SetOutput(os.Stderr)
    89  
    90  	if config.inspect {
    91  		stages.Inspect = true
    92  	}
    93  
    94  	// Set the global debug variable in the stages package which is used to conditionally log
    95  	// debug messages which otherwise cause huge allocations processing log lines for log messages never printed
    96  	if config.Config.ServerConfig.Config.LogLevel.String() == "debug" {
    97  		stages.Debug = true
    98  	}
    99  
   100  	if config.printConfig {
   101  		err := util.PrintConfig(os.Stderr, &config)
   102  		if err != nil {
   103  			level.Error(util_log.Logger).Log("msg", "failed to print config to stderr", "err", err.Error())
   104  		}
   105  	}
   106  
   107  	if config.logConfig {
   108  		err := util.LogConfig(&config)
   109  		if err != nil {
   110  			level.Error(util_log.Logger).Log("msg", "failed to log config object", "err", err.Error())
   111  		}
   112  	}
   113  
   114  	clientMetrics := client.NewMetrics(prometheus.DefaultRegisterer, config.Config.Options.StreamLagLabels)
   115  	p, err := promtail.New(config.Config, clientMetrics, config.dryRun)
   116  	if err != nil {
   117  		level.Error(util_log.Logger).Log("msg", "error creating promtail", "error", err)
   118  		os.Exit(1)
   119  	}
   120  
   121  	level.Info(util_log.Logger).Log("msg", "Starting Promtail", "version", version.Info())
   122  	defer p.Shutdown()
   123  
   124  	if err := p.Run(); err != nil {
   125  		level.Error(util_log.Logger).Log("msg", "error starting promtail", "error", err)
   126  		os.Exit(1)
   127  	}
   128  }