diff --git a/cmd/prometheus/config.go b/cmd/prometheus/config.go index 8d8a9f8fe..2442c4269 100644 --- a/cmd/prometheus/config.go +++ b/cmd/prometheus/config.go @@ -43,11 +43,12 @@ var cfg = struct { printVersion bool configFile string - storage local.MemorySeriesStorageOptions - notifier notifier.Options - queryEngine promql.EngineOptions - web web.Options - remote remote.Options + storage local.MemorySeriesStorageOptions + localStorageEngine string + notifier notifier.Options + queryEngine promql.EngineOptions + web web.Options + remote remote.Options alertmanagerURLs stringset prometheusURL string @@ -172,6 +173,10 @@ func init() { &cfg.storage.NumMutexes, "storage.local.num-fingerprint-mutexes", 4096, "The number of mutexes used for fingerprint locking.", ) + cfg.fs.StringVar( + &cfg.localStorageEngine, "storage.local.engine", "persisted", + "Local storage engine. Supported values are: 'persisted' (full local storage with on-disk persistence) and 'none' (no local storage).", + ) // Remote storage. cfg.fs.StringVar( diff --git a/cmd/prometheus/main.go b/cmd/prometheus/main.go index db093dd32..bbb99e373 100644 --- a/cmd/prometheus/main.go +++ b/cmd/prometheus/main.go @@ -73,13 +73,23 @@ func Main() int { log.Infoln("Starting prometheus", version.Info()) log.Infoln("Build context", version.BuildContext()) - var reloadables []Reloadable - var ( - memStorage = local.NewMemorySeriesStorage(&cfg.storage) - sampleAppender = storage.Fanout{memStorage} + sampleAppender = storage.Fanout{} + reloadables []Reloadable ) + var localStorage local.Storage + switch cfg.localStorageEngine { + case "persisted": + localStorage = local.NewMemorySeriesStorage(&cfg.storage) + sampleAppender = storage.Fanout{localStorage} + case "none": + localStorage = &local.NoopStorage{} + default: + log.Errorf("Invalid local storage engine %q", cfg.localStorageEngine) + return 1 + } + remoteStorage, err := remote.New(&cfg.remote) if err != nil { log.Errorf("Error initializing remote storage: %s", err) @@ -94,7 +104,7 @@ func Main() int { var ( notifier = notifier.New(&cfg.notifier) targetManager = retrieval.NewTargetManager(sampleAppender) - queryEngine = promql.NewEngine(memStorage, &cfg.queryEngine) + queryEngine = promql.NewEngine(localStorage, &cfg.queryEngine) ) ruleManager := rules.NewManager(&rules.ManagerOptions{ @@ -118,7 +128,7 @@ func Main() int { GoVersion: version.GoVersion, } - webHandler := web.New(memStorage, queryEngine, targetManager, ruleManager, version, flags, &cfg.web) + webHandler := web.New(localStorage, queryEngine, targetManager, ruleManager, version, flags, &cfg.web) reloadables = append(reloadables, targetManager, ruleManager, webHandler, notifier) @@ -154,12 +164,12 @@ func Main() int { // Start all components. The order is NOT arbitrary. - if err := memStorage.Start(); err != nil { + if err := localStorage.Start(); err != nil { log.Errorln("Error opening memory series storage:", err) return 1 } defer func() { - if err := memStorage.Stop(); err != nil { + if err := localStorage.Stop(); err != nil { log.Errorln("Error stopping storage:", err) } }() @@ -171,7 +181,9 @@ func Main() int { defer remoteStorage.Stop() } // The storage has to be fully initialized before registering. - prometheus.MustRegister(memStorage) + if instrumentedStorage, ok := localStorage.(prometheus.Collector); ok { + prometheus.MustRegister(instrumentedStorage) + } prometheus.MustRegister(notifier) prometheus.MustRegister(configSuccess) prometheus.MustRegister(configSuccessTime) diff --git a/storage/local/noop_storage.go b/storage/local/noop_storage.go new file mode 100644 index 000000000..4832f8f45 --- /dev/null +++ b/storage/local/noop_storage.go @@ -0,0 +1,82 @@ +// Copyright 2016 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. + +package local + +import ( + "time" + + "github.com/prometheus/common/model" + "github.com/prometheus/prometheus/storage/metric" +) + +// NoopStorage is a dummy storage for use when Prometheus's local storage is +// disabled. It throws away any appended samples and returns empty results. +type NoopStorage struct{} + +// Start implements Storage. +func (s *NoopStorage) Start() (err error) { + return nil +} + +// Stop implements Storage. +func (s *NoopStorage) Stop() error { + return nil +} + +// WaitForIndexing implements Storage. +func (s *NoopStorage) WaitForIndexing() { +} + +// LastSampleForLabelMatchers implements Storage. +func (s *NoopStorage) LastSampleForLabelMatchers(cutoff model.Time, matcherSets ...metric.LabelMatchers) (model.Vector, error) { + return nil, nil +} + +// QueryRange implements Storage. +func (s *NoopStorage) QueryRange(from, through model.Time, matchers ...*metric.LabelMatcher) ([]SeriesIterator, error) { + return nil, nil +} + +// QueryInstant implements Storage. +func (s *NoopStorage) QueryInstant(ts model.Time, stalenessDelta time.Duration, matchers ...*metric.LabelMatcher) ([]SeriesIterator, error) { + return nil, nil +} + +// MetricsForLabelMatchers implements Storage. +func (s *NoopStorage) MetricsForLabelMatchers( + from, through model.Time, + matcherSets ...metric.LabelMatchers, +) ([]metric.Metric, error) { + return nil, nil +} + +// LabelValuesForLabelName implements Storage. +func (s *NoopStorage) LabelValuesForLabelName(labelName model.LabelName) (model.LabelValues, error) { + return nil, nil +} + +// DropMetricsForLabelMatchers implements Storage. +func (s *NoopStorage) DropMetricsForLabelMatchers(matchers ...*metric.LabelMatcher) (int, error) { + return 0, nil +} + +// Append implements Storage. +func (s *NoopStorage) Append(sample *model.Sample) error { + return nil +} + +// NeedsThrottling implements Storage. +func (s *NoopStorage) NeedsThrottling() bool { + return false +}