Browse Source

wal: record metrics

Xiang Li 11 years ago
parent
commit
9e63b1fb63
1 changed files with 25 additions and 1 deletions
  1. 25 1
      wal/wal.go

+ 25 - 1
wal/wal.go

@@ -23,7 +23,9 @@ import (
 	"os"
 	"os"
 	"path"
 	"path"
 	"reflect"
 	"reflect"
+	"time"
 
 
+	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/codahale/metrics"
 	"github.com/coreos/etcd/pkg/fileutil"
 	"github.com/coreos/etcd/pkg/fileutil"
 	"github.com/coreos/etcd/pkg/pbutil"
 	"github.com/coreos/etcd/pkg/pbutil"
 	"github.com/coreos/etcd/raft"
 	"github.com/coreos/etcd/raft"
@@ -49,8 +51,15 @@ var (
 	ErrSnapshotMismatch = errors.New("wal: snapshot mismatch")
 	ErrSnapshotMismatch = errors.New("wal: snapshot mismatch")
 	ErrSnapshotNotFound = errors.New("wal: snapshot not found")
 	ErrSnapshotNotFound = errors.New("wal: snapshot not found")
 	crcTable            = crc32.MakeTable(crc32.Castagnoli)
 	crcTable            = crc32.MakeTable(crc32.Castagnoli)
+
+	// metrics
+	syncHdr *metrics.Histogram
 )
 )
 
 
+func init() {
+	syncHdr = metrics.NewHistogram("wal.syncInMicrosecond", 0, 10*int64(time.Second/time.Microsecond), 3)
+}
+
 // WAL is a logical repersentation of the stable storage.
 // WAL is a logical repersentation of the stable storage.
 // WAL is either in read mode or append mode but not both.
 // WAL is either in read mode or append mode but not both.
 // A newly created WAL is in append mode, and ready for appending records.
 // A newly created WAL is in append mode, and ready for appending records.
@@ -269,6 +278,7 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.
 	// create encoder (chain crc with the decoder), enable appending
 	// create encoder (chain crc with the decoder), enable appending
 	w.encoder = newEncoder(w.f, w.decoder.lastCRC())
 	w.encoder = newEncoder(w.f, w.decoder.lastCRC())
 	w.decoder = nil
 	w.decoder = nil
+	metrics.Gauge("wal.lastIndexSaved").Set(int64(w.enti))
 	return metadata, state, ents, err
 	return metadata, state, ents, err
 }
 }
 
 
@@ -317,7 +327,11 @@ func (w *WAL) sync() error {
 			return err
 			return err
 		}
 		}
 	}
 	}
-	return w.f.Sync()
+	start := time.Now()
+	err := w.f.Sync()
+	syncHdr.RecordValue(time.Since(start).Nanoseconds() / int64(time.Microsecond))
+	metrics.Counter("wal.syncs").Add()
+	return err
 }
 }
 
 
 // ReleaseLockTo releases the locks w is holding, which
 // ReleaseLockTo releases the locks w is holding, which
@@ -362,12 +376,14 @@ func (w *WAL) Close() error {
 }
 }
 
 
 func (w *WAL) saveEntry(e *raftpb.Entry) error {
 func (w *WAL) saveEntry(e *raftpb.Entry) error {
+	metrics.Counter("wal.saveEntryOps").Add()
 	b := pbutil.MustMarshal(e)
 	b := pbutil.MustMarshal(e)
 	rec := &walpb.Record{Type: entryType, Data: b}
 	rec := &walpb.Record{Type: entryType, Data: b}
 	if err := w.encoder.encode(rec); err != nil {
 	if err := w.encoder.encode(rec); err != nil {
 		return err
 		return err
 	}
 	}
 	w.enti = e.Index
 	w.enti = e.Index
+	metrics.Gauge("wal.lastIndexSaved").Set(int64(w.enti))
 	return nil
 	return nil
 }
 }
 
 
@@ -375,6 +391,7 @@ func (w *WAL) saveState(s *raftpb.HardState) error {
 	if raft.IsEmptyHardState(*s) {
 	if raft.IsEmptyHardState(*s) {
 		return nil
 		return nil
 	}
 	}
+	metrics.Counter("wal.saveStateOps").Add()
 	w.state = *s
 	w.state = *s
 	b := pbutil.MustMarshal(s)
 	b := pbutil.MustMarshal(s)
 	rec := &walpb.Record{Type: stateType, Data: b}
 	rec := &walpb.Record{Type: stateType, Data: b}
@@ -382,6 +399,11 @@ func (w *WAL) saveState(s *raftpb.HardState) error {
 }
 }
 
 
 func (w *WAL) Save(st raftpb.HardState, ents []raftpb.Entry) error {
 func (w *WAL) Save(st raftpb.HardState, ents []raftpb.Entry) error {
+	// short cut, do not call sync
+	if raft.IsEmptyHardState(st) && len(ents) == 0 {
+		return nil
+	}
+
 	// TODO(xiangli): no more reference operator
 	// TODO(xiangli): no more reference operator
 	if err := w.saveState(&st); err != nil {
 	if err := w.saveState(&st); err != nil {
 		return err
 		return err
@@ -400,10 +422,12 @@ func (w *WAL) SaveSnapshot(e walpb.Snapshot) error {
 	if err := w.encoder.encode(rec); err != nil {
 	if err := w.encoder.encode(rec); err != nil {
 		return err
 		return err
 	}
 	}
+	metrics.Counter("wal.saveSnapOps").Add()
 	// update enti only when snapshot is ahead of last index
 	// update enti only when snapshot is ahead of last index
 	if w.enti < e.Index {
 	if w.enti < e.Index {
 		w.enti = e.Index
 		w.enti = e.Index
 	}
 	}
+	metrics.Gauge("wal.lastIndexSaved").Set(int64(w.enti))
 	return w.sync()
 	return w.sync()
 }
 }