mirror of
https://github.com/prometheus/prometheus
synced 2024-12-26 00:23:18 +00:00
Code Review: First pass.
This commit is contained in:
parent
d8792cfd86
commit
07ac921aec
45
main.go
45
main.go
@ -28,6 +28,7 @@ import (
|
||||
"github.com/prometheus/prometheus/retrieval"
|
||||
"github.com/prometheus/prometheus/rules"
|
||||
"github.com/prometheus/prometheus/storage/metric"
|
||||
|
||||
"github.com/prometheus/prometheus/web"
|
||||
"github.com/prometheus/prometheus/web/api"
|
||||
)
|
||||
@ -68,14 +69,13 @@ var (
|
||||
)
|
||||
|
||||
type prometheus struct {
|
||||
headCompactionTimer *time.Ticker
|
||||
bodyCompactionTimer *time.Ticker
|
||||
tailCompactionTimer *time.Ticker
|
||||
deletionTimer *time.Ticker
|
||||
reportDatabasesTimer *time.Ticker
|
||||
headCompactionTimer *time.Ticker
|
||||
bodyCompactionTimer *time.Ticker
|
||||
tailCompactionTimer *time.Ticker
|
||||
deletionTimer *time.Ticker
|
||||
|
||||
curationMutex sync.Mutex
|
||||
curationState chan metric.CurationState
|
||||
databaseStates chan []string
|
||||
stopBackgroundOperations chan bool
|
||||
|
||||
unwrittenSamples chan *extraction.Result
|
||||
@ -141,10 +141,6 @@ func (p *prometheus) close() {
|
||||
p.deletionTimer.Stop()
|
||||
}
|
||||
|
||||
if p.reportDatabasesTimer != nil {
|
||||
p.reportDatabasesTimer.Stop()
|
||||
}
|
||||
|
||||
if len(p.stopBackgroundOperations) == 0 {
|
||||
p.stopBackgroundOperations <- true
|
||||
}
|
||||
@ -157,26 +153,6 @@ func (p *prometheus) close() {
|
||||
close(p.notifications)
|
||||
close(p.stopBackgroundOperations)
|
||||
close(p.curationState)
|
||||
close(p.databaseStates)
|
||||
}
|
||||
|
||||
func (p *prometheus) reportDatabaseState() {
|
||||
for _ = range p.reportDatabasesTimer.C {
|
||||
// BUG(matt): Per Julius, ...
|
||||
// These channel magic tricks confuse me and seem a bit awkward just to
|
||||
// pass a status around. Now that we have Go 1.1, would it be maybe be
|
||||
// nicer to pass ts.DiskStorage.States as a method value
|
||||
// (http://tip.golang.org/ref/spec#Method_values) to the web layer
|
||||
// instead of doing this?
|
||||
select {
|
||||
case <-p.databaseStates:
|
||||
// Reset the future database state if nobody consumes it.
|
||||
case p.databaseStates <- p.storage.DiskStorage.States():
|
||||
// Set the database state so someone can consume it if they want.
|
||||
default:
|
||||
// Don't block.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -206,7 +182,6 @@ func main() {
|
||||
|
||||
unwrittenSamples := make(chan *extraction.Result, *samplesQueueCapacity)
|
||||
curationState := make(chan metric.CurationState, 1)
|
||||
databaseStates := make(chan []string, 1)
|
||||
// Coprime numbers, fool!
|
||||
headCompactionTimer := time.NewTicker(*headCompactInterval)
|
||||
bodyCompactionTimer := time.NewTicker(*bodyCompactInterval)
|
||||
@ -254,7 +229,7 @@ func main() {
|
||||
}
|
||||
|
||||
databasesHandler := &web.DatabasesHandler{
|
||||
Incoming: databaseStates,
|
||||
Provider: ts.DiskStorage,
|
||||
}
|
||||
|
||||
metricsService := &api.MetricsService{
|
||||
@ -277,10 +252,7 @@ func main() {
|
||||
|
||||
deletionTimer: deletionTimer,
|
||||
|
||||
reportDatabasesTimer: time.NewTicker(15 * time.Minute),
|
||||
|
||||
curationState: curationState,
|
||||
databaseStates: databaseStates,
|
||||
curationState: curationState,
|
||||
|
||||
unwrittenSamples: unwrittenSamples,
|
||||
|
||||
@ -297,7 +269,6 @@ func main() {
|
||||
<-storageStarted
|
||||
|
||||
go prometheus.interruptHandler()
|
||||
go prometheus.reportDatabaseState()
|
||||
|
||||
go func() {
|
||||
for _ = range prometheus.headCompactionTimer.C {
|
||||
|
@ -14,6 +14,7 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"code.google.com/p/goprotobuf/proto"
|
||||
@ -30,14 +31,16 @@ import (
|
||||
type FingerprintMetricMapping map[clientmodel.Fingerprint]clientmodel.Metric
|
||||
|
||||
type FingerprintMetricIndex interface {
|
||||
io.Closer
|
||||
raw.Pruner
|
||||
|
||||
IndexBatch(FingerprintMetricMapping) error
|
||||
Lookup(*clientmodel.Fingerprint) (m clientmodel.Metric, ok bool, err error)
|
||||
Close() error
|
||||
State() string
|
||||
State() *raw.DatabaseState
|
||||
Size() (s uint64, present bool, err error)
|
||||
}
|
||||
|
||||
type leveldbFingerprintMetricIndex struct {
|
||||
type LeveldbFingerprintMetricIndex struct {
|
||||
p *leveldb.LevelDBPersistence
|
||||
}
|
||||
|
||||
@ -45,22 +48,22 @@ type LevelDBFingerprintMetricIndexOptions struct {
|
||||
leveldb.LevelDBOptions
|
||||
}
|
||||
|
||||
func (i *leveldbFingerprintMetricIndex) Close() error {
|
||||
func (i *LeveldbFingerprintMetricIndex) Close() error {
|
||||
i.p.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *leveldbFingerprintMetricIndex) State() string {
|
||||
func (i *LeveldbFingerprintMetricIndex) State() *raw.DatabaseState {
|
||||
return i.p.State()
|
||||
}
|
||||
|
||||
func (i *leveldbFingerprintMetricIndex) Size() (uint64, bool, error) {
|
||||
func (i *LeveldbFingerprintMetricIndex) Size() (uint64, bool, error) {
|
||||
s, err := i.p.ApproximateSize()
|
||||
return s, true, err
|
||||
}
|
||||
|
||||
func (i *leveldbFingerprintMetricIndex) IndexBatch(mapping FingerprintMetricMapping) error {
|
||||
func (i *LeveldbFingerprintMetricIndex) IndexBatch(mapping FingerprintMetricMapping) error {
|
||||
b := leveldb.NewBatch()
|
||||
defer b.Close()
|
||||
|
||||
@ -76,7 +79,7 @@ func (i *leveldbFingerprintMetricIndex) IndexBatch(mapping FingerprintMetricMapp
|
||||
return i.p.Commit(b)
|
||||
}
|
||||
|
||||
func (i *leveldbFingerprintMetricIndex) Lookup(f *clientmodel.Fingerprint) (m clientmodel.Metric, ok bool, err error) {
|
||||
func (i *LeveldbFingerprintMetricIndex) Lookup(f *clientmodel.Fingerprint) (m clientmodel.Metric, ok bool, err error) {
|
||||
k := new(dto.Fingerprint)
|
||||
dumpFingerprint(k, f)
|
||||
v := new(dto.Metric)
|
||||
@ -95,13 +98,19 @@ func (i *leveldbFingerprintMetricIndex) Lookup(f *clientmodel.Fingerprint) (m cl
|
||||
return m, true, nil
|
||||
}
|
||||
|
||||
func (i *LeveldbFingerprintMetricIndex) Prune() (bool, error) {
|
||||
i.p.Prune()
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func NewLevelDBFingerprintMetricIndex(o *LevelDBFingerprintMetricIndexOptions) (FingerprintMetricIndex, error) {
|
||||
s, err := leveldb.NewLevelDBPersistence(&o.LevelDBOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &leveldbFingerprintMetricIndex{
|
||||
return &LeveldbFingerprintMetricIndex{
|
||||
p: s,
|
||||
}, nil
|
||||
}
|
||||
@ -109,19 +118,21 @@ func NewLevelDBFingerprintMetricIndex(o *LevelDBFingerprintMetricIndexOptions) (
|
||||
type LabelNameFingerprintMapping map[clientmodel.LabelName]clientmodel.Fingerprints
|
||||
|
||||
type LabelNameFingerprintIndex interface {
|
||||
io.Closer
|
||||
raw.Pruner
|
||||
|
||||
IndexBatch(LabelNameFingerprintMapping) error
|
||||
Lookup(clientmodel.LabelName) (fps clientmodel.Fingerprints, ok bool, err error)
|
||||
Has(clientmodel.LabelName) (ok bool, err error)
|
||||
Close() error
|
||||
State() string
|
||||
State() *raw.DatabaseState
|
||||
Size() (s uint64, present bool, err error)
|
||||
}
|
||||
|
||||
type leveldbLabelNameFingerprintIndex struct {
|
||||
type LeveldbLabelNameFingerprintIndex struct {
|
||||
p *leveldb.LevelDBPersistence
|
||||
}
|
||||
|
||||
func (i *leveldbLabelNameFingerprintIndex) IndexBatch(b LabelNameFingerprintMapping) error {
|
||||
func (i *LeveldbLabelNameFingerprintIndex) IndexBatch(b LabelNameFingerprintMapping) error {
|
||||
batch := leveldb.NewBatch()
|
||||
defer batch.Close()
|
||||
|
||||
@ -144,7 +155,7 @@ func (i *leveldbLabelNameFingerprintIndex) IndexBatch(b LabelNameFingerprintMapp
|
||||
return i.p.Commit(batch)
|
||||
}
|
||||
|
||||
func (i *leveldbLabelNameFingerprintIndex) Lookup(l clientmodel.LabelName) (fps clientmodel.Fingerprints, ok bool, err error) {
|
||||
func (i *LeveldbLabelNameFingerprintIndex) Lookup(l clientmodel.LabelName) (fps clientmodel.Fingerprints, ok bool, err error) {
|
||||
k := new(dto.LabelName)
|
||||
dumpLabelName(k, l)
|
||||
v := new(dto.FingerprintCollection)
|
||||
@ -165,24 +176,30 @@ func (i *leveldbLabelNameFingerprintIndex) Lookup(l clientmodel.LabelName) (fps
|
||||
return fps, true, nil
|
||||
}
|
||||
|
||||
func (i *leveldbLabelNameFingerprintIndex) Has(l clientmodel.LabelName) (ok bool, err error) {
|
||||
func (i *LeveldbLabelNameFingerprintIndex) Has(l clientmodel.LabelName) (ok bool, err error) {
|
||||
return i.p.Has(&dto.LabelName{
|
||||
Name: proto.String(string(l)),
|
||||
})
|
||||
}
|
||||
|
||||
func (i *leveldbLabelNameFingerprintIndex) Close() error {
|
||||
func (i *LeveldbLabelNameFingerprintIndex) Prune() (bool, error) {
|
||||
i.p.Prune()
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (i *LeveldbLabelNameFingerprintIndex) Close() error {
|
||||
i.p.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *leveldbLabelNameFingerprintIndex) Size() (uint64, bool, error) {
|
||||
func (i *LeveldbLabelNameFingerprintIndex) Size() (uint64, bool, error) {
|
||||
s, err := i.p.ApproximateSize()
|
||||
return s, true, err
|
||||
}
|
||||
|
||||
func (i *leveldbLabelNameFingerprintIndex) State() string {
|
||||
func (i *LeveldbLabelNameFingerprintIndex) State() *raw.DatabaseState {
|
||||
return i.p.State()
|
||||
}
|
||||
|
||||
@ -196,7 +213,7 @@ func NewLevelLabelNameFingerprintIndex(o *LevelDBLabelNameFingerprintIndexOption
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &leveldbLabelNameFingerprintIndex{
|
||||
return &LeveldbLabelNameFingerprintIndex{
|
||||
p: s,
|
||||
}, nil
|
||||
}
|
||||
@ -204,17 +221,18 @@ func NewLevelLabelNameFingerprintIndex(o *LevelDBLabelNameFingerprintIndexOption
|
||||
type LabelSetFingerprintMapping map[LabelPair]clientmodel.Fingerprints
|
||||
|
||||
type LabelSetFingerprintIndex interface {
|
||||
io.Closer
|
||||
raw.ForEacher
|
||||
raw.Pruner
|
||||
|
||||
IndexBatch(LabelSetFingerprintMapping) error
|
||||
Lookup(*LabelPair) (m clientmodel.Fingerprints, ok bool, err error)
|
||||
Has(*LabelPair) (ok bool, err error)
|
||||
Close() error
|
||||
State() string
|
||||
State() *raw.DatabaseState
|
||||
Size() (s uint64, present bool, err error)
|
||||
}
|
||||
|
||||
type leveldbLabelSetFingerprintIndex struct {
|
||||
type LeveldbLabelSetFingerprintIndex struct {
|
||||
p *leveldb.LevelDBPersistence
|
||||
}
|
||||
|
||||
@ -222,7 +240,7 @@ type LevelDBLabelSetFingerprintIndexOptions struct {
|
||||
leveldb.LevelDBOptions
|
||||
}
|
||||
|
||||
func (i *leveldbLabelSetFingerprintIndex) IndexBatch(m LabelSetFingerprintMapping) error {
|
||||
func (i *LeveldbLabelSetFingerprintIndex) IndexBatch(m LabelSetFingerprintMapping) error {
|
||||
batch := leveldb.NewBatch()
|
||||
defer batch.Close()
|
||||
|
||||
@ -246,7 +264,7 @@ func (i *leveldbLabelSetFingerprintIndex) IndexBatch(m LabelSetFingerprintMappin
|
||||
return i.p.Commit(batch)
|
||||
}
|
||||
|
||||
func (i *leveldbLabelSetFingerprintIndex) Lookup(p *LabelPair) (m clientmodel.Fingerprints, ok bool, err error) {
|
||||
func (i *LeveldbLabelSetFingerprintIndex) Lookup(p *LabelPair) (m clientmodel.Fingerprints, ok bool, err error) {
|
||||
k := &dto.LabelPair{
|
||||
Name: proto.String(string(p.Name)),
|
||||
Value: proto.String(string(p.Value)),
|
||||
@ -271,7 +289,7 @@ func (i *leveldbLabelSetFingerprintIndex) Lookup(p *LabelPair) (m clientmodel.Fi
|
||||
return m, true, nil
|
||||
}
|
||||
|
||||
func (i *leveldbLabelSetFingerprintIndex) Has(p *LabelPair) (ok bool, err error) {
|
||||
func (i *LeveldbLabelSetFingerprintIndex) Has(p *LabelPair) (ok bool, err error) {
|
||||
k := &dto.LabelPair{
|
||||
Name: proto.String(string(p.Name)),
|
||||
Value: proto.String(string(p.Value)),
|
||||
@ -280,21 +298,27 @@ func (i *leveldbLabelSetFingerprintIndex) Has(p *LabelPair) (ok bool, err error)
|
||||
return i.p.Has(k)
|
||||
}
|
||||
|
||||
func (i *leveldbLabelSetFingerprintIndex) ForEach(d storage.RecordDecoder, f storage.RecordFilter, o storage.RecordOperator) (bool, error) {
|
||||
func (i *LeveldbLabelSetFingerprintIndex) ForEach(d storage.RecordDecoder, f storage.RecordFilter, o storage.RecordOperator) (bool, error) {
|
||||
return i.p.ForEach(d, f, o)
|
||||
}
|
||||
|
||||
func (i *leveldbLabelSetFingerprintIndex) Close() error {
|
||||
func (i *LeveldbLabelSetFingerprintIndex) Prune() (bool, error) {
|
||||
i.p.Prune()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (i *LeveldbLabelSetFingerprintIndex) Close() error {
|
||||
i.p.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *leveldbLabelSetFingerprintIndex) Size() (uint64, bool, error) {
|
||||
func (i *LeveldbLabelSetFingerprintIndex) Size() (uint64, bool, error) {
|
||||
s, err := i.p.ApproximateSize()
|
||||
return s, true, err
|
||||
}
|
||||
|
||||
func (i *leveldbLabelSetFingerprintIndex) State() string {
|
||||
func (i *LeveldbLabelSetFingerprintIndex) State() *raw.DatabaseState {
|
||||
return i.p.State()
|
||||
}
|
||||
|
||||
@ -304,26 +328,28 @@ func NewLevelDBLabelSetFingerprintIndex(o *LevelDBLabelSetFingerprintIndexOption
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &leveldbLabelSetFingerprintIndex{
|
||||
return &LeveldbLabelSetFingerprintIndex{
|
||||
p: s,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type MetricMembershipIndex interface {
|
||||
io.Closer
|
||||
raw.Pruner
|
||||
|
||||
IndexBatch([]clientmodel.Metric) error
|
||||
Has(clientmodel.Metric) (ok bool, err error)
|
||||
Close() error
|
||||
State() string
|
||||
State() *raw.DatabaseState
|
||||
Size() (s uint64, present bool, err error)
|
||||
}
|
||||
|
||||
type leveldbMetricMembershipIndex struct {
|
||||
type LeveldbMetricMembershipIndex struct {
|
||||
p *leveldb.LevelDBPersistence
|
||||
}
|
||||
|
||||
var existenceIdentity = new(dto.MembershipIndexValue)
|
||||
|
||||
func (i *leveldbMetricMembershipIndex) IndexBatch(ms []clientmodel.Metric) error {
|
||||
func (i *LeveldbMetricMembershipIndex) IndexBatch(ms []clientmodel.Metric) error {
|
||||
batch := leveldb.NewBatch()
|
||||
defer batch.Close()
|
||||
|
||||
@ -336,28 +362,34 @@ func (i *leveldbMetricMembershipIndex) IndexBatch(ms []clientmodel.Metric) error
|
||||
return i.p.Commit(batch)
|
||||
}
|
||||
|
||||
func (i *leveldbMetricMembershipIndex) Has(m clientmodel.Metric) (ok bool, err error) {
|
||||
func (i *LeveldbMetricMembershipIndex) Has(m clientmodel.Metric) (ok bool, err error) {
|
||||
k := new(dto.Metric)
|
||||
dumpMetric(k, m)
|
||||
|
||||
return i.p.Has(k)
|
||||
}
|
||||
|
||||
func (i *leveldbMetricMembershipIndex) Close() error {
|
||||
func (i *LeveldbMetricMembershipIndex) Close() error {
|
||||
i.p.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *leveldbMetricMembershipIndex) Size() (uint64, bool, error) {
|
||||
func (i *LeveldbMetricMembershipIndex) Size() (uint64, bool, error) {
|
||||
s, err := i.p.ApproximateSize()
|
||||
return s, true, err
|
||||
}
|
||||
|
||||
func (i *leveldbMetricMembershipIndex) State() string {
|
||||
func (i *LeveldbMetricMembershipIndex) State() *raw.DatabaseState {
|
||||
return i.p.State()
|
||||
}
|
||||
|
||||
func (i *LeveldbMetricMembershipIndex) Prune() (bool, error) {
|
||||
i.p.Prune()
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
type LevelDBMetricMembershipIndexOptions struct {
|
||||
leveldb.LevelDBOptions
|
||||
}
|
||||
@ -368,7 +400,7 @@ func NewLevelDBMetricMembershipIndex(o *LevelDBMetricMembershipIndexOptions) (Me
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &leveldbMetricMembershipIndex{
|
||||
return &LeveldbMetricMembershipIndex{
|
||||
p: s,
|
||||
}, nil
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
dto "github.com/prometheus/prometheus/model/generated"
|
||||
|
||||
"github.com/prometheus/prometheus/storage"
|
||||
"github.com/prometheus/prometheus/storage/raw"
|
||||
"github.com/prometheus/prometheus/storage/raw/leveldb"
|
||||
"github.com/prometheus/prometheus/utility"
|
||||
)
|
||||
@ -88,7 +89,7 @@ func (l *LevelDBMetricPersistence) Close() {
|
||||
closer.Close()
|
||||
case errorCloser:
|
||||
if err := closer.Close(); err != nil {
|
||||
log.Println("anomaly closing", err)
|
||||
log.Println("anomaly closing:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -767,14 +768,14 @@ func (l *LevelDBMetricPersistence) GetAllValuesForLabel(labelName clientmodel.La
|
||||
//
|
||||
// Beware that it would probably be imprudent to run this on a live user-facing
|
||||
// server due to latency implications.
|
||||
func (l *LevelDBMetricPersistence) CompactKeyspaces() {
|
||||
l.CurationRemarks.CompactKeyspace()
|
||||
// l.fingerprintToMetrics.CompactKeyspace()
|
||||
// l.labelNameToFingerprints.CompactKeyspace()
|
||||
// l.labelSetToFingerprints.CompactKeyspace()
|
||||
// l.MetricHighWatermarks.CompactKeyspace()
|
||||
// l.metricMembershipIndex.CompactKeyspace()
|
||||
l.MetricSamples.CompactKeyspace()
|
||||
func (l *LevelDBMetricPersistence) Prune() {
|
||||
l.CurationRemarks.Prune()
|
||||
l.fingerprintToMetrics.Prune()
|
||||
l.labelNameToFingerprints.Prune()
|
||||
l.labelSetToFingerprints.Prune()
|
||||
l.MetricHighWatermarks.Prune()
|
||||
l.metricMembershipIndex.Prune()
|
||||
l.MetricSamples.Prune()
|
||||
}
|
||||
|
||||
func (l *LevelDBMetricPersistence) ApproximateSizes() (total uint64, err error) {
|
||||
@ -818,8 +819,8 @@ func (l *LevelDBMetricPersistence) ApproximateSizes() (total uint64, err error)
|
||||
return total, nil
|
||||
}
|
||||
|
||||
func (l *LevelDBMetricPersistence) States() []string {
|
||||
return []string{
|
||||
func (l *LevelDBMetricPersistence) States() raw.DatabaseStates {
|
||||
return raw.DatabaseStates{
|
||||
l.CurationRemarks.State(),
|
||||
l.fingerprintToMetrics.State(),
|
||||
l.labelNameToFingerprints.State(),
|
||||
|
@ -15,6 +15,7 @@ package metric
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -170,20 +171,21 @@ func (lru *WatermarkCache) checkCapacity() {
|
||||
type FingerprintHighWatermarkMapping map[clientmodel.Fingerprint]time.Time
|
||||
|
||||
type HighWatermarker interface {
|
||||
io.Closer
|
||||
raw.ForEacher
|
||||
raw.Pruner
|
||||
|
||||
UpdateBatch(FingerprintHighWatermarkMapping) error
|
||||
Get(*clientmodel.Fingerprint) (t time.Time, ok bool, err error)
|
||||
Close() error
|
||||
State() string
|
||||
State() *raw.DatabaseState
|
||||
Size() (uint64, bool, error)
|
||||
}
|
||||
|
||||
type leveldbHighWatermarker struct {
|
||||
type LeveldbHighWatermarker struct {
|
||||
p *leveldb.LevelDBPersistence
|
||||
}
|
||||
|
||||
func (w *leveldbHighWatermarker) Get(f *clientmodel.Fingerprint) (t time.Time, ok bool, err error) {
|
||||
func (w *LeveldbHighWatermarker) Get(f *clientmodel.Fingerprint) (t time.Time, ok bool, err error) {
|
||||
k := new(dto.Fingerprint)
|
||||
dumpFingerprint(k, f)
|
||||
v := new(dto.MetricHighWatermark)
|
||||
@ -198,7 +200,7 @@ func (w *leveldbHighWatermarker) Get(f *clientmodel.Fingerprint) (t time.Time, o
|
||||
return t, true, nil
|
||||
}
|
||||
|
||||
func (w *leveldbHighWatermarker) UpdateBatch(m FingerprintHighWatermarkMapping) error {
|
||||
func (w *LeveldbHighWatermarker) UpdateBatch(m FingerprintHighWatermarkMapping) error {
|
||||
batch := leveldb.NewBatch()
|
||||
defer batch.Close()
|
||||
|
||||
@ -217,7 +219,7 @@ func (w *leveldbHighWatermarker) UpdateBatch(m FingerprintHighWatermarkMapping)
|
||||
continue
|
||||
}
|
||||
|
||||
// BUG(matt): Repace this with watermark management.
|
||||
// BUG(matt): Replace this with watermark management.
|
||||
if t.After(existing) {
|
||||
v.Timestamp = proto.Int64(t.Unix())
|
||||
batch.Put(k, v)
|
||||
@ -227,21 +229,27 @@ func (w *leveldbHighWatermarker) UpdateBatch(m FingerprintHighWatermarkMapping)
|
||||
return w.p.Commit(batch)
|
||||
}
|
||||
|
||||
func (i *leveldbHighWatermarker) ForEach(d storage.RecordDecoder, f storage.RecordFilter, o storage.RecordOperator) (bool, error) {
|
||||
func (i *LeveldbHighWatermarker) ForEach(d storage.RecordDecoder, f storage.RecordFilter, o storage.RecordOperator) (bool, error) {
|
||||
return i.p.ForEach(d, f, o)
|
||||
}
|
||||
|
||||
func (i *leveldbHighWatermarker) Close() error {
|
||||
func (i *LeveldbHighWatermarker) Prune() (bool, error) {
|
||||
i.p.Prune()
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (i *LeveldbHighWatermarker) Close() error {
|
||||
i.p.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *leveldbHighWatermarker) State() string {
|
||||
func (i *LeveldbHighWatermarker) State() *raw.DatabaseState {
|
||||
return i.p.State()
|
||||
}
|
||||
|
||||
func (i *leveldbHighWatermarker) Size() (uint64, bool, error) {
|
||||
func (i *LeveldbHighWatermarker) Size() (uint64, bool, error) {
|
||||
s, err := i.p.ApproximateSize()
|
||||
return s, true, err
|
||||
}
|
||||
@ -256,7 +264,7 @@ func NewLevelDBHighWatermarker(o *LevelDBHighWatermarkerOptions) (HighWatermarke
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &leveldbHighWatermarker{
|
||||
return &LeveldbHighWatermarker{
|
||||
p: s,
|
||||
}, nil
|
||||
}
|
||||
|
@ -67,14 +67,14 @@ func (l *LevelDBMembershipIndex) Commit(batch raw.Batch) error {
|
||||
//
|
||||
// Beware that it would probably be imprudent to run this on a live user-facing
|
||||
// server due to latency implications.
|
||||
func (l *LevelDBMembershipIndex) CompactKeyspace() {
|
||||
l.persistence.CompactKeyspace()
|
||||
func (l *LevelDBMembershipIndex) Prune() {
|
||||
l.persistence.Prune()
|
||||
}
|
||||
|
||||
func (l *LevelDBMembershipIndex) ApproximateSize() (uint64, error) {
|
||||
return l.persistence.ApproximateSize()
|
||||
}
|
||||
|
||||
func (l *LevelDBMembershipIndex) State() string {
|
||||
func (l *LevelDBMembershipIndex) State() *raw.DatabaseState {
|
||||
return l.persistence.State()
|
||||
}
|
||||
|
@ -64,3 +64,7 @@ type Batch interface {
|
||||
// Drop follows the same protocol as Persistence.Drop.
|
||||
Drop(key proto.Message)
|
||||
}
|
||||
|
||||
type Pruner interface {
|
||||
Prune() (noop bool, err error)
|
||||
}
|
||||
|
@ -163,6 +163,13 @@ func (i levigoIterator) GetError() (err error) {
|
||||
return i.iterator.GetError()
|
||||
}
|
||||
|
||||
type Compression uint
|
||||
|
||||
const (
|
||||
Snappy Compression = iota
|
||||
Uncompressed
|
||||
)
|
||||
|
||||
type LevelDBOptions struct {
|
||||
Path string
|
||||
Name string
|
||||
@ -174,15 +181,16 @@ type LevelDBOptions struct {
|
||||
FlushOnMutate bool
|
||||
UseParanoidChecks bool
|
||||
|
||||
NotUseSnappy bool
|
||||
Compression Compression
|
||||
}
|
||||
|
||||
func NewLevelDBPersistence(o *LevelDBOptions) (*LevelDBPersistence, error) {
|
||||
options := levigo.NewOptions()
|
||||
options.SetCreateIfMissing(true)
|
||||
options.SetParanoidChecks(o.UseParanoidChecks)
|
||||
|
||||
compression := levigo.SnappyCompression
|
||||
if !o.NotUseSnappy {
|
||||
if o.Compression == Uncompressed {
|
||||
compression = levigo.NoCompression
|
||||
}
|
||||
options.SetCompression(compression)
|
||||
@ -313,7 +321,7 @@ func (l *LevelDBPersistence) Commit(b raw.Batch) (err error) {
|
||||
//
|
||||
// Beware that it would probably be imprudent to run this on a live user-facing
|
||||
// server due to latency implications.
|
||||
func (l *LevelDBPersistence) CompactKeyspace() {
|
||||
func (l *LevelDBPersistence) Prune() {
|
||||
|
||||
// Magic values per https://code.google.com/p/leveldb/source/browse/include/leveldb/db.h#131.
|
||||
keyspace := levigo.Range{
|
||||
|
@ -14,9 +14,7 @@
|
||||
package leveldb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/prometheus/prometheus/storage/raw"
|
||||
"github.com/prometheus/prometheus/utility"
|
||||
)
|
||||
|
||||
@ -25,50 +23,22 @@ const (
|
||||
sstablesKey = "leveldb.sstables"
|
||||
)
|
||||
|
||||
// DatabaseState models a bundle of metadata about a LevelDB database used in
|
||||
// template format string interpolation.
|
||||
type DatabaseState struct {
|
||||
Name string
|
||||
Purpose string
|
||||
Path string
|
||||
LowLevelStatus string
|
||||
SSTablesStatus string
|
||||
ApproximateSize utility.ByteSize
|
||||
Error error
|
||||
}
|
||||
|
||||
func (s DatabaseState) String() string {
|
||||
b := new(bytes.Buffer)
|
||||
|
||||
fmt.Fprintln(b, "Name:", s.Name)
|
||||
fmt.Fprintln(b, "Path:", s.Path)
|
||||
fmt.Fprintln(b, "Purpose:", s.Purpose)
|
||||
fmt.Fprintln(b, "Low Level Diagnostics:", s.LowLevelStatus)
|
||||
fmt.Fprintln(b, "SSTable Statistics:", s.SSTablesStatus)
|
||||
fmt.Fprintln(b, "Approximate Size:", s.ApproximateSize)
|
||||
fmt.Fprintln(b, "Error:", s.Error)
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (l *LevelDBPersistence) LowLevelState() DatabaseState {
|
||||
databaseState := DatabaseState{
|
||||
Path: l.path,
|
||||
Name: l.name,
|
||||
Purpose: l.purpose,
|
||||
LowLevelStatus: l.storage.PropertyValue(statsKey),
|
||||
SSTablesStatus: l.storage.PropertyValue(sstablesKey),
|
||||
func (l *LevelDBPersistence) State() *raw.DatabaseState {
|
||||
databaseState := &raw.DatabaseState{
|
||||
Location: l.path,
|
||||
Name: l.name,
|
||||
Purpose: l.purpose,
|
||||
Supplemental: map[string]string{},
|
||||
}
|
||||
|
||||
if size, err := l.ApproximateSize(); err != nil {
|
||||
databaseState.Error = err
|
||||
databaseState.Supplemental["Errors"] = err.Error()
|
||||
} else {
|
||||
databaseState.ApproximateSize = utility.ByteSize(size)
|
||||
databaseState.Size = utility.ByteSize(size)
|
||||
}
|
||||
|
||||
databaseState.Supplemental["Low Level"] = l.storage.PropertyValue(statsKey)
|
||||
databaseState.Supplemental["SSTable"] = l.storage.PropertyValue(sstablesKey)
|
||||
|
||||
return databaseState
|
||||
}
|
||||
|
||||
func (l *LevelDBPersistence) State() string {
|
||||
return l.LowLevelState().String()
|
||||
}
|
||||
|
53
storage/raw/state.go
Normal file
53
storage/raw/state.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2013 Prometheus Team
|
||||
// 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 raw
|
||||
|
||||
import (
|
||||
"github.com/prometheus/prometheus/utility"
|
||||
)
|
||||
|
||||
type DatabaseState struct {
|
||||
Name string
|
||||
|
||||
Size utility.ByteSize
|
||||
|
||||
Location string
|
||||
Purpose string
|
||||
|
||||
Supplemental map[string]string
|
||||
}
|
||||
|
||||
type DatabaseStates []*DatabaseState
|
||||
|
||||
func (s DatabaseStates) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s DatabaseStates) Less(i, j int) bool {
|
||||
l := s[i]
|
||||
r := s[j]
|
||||
|
||||
if l.Name > r.Name {
|
||||
return false
|
||||
}
|
||||
if l.Name < r.Name {
|
||||
return true
|
||||
}
|
||||
|
||||
return l.Size < r.Size
|
||||
}
|
||||
|
||||
func (s DatabaseStates) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
@ -44,7 +44,7 @@ func main() {
|
||||
log.Printf("Starting compaction...")
|
||||
size, _ := persistences.ApproximateSizes()
|
||||
log.Printf("Original Size: %d", size)
|
||||
persistences.CompactKeyspaces()
|
||||
persistences.Prune()
|
||||
log.Printf("Finished in %s", time.Since(start))
|
||||
size, _ = persistences.ApproximateSizes()
|
||||
log.Printf("New Size: %d", size)
|
||||
|
@ -16,26 +16,45 @@ package web
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/prometheus/storage/raw"
|
||||
)
|
||||
|
||||
type DatabasesHandler struct {
|
||||
States []string
|
||||
type DatabaseStatesProvider interface {
|
||||
States() raw.DatabaseStates
|
||||
}
|
||||
|
||||
Incoming chan []string
|
||||
type DatabasesHandler struct {
|
||||
RefreshInterval time.Duration
|
||||
NextRefresh time.Time
|
||||
|
||||
Current raw.DatabaseStates
|
||||
|
||||
Provider DatabaseStatesProvider
|
||||
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (h *DatabasesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
select {
|
||||
case states := <-h.Incoming:
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
h.States = states
|
||||
default:
|
||||
h.mutex.RLock()
|
||||
defer h.mutex.RUnlock()
|
||||
}
|
||||
h.Refresh()
|
||||
|
||||
h.mutex.RLock()
|
||||
defer h.mutex.RUnlock()
|
||||
executeTemplate(w, "databases", h)
|
||||
}
|
||||
|
||||
func (h *DatabasesHandler) Refresh() {
|
||||
h.mutex.RLock()
|
||||
if !time.Now().After(h.NextRefresh) {
|
||||
h.mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
h.mutex.RUnlock()
|
||||
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
|
||||
h.Current = h.Provider.States()
|
||||
h.NextRefresh = time.Now().Add(h.RefreshInterval)
|
||||
}
|
||||
|
@ -3,34 +3,28 @@
|
||||
{{define "content"}}
|
||||
<div class="container-fluid">
|
||||
<h2>Database Information</h2>
|
||||
{{range .States}}
|
||||
<h3>{{.Name}}</h3>
|
||||
{{range $database := .Current }}
|
||||
<h3>{{$database.Name}}</h3>
|
||||
<table class="table table-bordered table-condensed table-hover literal_output">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Path</th>
|
||||
<td>{{.Path}}</td>
|
||||
<th>Location</th>
|
||||
<td>{{$database.Location}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Last Refreshed</th>
|
||||
<td>{{.LastRefreshed}}</td>
|
||||
<th>Purpose</th>
|
||||
<td>{{$database.Purpose}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<td>{{.Type}}</td>
|
||||
<th>Size</th>
|
||||
<td>{{$database.Size}}</td>
|
||||
</tr>
|
||||
{{range $subject, $state := $database.Supplemental }}
|
||||
<tr>
|
||||
<th>Approximate Size</th>
|
||||
<td>{{.ApproximateSize}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Low Level Status</th>
|
||||
<td><pre>{{.LowLevelStatus}}</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>SSTable Status</th>
|
||||
<td><pre>{{.SSTablesStatus}}</pre></td>
|
||||
<th>{{$subject}}</th>
|
||||
<td><pre>{{$state}}</pre></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
|
Loading…
Reference in New Issue
Block a user