func main() { flag.Parse() conf, err := config.LoadFromFile(*configFile) if err != nil { log.Fatalf("Error loading configuration from %s: %v", *configFile, err) } ts, err := metric.NewTieredStorage(5000, 5000, 100, time.Second*30, time.Second*1, time.Second*20, *metricsStoragePath) if err != nil { log.Fatalf("Error opening storage: %s", err) } go ts.Serve() go func() { notifier := make(chan os.Signal) signal.Notify(notifier, os.Interrupt) <-notifier ts.Close() os.Exit(0) }() // Queue depth will need to be exposed scrapeResults := make(chan format.Result, *scrapeResultsQueueCapacity) targetManager := retrieval.NewTargetManager(scrapeResults, *concurrentRetrievalAllowance) targetManager.AddTargetsFromConfig(conf) ruleResults := make(chan *rules.Result, *ruleResultsQueueCapacity) ast.SetStorage(ts) ruleManager := rules.NewRuleManager(ruleResults, conf.Global.EvaluationInterval) err = ruleManager.AddRulesFromConfig(conf) if err != nil { log.Fatalf("Error loading rule files: %v", err) } appState := &appstate.ApplicationState{ Config: conf, RuleManager: ruleManager, Storage: ts, TargetManager: targetManager, } web.StartServing(appState) for { select { case scrapeResult := <-scrapeResults: if scrapeResult.Err == nil { ts.AppendSample(scrapeResult.Sample) } case ruleResult := <-ruleResults: for _, sample := range ruleResult.Samples { ts.AppendSample(sample) } } } }
func reloadConfig(filename string, rls ...Reloadable) bool { log.Infof("Loading configuration file %s", filename) conf, err := config.LoadFromFile(filename) if err != nil { log.Errorf("Couldn't load configuration (-config.file=%s): %v", filename, err) log.Errorf("Note: The configuration format has changed with version 0.14. Please see the documentation (http://prometheus.io/docs/operating/configuration/) and the provided configuration migration tool (https://github.com/prometheus/migrate).") return false } success := true for _, rl := range rls { success = success && rl.ApplyConfig(conf) } return success }
// NewPrometheus creates a new prometheus object based on flag values. // Call Serve() to start serving and Close() for clean shutdown. func NewPrometheus() *prometheus { conf, err := config.LoadFromFile(*configFile) if err != nil { glog.Fatalf("Error loading configuration from %s: %v", *configFile, err) } unwrittenSamples := make(chan clientmodel.Samples, *samplesQueueCapacity) ingester := &retrieval.MergeLabelsIngester{ Labels: conf.GlobalLabels(), CollisionPrefix: clientmodel.ExporterLabelPrefix, Ingester: retrieval.ChannelIngester(unwrittenSamples), } targetManager := retrieval.NewTargetManager(ingester) targetManager.AddTargetsFromConfig(conf) notificationHandler := notification.NewNotificationHandler(*alertmanagerURL, *notificationQueueCapacity) o := &local.MemorySeriesStorageOptions{ MemoryChunks: *numMemoryChunks, PersistenceStoragePath: *metricsStoragePath, PersistenceRetentionPeriod: *storageRetentionPeriod, CheckpointInterval: *checkpointInterval, CheckpointDirtySeriesLimit: *checkpointDirtySeriesLimit, Dirty: *storageDirty, } memStorage, err := local.NewMemorySeriesStorage(o) if err != nil { glog.Fatal("Error opening memory series storage: ", err) } ruleManager := manager.NewRuleManager(&manager.RuleManagerOptions{ Results: unwrittenSamples, NotificationHandler: notificationHandler, EvaluationInterval: conf.EvaluationInterval(), Storage: memStorage, PrometheusURL: web.MustBuildServerURL(), }) if err := ruleManager.AddRulesFromConfig(conf); err != nil { glog.Fatal("Error loading rule files: ", err) } var remoteTSDBQueue *remote.TSDBQueueManager if *remoteTSDBUrl == "" { glog.Warningf("No TSDB URL provided; not sending any samples to long-term storage") } else { openTSDB := opentsdb.NewClient(*remoteTSDBUrl, *remoteTSDBTimeout) remoteTSDBQueue = remote.NewTSDBQueueManager(openTSDB, 512) } flags := map[string]string{} flag.VisitAll(func(f *flag.Flag) { flags[f.Name] = f.Value.String() }) prometheusStatus := &web.PrometheusStatusHandler{ BuildInfo: BuildInfo, Config: conf.String(), RuleManager: ruleManager, TargetPools: targetManager.Pools(), Flags: flags, Birth: time.Now(), } alertsHandler := &web.AlertsHandler{ RuleManager: ruleManager, } consolesHandler := &web.ConsolesHandler{ Storage: memStorage, } metricsService := &api.MetricsService{ Config: &conf, TargetManager: targetManager, Storage: memStorage, } webService := &web.WebService{ StatusHandler: prometheusStatus, MetricsHandler: metricsService, ConsolesHandler: consolesHandler, AlertsHandler: alertsHandler, } p := &prometheus{ unwrittenSamples: unwrittenSamples, ruleManager: ruleManager, targetManager: targetManager, notificationHandler: notificationHandler, storage: memStorage, remoteTSDBQueue: remoteTSDBQueue, webService: webService, } webService.QuitDelegate = p.Close return p }
func main() { // TODO(all): Future additions to main should be, where applicable, glumped // into the prometheus struct above---at least where the scoping of the entire // server is concerned. flag.Parse() versionInfoTmpl.Execute(os.Stdout, BuildInfo) if *printVersion { os.Exit(0) } conf, err := config.LoadFromFile(*configFile) if err != nil { glog.Fatalf("Error loading configuration from %s: %v", *configFile, err) } ts, err := tiered.NewTieredStorage(uint(*diskAppendQueueCapacity), 100, *arenaFlushInterval, *arenaTTL, *metricsStoragePath) if err != nil { glog.Fatal("Error opening storage: ", err) } var remoteTSDBQueue *remote.TSDBQueueManager = nil if *remoteTSDBUrl == "" { glog.Warningf("No TSDB URL provided; not sending any samples to long-term storage") } else { openTSDB := opentsdb.NewClient(*remoteTSDBUrl, *remoteTSDBTimeout) remoteTSDBQueue = remote.NewTSDBQueueManager(openTSDB, 512) go remoteTSDBQueue.Run() } unwrittenSamples := make(chan *extraction.Result, *samplesQueueCapacity) ingester := &retrieval.MergeLabelsIngester{ Labels: conf.GlobalLabels(), CollisionPrefix: clientmodel.ExporterLabelPrefix, Ingester: retrieval.ChannelIngester(unwrittenSamples), } compactionTimer := time.NewTicker(*compactInterval) deletionTimer := time.NewTicker(*deleteInterval) // Queue depth will need to be exposed targetManager := retrieval.NewTargetManager(ingester, *concurrentRetrievalAllowance) targetManager.AddTargetsFromConfig(conf) notifications := make(chan notification.NotificationReqs, *notificationQueueCapacity) // Queue depth will need to be exposed ruleManager := rules.NewRuleManager(&rules.RuleManagerOptions{ Results: unwrittenSamples, Notifications: notifications, EvaluationInterval: conf.EvaluationInterval(), Storage: ts, PrometheusUrl: web.MustBuildServerUrl(), }) if err := ruleManager.AddRulesFromConfig(conf); err != nil { glog.Fatal("Error loading rule files: ", err) } go ruleManager.Run() notificationHandler := notification.NewNotificationHandler(*alertmanagerUrl, notifications) go notificationHandler.Run() flags := map[string]string{} flag.VisitAll(func(f *flag.Flag) { flags[f.Name] = f.Value.String() }) prometheusStatus := &web.PrometheusStatusHandler{ BuildInfo: BuildInfo, Config: conf.String(), RuleManager: ruleManager, TargetPools: targetManager.Pools(), Flags: flags, Birth: time.Now(), } alertsHandler := &web.AlertsHandler{ RuleManager: ruleManager, } databasesHandler := &web.DatabasesHandler{ Provider: ts.DiskStorage, RefreshInterval: 5 * time.Minute, } metricsService := &api.MetricsService{ Config: &conf, TargetManager: targetManager, Storage: ts, } prometheus := &prometheus{ compactionTimer: compactionTimer, deletionTimer: deletionTimer, curationState: prometheusStatus, curationSema: make(chan struct{}, 1), unwrittenSamples: unwrittenSamples, stopBackgroundOperations: make(chan struct{}), ruleManager: ruleManager, targetManager: targetManager, notifications: notifications, storage: ts, remoteTSDBQueue: remoteTSDBQueue, } defer prometheus.Close() webService := &web.WebService{ StatusHandler: prometheusStatus, MetricsHandler: metricsService, DatabasesHandler: databasesHandler, AlertsHandler: alertsHandler, QuitDelegate: prometheus.Close, } prometheus.curationSema <- struct{}{} storageStarted := make(chan bool) go ts.Serve(storageStarted) <-storageStarted go prometheus.interruptHandler() go func() { for _ = range prometheus.compactionTimer.C { glog.Info("Starting compaction...") err := prometheus.compact(*compactAgeInclusiveness, *compactGroupSize) if err != nil { glog.Error("could not compact: ", err) } glog.Info("Done") } }() go func() { for _ = range prometheus.deletionTimer.C { glog.Info("Starting deletion of stale values...") err := prometheus.delete(*deleteAge, deletionBatchSize) if err != nil { glog.Error("could not delete: ", err) } glog.Info("Done") } }() go func() { err := webService.ServeForever() if err != nil { glog.Fatal(err) } }() // TODO(all): Migrate this into prometheus.serve(). for block := range unwrittenSamples { if block.Err == nil && len(block.Samples) > 0 { ts.AppendSamples(block.Samples) if remoteTSDBQueue != nil { remoteTSDBQueue.Queue(block.Samples) } } } }