| // Copyright 2015 The etcd 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 mvcc |
| |
| import ( |
| "sync" |
| |
| "github.com/prometheus/client_golang/prometheus" |
| ) |
| |
| var ( |
| rangeCounter = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "range_total", |
| Help: "Total number of ranges seen by this member.", |
| }) |
| rangeCounterDebug = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "range_total", |
| Help: "Total number of ranges seen by this member.", |
| }) |
| |
| putCounter = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "put_total", |
| Help: "Total number of puts seen by this member.", |
| }) |
| // TODO: remove in 3.5 release |
| putCounterDebug = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "put_total", |
| Help: "Total number of puts seen by this member.", |
| }) |
| |
| deleteCounter = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "delete_total", |
| Help: "Total number of deletes seen by this member.", |
| }) |
| // TODO: remove in 3.5 release |
| deleteCounterDebug = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "delete_total", |
| Help: "Total number of deletes seen by this member.", |
| }) |
| |
| txnCounter = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "txn_total", |
| Help: "Total number of txns seen by this member.", |
| }) |
| txnCounterDebug = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "txn_total", |
| Help: "Total number of txns seen by this member.", |
| }) |
| |
| keysGauge = prometheus.NewGauge( |
| prometheus.GaugeOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "keys_total", |
| Help: "Total number of keys.", |
| }) |
| |
| watchStreamGauge = prometheus.NewGauge( |
| prometheus.GaugeOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "watch_stream_total", |
| Help: "Total number of watch streams.", |
| }) |
| |
| watcherGauge = prometheus.NewGauge( |
| prometheus.GaugeOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "watcher_total", |
| Help: "Total number of watchers.", |
| }) |
| |
| slowWatcherGauge = prometheus.NewGauge( |
| prometheus.GaugeOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "slow_watcher_total", |
| Help: "Total number of unsynced slow watchers.", |
| }) |
| |
| totalEventsCounter = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "events_total", |
| Help: "Total number of events sent by this member.", |
| }) |
| |
| pendingEventsGauge = prometheus.NewGauge( |
| prometheus.GaugeOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "pending_events_total", |
| Help: "Total number of pending events to be sent.", |
| }) |
| |
| indexCompactionPauseMs = prometheus.NewHistogram( |
| prometheus.HistogramOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "index_compaction_pause_duration_milliseconds", |
| Help: "Bucketed histogram of index compaction pause duration.", |
| |
| // lowest bucket start of upper bound 0.5 ms with factor 2 |
| // highest bucket start of 0.5 ms * 2^13 == 4.096 sec |
| Buckets: prometheus.ExponentialBuckets(0.5, 2, 14), |
| }) |
| |
| dbCompactionPauseMs = prometheus.NewHistogram( |
| prometheus.HistogramOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "db_compaction_pause_duration_milliseconds", |
| Help: "Bucketed histogram of db compaction pause duration.", |
| |
| // lowest bucket start of upper bound 1 ms with factor 2 |
| // highest bucket start of 1 ms * 2^12 == 4.096 sec |
| Buckets: prometheus.ExponentialBuckets(1, 2, 13), |
| }) |
| |
| dbCompactionTotalMs = prometheus.NewHistogram( |
| prometheus.HistogramOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "db_compaction_total_duration_milliseconds", |
| Help: "Bucketed histogram of db compaction total duration.", |
| |
| // lowest bucket start of upper bound 100 ms with factor 2 |
| // highest bucket start of 100 ms * 2^13 == 8.192 sec |
| Buckets: prometheus.ExponentialBuckets(100, 2, 14), |
| }) |
| |
| dbCompactionKeysCounter = prometheus.NewCounter( |
| prometheus.CounterOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "db_compaction_keys_total", |
| Help: "Total number of db keys compacted.", |
| }) |
| |
| dbTotalSize = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "db_total_size_in_bytes", |
| Help: "Total size of the underlying database physically allocated in bytes.", |
| }, |
| func() float64 { |
| reportDbTotalSizeInBytesMu.RLock() |
| defer reportDbTotalSizeInBytesMu.RUnlock() |
| return reportDbTotalSizeInBytes() |
| }, |
| ) |
| // overridden by mvcc initialization |
| reportDbTotalSizeInBytesMu sync.RWMutex |
| reportDbTotalSizeInBytes = func() float64 { return 0 } |
| |
| // TODO: remove this in v3.5 |
| dbTotalSizeDebug = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "db_total_size_in_bytes", |
| Help: "Total size of the underlying database physically allocated in bytes.", |
| }, |
| func() float64 { |
| reportDbTotalSizeInBytesDebugMu.RLock() |
| defer reportDbTotalSizeInBytesDebugMu.RUnlock() |
| return reportDbTotalSizeInBytesDebug() |
| }, |
| ) |
| // overridden by mvcc initialization |
| reportDbTotalSizeInBytesDebugMu sync.RWMutex |
| reportDbTotalSizeInBytesDebug = func() float64 { return 0 } |
| |
| dbTotalSizeInUse = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "db_total_size_in_use_in_bytes", |
| Help: "Total size of the underlying database logically in use in bytes.", |
| }, |
| func() float64 { |
| reportDbTotalSizeInUseInBytesMu.RLock() |
| defer reportDbTotalSizeInUseInBytesMu.RUnlock() |
| return reportDbTotalSizeInUseInBytes() |
| }, |
| ) |
| // overridden by mvcc initialization |
| reportDbTotalSizeInUseInBytesMu sync.RWMutex |
| reportDbTotalSizeInUseInBytes = func() float64 { return 0 } |
| |
| dbOpenReadTxN = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "db_open_read_transactions", |
| Help: "The number of currently open read transactions", |
| }, |
| |
| func() float64 { |
| reportDbOpenReadTxNMu.RLock() |
| defer reportDbOpenReadTxNMu.RUnlock() |
| return reportDbOpenReadTxN() |
| }, |
| ) |
| // overridden by mvcc initialization |
| reportDbOpenReadTxNMu sync.RWMutex |
| reportDbOpenReadTxN = func() float64 { return 0 } |
| |
| hashSec = prometheus.NewHistogram(prometheus.HistogramOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "hash_duration_seconds", |
| Help: "The latency distribution of storage hash operation.", |
| |
| // 100 MB usually takes 100 ms, so start with 10 MB of 10 ms |
| // lowest bucket start of upper bound 0.01 sec (10 ms) with factor 2 |
| // highest bucket start of 0.01 sec * 2^14 == 163.84 sec |
| Buckets: prometheus.ExponentialBuckets(.01, 2, 15), |
| }) |
| |
| hashRevSec = prometheus.NewHistogram(prometheus.HistogramOpts{ |
| Namespace: "etcd", |
| Subsystem: "mvcc", |
| Name: "hash_rev_duration_seconds", |
| Help: "The latency distribution of storage hash by revision operation.", |
| |
| // 100 MB usually takes 100 ms, so start with 10 MB of 10 ms |
| // lowest bucket start of upper bound 0.01 sec (10 ms) with factor 2 |
| // highest bucket start of 0.01 sec * 2^14 == 163.84 sec |
| Buckets: prometheus.ExponentialBuckets(.01, 2, 15), |
| }) |
| |
| currentRev = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "current_revision", |
| Help: "The current revision of store.", |
| }, |
| func() float64 { |
| reportCurrentRevMu.RLock() |
| defer reportCurrentRevMu.RUnlock() |
| return reportCurrentRev() |
| }, |
| ) |
| // overridden by mvcc initialization |
| reportCurrentRevMu sync.RWMutex |
| reportCurrentRev = func() float64 { return 0 } |
| |
| compactRev = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ |
| Namespace: "etcd_debugging", |
| Subsystem: "mvcc", |
| Name: "compact_revision", |
| Help: "The revision of the last compaction in store.", |
| }, |
| func() float64 { |
| reportCompactRevMu.RLock() |
| defer reportCompactRevMu.RUnlock() |
| return reportCompactRev() |
| }, |
| ) |
| // overridden by mvcc initialization |
| reportCompactRevMu sync.RWMutex |
| reportCompactRev = func() float64 { return 0 } |
| ) |
| |
| func init() { |
| prometheus.MustRegister(rangeCounter) |
| prometheus.MustRegister(rangeCounterDebug) |
| prometheus.MustRegister(putCounter) |
| prometheus.MustRegister(putCounterDebug) |
| prometheus.MustRegister(deleteCounter) |
| prometheus.MustRegister(deleteCounterDebug) |
| prometheus.MustRegister(txnCounter) |
| prometheus.MustRegister(txnCounterDebug) |
| prometheus.MustRegister(keysGauge) |
| prometheus.MustRegister(watchStreamGauge) |
| prometheus.MustRegister(watcherGauge) |
| prometheus.MustRegister(slowWatcherGauge) |
| prometheus.MustRegister(totalEventsCounter) |
| prometheus.MustRegister(pendingEventsGauge) |
| prometheus.MustRegister(indexCompactionPauseMs) |
| prometheus.MustRegister(dbCompactionPauseMs) |
| prometheus.MustRegister(dbCompactionTotalMs) |
| prometheus.MustRegister(dbCompactionKeysCounter) |
| prometheus.MustRegister(dbTotalSize) |
| prometheus.MustRegister(dbTotalSizeDebug) |
| prometheus.MustRegister(dbTotalSizeInUse) |
| prometheus.MustRegister(dbOpenReadTxN) |
| prometheus.MustRegister(hashSec) |
| prometheus.MustRegister(hashRevSec) |
| prometheus.MustRegister(currentRev) |
| prometheus.MustRegister(compactRev) |
| } |
| |
| // ReportEventReceived reports that an event is received. |
| // This function should be called when the external systems received an |
| // event from mvcc.Watcher. |
| func ReportEventReceived(n int) { |
| pendingEventsGauge.Sub(float64(n)) |
| totalEventsCounter.Add(float64(n)) |
| } |