Skip to content

Commit

Permalink
Adding replication lag metric
Browse files Browse the repository at this point in the history
  • Loading branch information
Victor Garcia committed Apr 20, 2016
1 parent 4bcf157 commit 76973fa
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ based on _prefix_ in addition to globs. This means that a filter like
- [#889](https://github.com/influxdata/telegraf/pull/889): Improved MySQL plugin. Thanks @maksadbek!
- [#1060](https://github.com/influxdata/telegraf/pull/1060): TTL metrics added to MongoDB input plugin
- [#1056](https://github.com/influxdata/telegraf/pull/1056): Don't allow inputs to overwrite host tags.
- [#1066](https://github.com/influxdata/telegraf/pull/1066): Replication lag metrics for MongoDB input plugin

### Bugfixes

Expand Down
1 change: 1 addition & 0 deletions plugins/inputs/mongodb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ and create a single measurement containing values e.g.
* vsize_megabytes
* ttl_deletes_per_sec
* ttl_passes_per_sec
* repl_lag
1 change: 1 addition & 0 deletions plugins/inputs/mongodb/mongodb_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ var DefaultReplStats = map[string]string{
"repl_getmores_per_sec": "GetMoreR",
"repl_commands_per_sec": "CommandR",
"member_status": "NodeType",
"repl_lag": "ReplLag",
}

var MmapStats = map[string]string{
Expand Down
1 change: 1 addition & 0 deletions plugins/inputs/mongodb/mongodb_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ func TestStateTag(t *testing.T) {
"repl_inserts_per_sec": int64(0),
"repl_queries_per_sec": int64(0),
"repl_updates_per_sec": int64(0),
"repl_lag": int64(0),
"resident_megabytes": int64(0),
"updates_per_sec": int64(0),
"vsize_megabytes": int64(0),
Expand Down
18 changes: 15 additions & 3 deletions plugins/inputs/mongodb/mongodb_server.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mongodb

import (
"log"
"net/url"
"time"

Expand All @@ -12,7 +13,7 @@ import (
type Server struct {
Url *url.URL
Session *mgo.Session
lastResult *ServerStatus
lastResult *MongoStatus
}

func (s *Server) getDefaultTags() map[string]string {
Expand All @@ -24,11 +25,22 @@ func (s *Server) getDefaultTags() map[string]string {
func (s *Server) gatherData(acc telegraf.Accumulator) error {
s.Session.SetMode(mgo.Eventual, true)
s.Session.SetSocketTimeout(0)
result := &ServerStatus{}
err := s.Session.DB("admin").Run(bson.D{{"serverStatus", 1}, {"recordStats", 0}}, result)
result_server := &ServerStatus{}
err := s.Session.DB("admin").Run(bson.D{{"serverStatus", 1}, {"recordStats", 0}}, result_server)
if err != nil {
return err
}
result_repl := &ReplSetStatus{}
err = s.Session.DB("admin").Run(bson.D{{"replSetGetStatus", 1}}, result_repl)
if err != nil {
log.Println("Not gathering replica set status, member not in replica set")
}

result := &MongoStatus{
ServerStatus: result_server,
ReplSetStatus: result_repl,
}

defer func() {
s.lastResult = result
}()
Expand Down
66 changes: 62 additions & 4 deletions plugins/inputs/mongodb/mongostat.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"sort"
"strings"
"time"

"gopkg.in/mgo.v2/bson"
)

const (
Expand All @@ -28,8 +30,13 @@ const (
WTOnly // only active if node has wiredtiger-specific fields
)

type MongoStatus struct {
SampleTime time.Time
ServerStatus *ServerStatus
ReplSetStatus *ReplSetStatus
}

type ServerStatus struct {
SampleTime time.Time `bson:""`
Host string `bson:"host"`
Version string `bson:"version"`
Process string `bson:"process"`
Expand Down Expand Up @@ -57,6 +64,19 @@ type ServerStatus struct {
Metrics *MetricsStats `bson:"metrics"`
}

// ReplSetStatus stores information from replSetGetStatus
type ReplSetStatus struct {
Members []ReplSetMember `bson:"members"`
MyState int64 `bson:"myState"`
}

// ReplSetMember stores information related to a replica set member
type ReplSetMember struct {
Name string `bson:"name"`
State int64 `bson:"state"`
Optime *bson.MongoTimestamp `bson:"optime"`
}

// WiredTiger stores information related to the WiredTiger storage engine.
type WiredTiger struct {
Transaction TransactionStats `bson:"transaction"`
Expand Down Expand Up @@ -356,6 +376,7 @@ type StatLine struct {

// Replicated Opcounter fields
InsertR, QueryR, UpdateR, DeleteR, GetMoreR, CommandR int64
ReplLag int64
Flushes int64
Mapped, Virtual, Resident, NonMapped int64
Faults int64
Expand Down Expand Up @@ -410,8 +431,11 @@ func diff(newVal, oldVal, sampleTime int64) int64 {
return d / sampleTime
}

// NewStatLine constructs a StatLine object from two ServerStatus objects.
func NewStatLine(oldStat, newStat ServerStatus, key string, all bool, sampleSecs int64) *StatLine {
// NewStatLine constructs a StatLine object from two MongoStatus objects.
func NewStatLine(oldMongo, newMongo MongoStatus, key string, all bool, sampleSecs int64) *StatLine {
oldStat := *oldMongo.ServerStatus
newStat := *newMongo.ServerStatus

returnVal := &StatLine{
Key: key,
Host: newStat.Host,
Expand Down Expand Up @@ -462,7 +486,7 @@ func NewStatLine(oldStat, newStat ServerStatus, key string, all bool, sampleSecs
returnVal.Flushes = newStat.BackgroundFlushing.Flushes - oldStat.BackgroundFlushing.Flushes
}

returnVal.Time = newStat.SampleTime
returnVal.Time = newMongo.SampleTime
returnVal.IsMongos =
(newStat.ShardCursorType != nil || strings.HasPrefix(newStat.Process, MongosProcess))

Expand Down Expand Up @@ -607,5 +631,39 @@ func NewStatLine(oldStat, newStat ServerStatus, key string, all bool, sampleSecs
returnVal.NumConnections = newStat.Connections.Current
}

newReplStat := *newMongo.ReplSetStatus

if newReplStat.Members != nil {
myName := newStat.Repl.Me
// Find the master and myself
master := ReplSetMember{}
me := ReplSetMember{}
for _, member := range newReplStat.Members {
if member.Name == myName {
if member.State == 1 {
// I'm the master
returnVal.ReplLag = 0
break
} else {
// I'm secondary
me = member
}
} else if member.State == 1 {
// Master found
master = member
}
}

if me.Optime != nil && master.Optime != nil && me.State == 2 {
// MongoTimestamp type is int64 where the first 32bits are the unix timestamp
lag := int64(*master.Optime>>32 - *me.Optime>>32)
if lag < 0 {
returnVal.ReplLag = 0
} else {
returnVal.ReplLag = lag
}
}
}

return returnVal
}

0 comments on commit 76973fa

Please sign in to comment.