github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/cmd/init.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"time"
    10  
    11  	"contrib.go.opencensus.io/exporter/jaeger"
    12  	"contrib.go.opencensus.io/exporter/prometheus"
    13  	"github.com/hellofresh/janus/pkg/config"
    14  	obs "github.com/hellofresh/janus/pkg/observability"
    15  	"github.com/hellofresh/logging-go"
    16  	_trace "github.com/hellofresh/opencensus-go-extras/trace"
    17  	"github.com/hellofresh/stats-go"
    18  	"github.com/hellofresh/stats-go/bucket"
    19  	"github.com/hellofresh/stats-go/client"
    20  	"github.com/hellofresh/stats-go/hooks"
    21  	log "github.com/sirupsen/logrus"
    22  	"go.opencensus.io/stats/view"
    23  	"go.opencensus.io/trace"
    24  )
    25  
    26  var (
    27  	globalConfig *config.Specification
    28  	statsClient  client.Client
    29  )
    30  
    31  func initLogWriterEarly() {
    32  	switch logging.LogWriter(strings.ToLower(os.Getenv("LOG_WRITER"))) {
    33  	case logging.StdOut:
    34  		log.SetOutput(os.Stdout)
    35  	case logging.Discard:
    36  		log.SetOutput(ioutil.Discard)
    37  	case logging.StdErr:
    38  		fallthrough
    39  	default:
    40  		log.SetOutput(os.Stderr)
    41  	}
    42  }
    43  
    44  func initConfig() {
    45  	var err error
    46  	globalConfig, err = config.Load(configFile)
    47  	if nil != err {
    48  		log.WithError(err).Info("Could not load configurations from file - trying environment configurations instead.")
    49  
    50  		globalConfig, err = config.LoadEnv()
    51  		if nil != err {
    52  			log.WithError(err).Error("Could not load configurations from environment variables")
    53  		}
    54  	}
    55  }
    56  
    57  // initializes the basic configuration for the log wrapper
    58  func initLog() {
    59  	err := globalConfig.Log.Apply()
    60  	if nil != err {
    61  		log.WithError(err).Fatal("Could not apply logging configurations")
    62  	}
    63  }
    64  
    65  func initStatsClient() {
    66  	// FIXME: this causes application hang because we're in the locked log already
    67  	//statsLog.SetHandler(func(msg string, fields map[string]interface{}, err error) {
    68  	//	entry := log.WithFields(log.Fields(fields))
    69  	//	if err == nil {
    70  	//		entry.Warn(msg)
    71  	//	} else {
    72  	//		entry.WithError(err).Warn(msg)
    73  	//	}
    74  	//})
    75  
    76  	sectionsTestsMap, err := bucket.ParseSectionsTestsMap(globalConfig.Stats.IDs)
    77  	if err != nil {
    78  		log.WithError(err).WithField("config", globalConfig.Stats.IDs).
    79  			Error("Failed to parse stats second level IDs from env")
    80  		sectionsTestsMap = map[bucket.PathSection]bucket.SectionTestDefinition{}
    81  	}
    82  	log.WithField("config", globalConfig.Stats.IDs).
    83  		WithField("map", sectionsTestsMap.String()).
    84  		Debug("Setting stats second level IDs")
    85  
    86  	statsClient, err = stats.NewClient(globalConfig.Stats.DSN)
    87  	if err != nil {
    88  		log.WithError(err).Fatal("Error initializing stats client")
    89  	}
    90  
    91  	statsClient.SetHTTPMetricCallback(bucket.NewHasIDAtSecondLevelCallback(&bucket.SecondLevelIDConfig{
    92  		HasIDAtSecondLevel:    sectionsTestsMap,
    93  		AutoDiscoverThreshold: globalConfig.Stats.AutoDiscoverThreshold,
    94  		AutoDiscoverWhiteList: globalConfig.Stats.AutoDiscoverWhiteList,
    95  	}))
    96  
    97  	host, err := os.Hostname()
    98  	if nil != err {
    99  		host = "-unknown-"
   100  	}
   101  
   102  	_, appFile := filepath.Split(os.Args[0])
   103  	statsClient.TrackMetric("app", bucket.MetricOperation{"init", host, appFile})
   104  
   105  	log.AddHook(hooks.NewLogrusHook(statsClient, globalConfig.Stats.ErrorsSection))
   106  }
   107  
   108  func initStatsExporter() {
   109  	var err error
   110  	logger := log.WithField("stats.exporter", globalConfig.Stats.Exporter)
   111  
   112  	// Register stats exporter according to config
   113  	switch globalConfig.Stats.Exporter {
   114  	case obs.Datadog:
   115  		fallthrough
   116  	case obs.Stackdriver:
   117  		logger.Warn("Not implemented!")
   118  		return
   119  	case obs.Prometheus:
   120  		err = initPrometheusExporter()
   121  	default:
   122  		logger.Info("Invalid or no stats exporter was specified")
   123  		return
   124  	}
   125  
   126  	if err != nil {
   127  		logger.WithError(err).Error("Failed initialising stats exporter")
   128  		return
   129  	}
   130  
   131  	// Configure/Register stats views
   132  	view.SetReportingPeriod(time.Second)
   133  
   134  	vv := append(obs.AllViews)
   135  
   136  	if err := view.Register(vv...); err != nil {
   137  		log.WithError(err).Warn("Failed to register server views")
   138  	}
   139  }
   140  
   141  func initPrometheusExporter() (err error) {
   142  	obs.PrometheusExporter, err = prometheus.NewExporter(prometheus.Options{})
   143  	if err != nil {
   144  		log.WithError(err).Warn("Failed to create prometheus exporter")
   145  	} else {
   146  		view.RegisterExporter(obs.PrometheusExporter)
   147  	}
   148  	return err
   149  }
   150  
   151  func initTracingExporter() {
   152  	var err error
   153  	logger := log.WithField("tracing.exporter", globalConfig.Tracing.Exporter)
   154  
   155  	switch globalConfig.Tracing.Exporter {
   156  	case obs.AzureMonitor:
   157  		fallthrough
   158  	case obs.Datadog:
   159  		fallthrough
   160  	case obs.Stackdriver:
   161  		fallthrough
   162  	case obs.Zipkin:
   163  		logger.Warn("Not implemented!")
   164  	case obs.Jaeger:
   165  		err = initJaegerExporter()
   166  	default:
   167  		logger.Info("Invalid or no tracing exporter was specified")
   168  		return
   169  	}
   170  
   171  	if err != nil {
   172  		logger.WithError(err).Error("Failed initialising tracing exporter")
   173  		return
   174  	}
   175  
   176  	var traceConfig trace.Config
   177  	var sampler trace.Sampler
   178  	logger = logger.WithField("tracing.samplingStrategy", globalConfig.Tracing.SamplingStrategy)
   179  
   180  	switch globalConfig.Tracing.SamplingStrategy {
   181  	case "always":
   182  		sampler = trace.AlwaysSample()
   183  	case "never":
   184  		sampler = trace.NeverSample()
   185  	case "probabilistic":
   186  		sampler = trace.ProbabilitySampler(globalConfig.Tracing.SamplingParam)
   187  	default:
   188  		logger.Warn("Invalid tracing sampling strategy specified")
   189  		return
   190  	}
   191  
   192  	if !globalConfig.Tracing.IsPublicEndpoint {
   193  		sampler = _trace.RespectParentSampler(sampler)
   194  	}
   195  
   196  	traceConfig.DefaultSampler = sampler
   197  	trace.ApplyConfig(traceConfig)
   198  }
   199  
   200  func initJaegerExporter() (err error) {
   201  	jaegerURL := globalConfig.Tracing.JaegerTracing.SamplingServerURL
   202  	if jaegerURL == "" {
   203  		jaegerURL = fmt.Sprintf("%s:%s", globalConfig.Tracing.JaegerTracing.SamplingServerHost, globalConfig.Tracing.JaegerTracing.SamplingServerPort)
   204  	}
   205  
   206  	jaegerExporter, err := jaeger.NewExporter(jaeger.Options{
   207  		AgentEndpoint: jaegerURL,
   208  		ServiceName:   globalConfig.Tracing.ServiceName,
   209  	})
   210  	if err != nil {
   211  		log.WithError(err).Warn("Failed to create jaeger exporter")
   212  	} else {
   213  		trace.RegisterExporter(jaegerExporter)
   214  	}
   215  	return err
   216  }