github.com/prysmaticlabs/prysm@v1.4.4/cmd/client-stats/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	runtimeDebug "runtime/debug"
     7  	"time"
     8  
     9  	joonix "github.com/joonix/log"
    10  	"github.com/prysmaticlabs/prysm/cmd/client-stats/flags"
    11  	"github.com/prysmaticlabs/prysm/shared/clientstats"
    12  	"github.com/prysmaticlabs/prysm/shared/cmd"
    13  	"github.com/prysmaticlabs/prysm/shared/journald"
    14  	"github.com/prysmaticlabs/prysm/shared/logutil"
    15  	"github.com/prysmaticlabs/prysm/shared/version"
    16  	"github.com/sirupsen/logrus"
    17  	"github.com/urfave/cli/v2"
    18  	prefixed "github.com/x-cray/logrus-prefixed-formatter"
    19  )
    20  
    21  var appFlags = []cli.Flag{
    22  	cmd.VerbosityFlag,
    23  	cmd.LogFormat,
    24  	cmd.LogFileName,
    25  	cmd.ConfigFileFlag,
    26  	flags.BeaconnodeMetricsURLFlag,
    27  	flags.ValidatorMetricsURLFlag,
    28  	flags.ClientStatsAPIURLFlag,
    29  	flags.ScrapeIntervalFlag,
    30  }
    31  
    32  func main() {
    33  	app := cli.App{}
    34  	app.Name = "client-stats"
    35  	app.Usage = "daemon to scrape client-stats from prometheus and ship to a remote endpoint"
    36  	app.Action = run
    37  	app.Version = version.Version()
    38  
    39  	app.Flags = appFlags
    40  
    41  	// logging/config setup cargo-culted from beaconchain
    42  	app.Before = func(ctx *cli.Context) error {
    43  		// Load flags from config file, if specified.
    44  		if err := cmd.LoadFlagsFromConfig(ctx, app.Flags); err != nil {
    45  			return err
    46  		}
    47  
    48  		verbosity := ctx.String(cmd.VerbosityFlag.Name)
    49  		level, err := logrus.ParseLevel(verbosity)
    50  		if err != nil {
    51  			return err
    52  		}
    53  		logrus.SetLevel(level)
    54  
    55  		format := ctx.String(cmd.LogFormat.Name)
    56  		switch format {
    57  		case "text":
    58  			formatter := new(prefixed.TextFormatter)
    59  			formatter.TimestampFormat = "2006-01-02 15:04:05"
    60  			formatter.FullTimestamp = true
    61  			// If persistent log files are written - we disable the log messages coloring because
    62  			// the colors are ANSI codes and seen as gibberish in the log files.
    63  			formatter.DisableColors = ctx.String(cmd.LogFileName.Name) != ""
    64  			logrus.SetFormatter(formatter)
    65  		case "fluentd":
    66  			f := joonix.NewFormatter()
    67  			if err := joonix.DisableTimestampFormat(f); err != nil {
    68  				panic(err)
    69  			}
    70  			logrus.SetFormatter(f)
    71  		case "json":
    72  			logrus.SetFormatter(&logrus.JSONFormatter{})
    73  		case "journald":
    74  			if err := journald.Enable(); err != nil {
    75  				return err
    76  			}
    77  		default:
    78  			return fmt.Errorf("unknown log format %s", format)
    79  		}
    80  
    81  		logFileName := ctx.String(cmd.LogFileName.Name)
    82  		if logFileName != "" {
    83  			if err := logutil.ConfigurePersistentLogging(logFileName); err != nil {
    84  				log.WithError(err).Error("Failed to configuring logging to disk.")
    85  			}
    86  		}
    87  		return cmd.ValidateNoArgs(ctx)
    88  	}
    89  
    90  	defer func() {
    91  		if x := recover(); x != nil {
    92  			log.Errorf("Runtime panic: %v\n%v", x, string(runtimeDebug.Stack()))
    93  			panic(x)
    94  		}
    95  	}()
    96  
    97  	if err := app.Run(os.Args); err != nil {
    98  		log.Error(err.Error())
    99  	}
   100  }
   101  
   102  func run(ctx *cli.Context) error {
   103  	var upd clientstats.Updater
   104  	if ctx.IsSet(flags.ClientStatsAPIURLFlag.Name) {
   105  		u := ctx.String(flags.ClientStatsAPIURLFlag.Name)
   106  		upd = clientstats.NewClientStatsHTTPPostUpdater(u)
   107  	} else {
   108  		log.Warn("No --clientstats-api-url flag set, writing to stdout as default metrics sink.")
   109  		upd = clientstats.NewGenericClientStatsUpdater(os.Stdout)
   110  	}
   111  
   112  	scrapers := make([]clientstats.Scraper, 0)
   113  	if ctx.IsSet(flags.BeaconnodeMetricsURLFlag.Name) {
   114  		u := ctx.String(flags.BeaconnodeMetricsURLFlag.Name)
   115  		scrapers = append(scrapers, clientstats.NewBeaconNodeScraper(u))
   116  	}
   117  	if ctx.IsSet(flags.ValidatorMetricsURLFlag.Name) {
   118  		u := ctx.String(flags.ValidatorMetricsURLFlag.Name)
   119  		scrapers = append(scrapers, clientstats.NewValidatorScraper(u))
   120  	}
   121  
   122  	ticker := time.NewTicker(ctx.Duration(flags.ScrapeIntervalFlag.Name))
   123  	for {
   124  		select {
   125  		case <-ticker.C:
   126  			for _, s := range scrapers {
   127  				r, err := s.Scrape()
   128  				if err != nil {
   129  					log.Errorf("Scraper error: %s", err)
   130  					continue
   131  				}
   132  				err = upd.Update(r)
   133  				if err != nil {
   134  					log.Errorf("client-stats collector error: %s", err)
   135  					continue
   136  				}
   137  			}
   138  		case <-ctx.Done():
   139  			ticker.Stop()
   140  			return nil
   141  		}
   142  	}
   143  }