| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | // Copyright 2015 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-18 06:52:44 +08:00
										 |  |  | // The main package for the Prometheus server executable.
 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"flag" | 
					
						
							| 
									
										
										
										
											2015-06-15 18:23:02 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	_ "net/http/pprof" // Comment this line to disable pprof endpoint.
 | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/signal" | 
					
						
							|  |  |  | 	"syscall" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-24 00:04:04 +08:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							| 
									
										
										
										
											2016-05-05 19:46:51 +08:00
										 |  |  | 	"github.com/prometheus/common/log" | 
					
						
							|  |  |  | 	"github.com/prometheus/common/version" | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/config" | 
					
						
							| 
									
										
										
										
											2016-03-01 19:37:22 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/notifier" | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/promql" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/retrieval" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/rules" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/storage" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/storage/local" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/storage/remote" | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/web" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func main() { | 
					
						
							|  |  |  | 	os.Exit(Main()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-02 01:18:39 +08:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	configSuccess = prometheus.NewGauge(prometheus.GaugeOpts{ | 
					
						
							|  |  |  | 		Namespace: "prometheus", | 
					
						
							|  |  |  | 		Name:      "config_last_reload_successful", | 
					
						
							|  |  |  | 		Help:      "Whether the last configuration reload attempt was successful.", | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	configSuccessTime = prometheus.NewGauge(prometheus.GaugeOpts{ | 
					
						
							|  |  |  | 		Namespace: "prometheus", | 
					
						
							|  |  |  | 		Name:      "config_last_reload_success_timestamp_seconds", | 
					
						
							|  |  |  | 		Help:      "Timestamp of the last successful configuration reload.", | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-05 19:46:51 +08:00
										 |  |  | func init() { | 
					
						
							|  |  |  | 	prometheus.MustRegister(version.NewCollector("prometheus")) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-24 21:07:27 +08:00
										 |  |  | // Main manages the startup and shutdown lifecycle of the entire Prometheus server.
 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | func Main() int { | 
					
						
							|  |  |  | 	if err := parse(os.Args[1:]); err != nil { | 
					
						
							| 
									
										
										
										
											2016-02-19 19:18:19 +08:00
										 |  |  | 		log.Error(err) | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 		return 2 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if cfg.printVersion { | 
					
						
							| 
									
										
										
										
											2016-05-05 19:46:51 +08:00
										 |  |  | 		fmt.Fprintln(os.Stdout, version.Print("prometheus")) | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 		return 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-05 19:46:51 +08:00
										 |  |  | 	log.Infoln("Starting prometheus", version.Info()) | 
					
						
							|  |  |  | 	log.Infoln("Build context", version.BuildContext()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-03 19:44:03 +08:00
										 |  |  | 	var reloadables []Reloadable | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2015-06-26 07:32:44 +08:00
										 |  |  | 		memStorage     = local.NewMemorySeriesStorage(&cfg.storage) | 
					
						
							|  |  |  | 		remoteStorage  = remote.New(&cfg.remote) | 
					
						
							|  |  |  | 		sampleAppender = storage.Fanout{memStorage} | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-06-24 00:04:04 +08:00
										 |  |  | 	if remoteStorage != nil { | 
					
						
							|  |  |  | 		sampleAppender = append(sampleAppender, remoteStorage) | 
					
						
							| 
									
										
										
										
											2015-09-03 19:44:03 +08:00
										 |  |  | 		reloadables = append(reloadables, remoteStorage) | 
					
						
							| 
									
										
										
										
											2015-06-24 00:04:04 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-26 07:32:44 +08:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2016-03-01 19:37:22 +08:00
										 |  |  | 		notifier      = notifier.New(&cfg.notifier) | 
					
						
							|  |  |  | 		targetManager = retrieval.NewTargetManager(sampleAppender) | 
					
						
							|  |  |  | 		queryEngine   = promql.NewEngine(memStorage, &cfg.queryEngine) | 
					
						
							| 
									
										
										
										
											2015-06-26 07:32:44 +08:00
										 |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	ruleManager := rules.NewManager(&rules.ManagerOptions{ | 
					
						
							| 
									
										
										
										
											2016-03-01 19:37:22 +08:00
										 |  |  | 		SampleAppender: sampleAppender, | 
					
						
							|  |  |  | 		Notifier:       notifier, | 
					
						
							|  |  |  | 		QueryEngine:    queryEngine, | 
					
						
							|  |  |  | 		ExternalURL:    cfg.web.ExternalURL, | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	flags := map[string]string{} | 
					
						
							|  |  |  | 	cfg.fs.VisitAll(func(f *flag.Flag) { | 
					
						
							|  |  |  | 		flags[f.Name] = f.Value.String() | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	status := &web.PrometheusStatus{ | 
					
						
							|  |  |  | 		TargetPools: targetManager.Pools, | 
					
						
							|  |  |  | 		Rules:       ruleManager.Rules, | 
					
						
							|  |  |  | 		Flags:       flags, | 
					
						
							|  |  |  | 		Birth:       time.Now(), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-05 19:46:51 +08:00
										 |  |  | 	version := &web.PrometheusVersion{ | 
					
						
							|  |  |  | 		Version:   version.Version, | 
					
						
							|  |  |  | 		Revision:  version.Revision, | 
					
						
							|  |  |  | 		Branch:    version.Branch, | 
					
						
							|  |  |  | 		BuildUser: version.BuildUser, | 
					
						
							|  |  |  | 		BuildDate: version.BuildDate, | 
					
						
							|  |  |  | 		GoVersion: version.GoVersion, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	webHandler := web.New(memStorage, queryEngine, ruleManager, status, version, &cfg.web) | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 19:37:22 +08:00
										 |  |  | 	reloadables = append(reloadables, status, targetManager, ruleManager, webHandler, notifier) | 
					
						
							| 
									
										
										
										
											2015-09-02 00:47:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if !reloadConfig(cfg.configFile, reloadables...) { | 
					
						
							| 
									
										
										
										
											2015-06-24 00:04:04 +08:00
										 |  |  | 		return 1 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Wait for reload or termination signals. Start the handler for SIGHUP as
 | 
					
						
							|  |  |  | 	// early as possible, but ignore it until we are ready to handle reloading
 | 
					
						
							|  |  |  | 	// our config.
 | 
					
						
							|  |  |  | 	hup := make(chan os.Signal) | 
					
						
							|  |  |  | 	hupReady := make(chan bool) | 
					
						
							|  |  |  | 	signal.Notify(hup, syscall.SIGHUP) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		<-hupReady | 
					
						
							| 
									
										
										
										
											2015-08-11 15:08:17 +08:00
										 |  |  | 		for { | 
					
						
							|  |  |  | 			select { | 
					
						
							|  |  |  | 			case <-hup: | 
					
						
							|  |  |  | 			case <-webHandler.Reload(): | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-09-02 00:47:48 +08:00
										 |  |  | 			reloadConfig(cfg.configFile, reloadables...) | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-18 23:47:31 +08:00
										 |  |  | 	// Start all components. The order is NOT arbitrary.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	if err := memStorage.Start(); err != nil { | 
					
						
							|  |  |  | 		log.Errorln("Error opening memory series storage:", err) | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err := memStorage.Stop(); err != nil { | 
					
						
							|  |  |  | 			log.Errorln("Error stopping storage:", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-24 00:04:04 +08:00
										 |  |  | 	if remoteStorage != nil { | 
					
						
							|  |  |  | 		prometheus.MustRegister(remoteStorage) | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-24 00:04:04 +08:00
										 |  |  | 		go remoteStorage.Run() | 
					
						
							|  |  |  | 		defer remoteStorage.Stop() | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-24 00:04:04 +08:00
										 |  |  | 	// The storage has to be fully initialized before registering.
 | 
					
						
							|  |  |  | 	prometheus.MustRegister(memStorage) | 
					
						
							| 
									
										
										
										
											2016-03-01 19:37:22 +08:00
										 |  |  | 	prometheus.MustRegister(notifier) | 
					
						
							| 
									
										
										
										
											2015-09-02 01:18:39 +08:00
										 |  |  | 	prometheus.MustRegister(configSuccess) | 
					
						
							|  |  |  | 	prometheus.MustRegister(configSuccessTime) | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 19:37:22 +08:00
										 |  |  | 	// The notifieris a dependency of the rule manager. It has to be
 | 
					
						
							| 
									
										
										
										
											2016-01-18 23:47:31 +08:00
										 |  |  | 	// started before and torn down afterwards.
 | 
					
						
							| 
									
										
										
										
											2016-03-01 19:37:22 +08:00
										 |  |  | 	go notifier.Run() | 
					
						
							|  |  |  | 	defer notifier.Stop() | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-18 23:47:31 +08:00
										 |  |  | 	go ruleManager.Run() | 
					
						
							|  |  |  | 	defer ruleManager.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	go targetManager.Run() | 
					
						
							|  |  |  | 	defer targetManager.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-18 23:47:31 +08:00
										 |  |  | 	// Shutting down the query engine before the rule manager will cause pending queries
 | 
					
						
							|  |  |  | 	// to be canceled and ensures a quick shutdown of the rule manager.
 | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	defer queryEngine.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go webHandler.Run() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Wait for reload or termination signals.
 | 
					
						
							|  |  |  | 	close(hupReady) // Unblock SIGHUP handler.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	term := make(chan os.Signal) | 
					
						
							|  |  |  | 	signal.Notify(term, os.Interrupt, syscall.SIGTERM) | 
					
						
							|  |  |  | 	select { | 
					
						
							|  |  |  | 	case <-term: | 
					
						
							|  |  |  | 		log.Warn("Received SIGTERM, exiting gracefully...") | 
					
						
							|  |  |  | 	case <-webHandler.Quit(): | 
					
						
							|  |  |  | 		log.Warn("Received termination request via web service, exiting gracefully...") | 
					
						
							| 
									
										
										
										
											2015-08-21 00:23:57 +08:00
										 |  |  | 	case err := <-webHandler.ListenError(): | 
					
						
							|  |  |  | 		log.Errorln("Error starting web server, exiting gracefully:", err) | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	log.Info("See you next time!") | 
					
						
							|  |  |  | 	return 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Reloadable things can change their internal state to match a new config
 | 
					
						
							|  |  |  | // and handle failure gracefully.
 | 
					
						
							|  |  |  | type Reloadable interface { | 
					
						
							|  |  |  | 	ApplyConfig(*config.Config) bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-02 01:18:39 +08:00
										 |  |  | func reloadConfig(filename string, rls ...Reloadable) (success bool) { | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	log.Infof("Loading configuration file %s", filename) | 
					
						
							| 
									
										
										
										
											2015-09-02 01:18:39 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if success { | 
					
						
							|  |  |  | 			configSuccess.Set(1) | 
					
						
							|  |  |  | 			configSuccessTime.Set(float64(time.Now().Unix())) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			configSuccess.Set(0) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-06 00:30:37 +08:00
										 |  |  | 	conf, err := config.LoadFile(filename) | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Errorf("Couldn't load configuration (-config.file=%s): %v", filename, err) | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-02 01:18:39 +08:00
										 |  |  | 	success = true | 
					
						
							| 
									
										
										
										
											2015-06-15 18:36:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for _, rl := range rls { | 
					
						
							|  |  |  | 		success = success && rl.ApplyConfig(conf) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return success | 
					
						
							|  |  |  | } |