diff --git a/plugins/inputs/mongodb/README.md b/plugins/inputs/mongodb/README.md index cce93dc07376a..ddcb1971f9667 100644 --- a/plugins/inputs/mongodb/README.md +++ b/plugins/inputs/mongodb/README.md @@ -21,6 +21,10 @@ ## When true, collect per collection stats # gather_col_stats = false + + ## When true, collect usage statistics for each collection + ## (insert, update, queries, remove, getmore, commands etc...). + # gather_top_stat = false ## List of db where collections stats are collected ## If empty, all db are concerned @@ -263,6 +267,29 @@ by running Telegraf with the `--debug` argument. - available (integer) - created (integer) - refreshing (integer) + +- mongodb_top_stats + - tags: + - collection + - fields: + - total_time (integer) + - total_count (integer) + - read_lock_time (integer) + - read_lock_count (integer) + - write_lock_time (integer) + - write_lock_count (integer) + - queries_time (integer) + - queries_count (integer) + - get_more_time (integer) + - get_more_count (integer) + - insert_time (integer) + - insert_count (integer) + - update_time (integer) + - update_count (integer) + - remove_time (integer) + - remove_count (integer) + - commands_time (integer) + - commands_count (integer) ### Example Output: ``` @@ -272,4 +299,5 @@ mongodb_db_stats,db_name=admin,hostname=127.0.0.1:27017 avg_obj_size=241,collect mongodb_db_stats,db_name=local,hostname=127.0.0.1:27017 avg_obj_size=813.9705882352941,collections=6i,data_size=55350i,index_size=102400i,indexes=5i,num_extents=0i,objects=68i,ok=1i,storage_size=204800i,type="db_stat" 1547159491000000000 mongodb_col_stats,collection=foo,db_name=local,hostname=127.0.0.1:27017 size=375005928i,avg_obj_size=5494,type="col_stat",storage_size=249307136i,total_index_size=2138112i,ok=1i,count=68251i 1547159491000000000 mongodb_shard_stats,hostname=127.0.0.1:27017,in_use=3i,available=3i,created=4i,refreshing=0i 1522799074000000000 +mongodb_top_stats,collection=foo,total_time=1471,total_count=158,read_lock_time=49614,read_lock_count=657,write_lock_time=49125456,write_lock_count=9841,queries_time=174,queries_count=495,get_more_time=498,get_more_count=46,insert_time=2651,insert_count=1265,update_time=0,update_count=0,remove_time=0,remove_count=0,commands_time=498611,commands_count=4615 ``` diff --git a/plugins/inputs/mongodb/mongodb.go b/plugins/inputs/mongodb/mongodb.go index 77ea2744b300f..355c12caffef6 100644 --- a/plugins/inputs/mongodb/mongodb.go +++ b/plugins/inputs/mongodb/mongodb.go @@ -23,6 +23,7 @@ type MongoDB struct { GatherClusterStatus bool GatherPerdbStats bool GatherColStats bool + GatherTopStat bool ColStatsDbs []string tlsint.ClientConfig @@ -53,6 +54,10 @@ var sampleConfig = ` ## When true, collect per collection stats # gather_col_stats = false + ## When true, collect usage statistics for each collection + ## (insert, update, queries, remove, getmore, commands etc...). + # gather_top_stat = false + ## List of db where collections stats are collected ## If empty, all db are concerned # col_stats_dbs = ["local"] @@ -183,7 +188,7 @@ func (m *MongoDB) gatherServer(server *Server, acc telegraf.Accumulator) error { } server.Session = sess } - return server.gatherData(acc, m.GatherClusterStatus, m.GatherPerdbStats, m.GatherColStats, m.ColStatsDbs) + return server.gatherData(acc, m.GatherClusterStatus, m.GatherPerdbStats, m.GatherColStats, m.GatherTopStat, m.ColStatsDbs) } func init() { @@ -193,6 +198,7 @@ func init() { GatherClusterStatus: true, GatherPerdbStats: false, GatherColStats: false, + GatherTopStat: false, ColStatsDbs: []string{"local"}, } }) diff --git a/plugins/inputs/mongodb/mongodb_data.go b/plugins/inputs/mongodb/mongodb_data.go index 6a2c0a86ebd12..e26c0e45231eb 100644 --- a/plugins/inputs/mongodb/mongodb_data.go +++ b/plugins/inputs/mongodb/mongodb_data.go @@ -15,6 +15,7 @@ type MongodbData struct { DbData []DbData ColData []ColData ShardHostData []DbData + TopStatsData []DbData } type DbData struct { @@ -37,7 +38,7 @@ func NewMongodbData(statLine *StatLine, tags map[string]string) *MongodbData { } } -var DefaultStats = map[string]string{ +var defaultStats = map[string]string{ "uptime_ns": "UptimeNanos", "inserts": "InsertCnt", "inserts_per_sec": "Insert", @@ -94,7 +95,7 @@ var DefaultStats = map[string]string{ "total_docs_scanned": "TotalObjectsScanned", } -var DefaultAssertsStats = map[string]string{ +var defaultAssertsStats = map[string]string{ "assert_regular": "Regular", "assert_warning": "Warning", "assert_msg": "Msg", @@ -102,7 +103,7 @@ var DefaultAssertsStats = map[string]string{ "assert_rollovers": "Rollovers", } -var DefaultCommandsStats = map[string]string{ +var defaultCommandsStats = map[string]string{ "aggregate_command_total": "AggregateCommandTotal", "aggregate_command_failed": "AggregateCommandFailed", "count_command_total": "CountCommandTotal", @@ -123,7 +124,7 @@ var DefaultCommandsStats = map[string]string{ "update_command_failed": "UpdateCommandFailed", } -var DefaultLatencyStats = map[string]string{ +var defaultLatencyStats = map[string]string{ "latency_writes_count": "WriteOpsCnt", "latency_writes": "WriteLatency", "latency_reads_count": "ReadOpsCnt", @@ -132,7 +133,7 @@ var DefaultLatencyStats = map[string]string{ "latency_commands": "CommandLatency", } -var DefaultReplStats = map[string]string{ +var defaultReplStats = map[string]string{ "repl_inserts": "InsertRCnt", "repl_inserts_per_sec": "InsertR", "repl_queries": "QueryRCnt", @@ -164,37 +165,37 @@ var DefaultReplStats = map[string]string{ "repl_executor_unsignaled_events": "ReplExecutorUnsignaledEvents", } -var DefaultClusterStats = map[string]string{ +var defaultClusterStats = map[string]string{ "jumbo_chunks": "JumboChunksCount", } -var DefaultShardStats = map[string]string{ +var defaultShardStats = map[string]string{ "total_in_use": "TotalInUse", "total_available": "TotalAvailable", "total_created": "TotalCreated", "total_refreshing": "TotalRefreshing", } -var ShardHostStats = map[string]string{ +var shardHostStats = map[string]string{ "in_use": "InUse", "available": "Available", "created": "Created", "refreshing": "Refreshing", } -var MmapStats = map[string]string{ +var mmapStats = map[string]string{ "mapped_megabytes": "Mapped", "non-mapped_megabytes": "NonMapped", "page_faults": "FaultsCnt", "page_faults_per_sec": "Faults", } -var WiredTigerStats = map[string]string{ +var wiredTigerStats = map[string]string{ "percent_cache_dirty": "CacheDirtyPercent", "percent_cache_used": "CacheUsedPercent", } -var WiredTigerExtStats = map[string]string{ +var wiredTigerExtStats = map[string]string{ "wtcache_tracked_dirty_bytes": "TrackedDirtyBytes", "wtcache_current_bytes": "CurrentCachedBytes", "wtcache_max_bytes_configured": "MaxBytesConfigured", @@ -215,7 +216,7 @@ var WiredTigerExtStats = map[string]string{ "wtcache_unmodified_pages_evicted": "UnmodifiedPagesEvicted", } -var DefaultTCMallocStats = map[string]string{ +var defaultTCMallocStats = map[string]string{ "tcmalloc_current_allocated_bytes": "TCMallocCurrentAllocatedBytes", "tcmalloc_heap_size": "TCMallocHeapSize", "tcmalloc_central_cache_free_bytes": "TCMallocCentralCacheFreeBytes", @@ -237,13 +238,13 @@ var DefaultTCMallocStats = map[string]string{ "tcmalloc_pageheap_total_reserve_bytes": "TCMallocPageheapTotalReserveBytes", } -var DefaultStorageStats = map[string]string{ +var defaultStorageStats = map[string]string{ "storage_freelist_search_bucket_exhausted": "StorageFreelistSearchBucketExhausted", "storage_freelist_search_requests": "StorageFreelistSearchRequests", "storage_freelist_search_scanned": "StorageFreelistSearchScanned", } -var DbDataStats = map[string]string{ +var dbDataStats = map[string]string{ "collections": "Collections", "objects": "Objects", "avg_obj_size": "AvgObjSize", @@ -255,7 +256,7 @@ var DbDataStats = map[string]string{ "ok": "Ok", } -var ColDataStats = map[string]string{ +var colDataStats = map[string]string{ "count": "Count", "size": "Size", "avg_obj_size": "AvgObjSize", @@ -264,6 +265,27 @@ var ColDataStats = map[string]string{ "ok": "Ok", } +var topDataStats = map[string]string{ + "total_time": "TotalTime", + "total_count": "TotalCount", + "read_lock_time": "ReadLockTime", + "read_lock_count": "ReadLockCount", + "write_lock_time": "WriteLockTime", + "write_lock_count": "WriteLockCount", + "queries_time": "QueriesTime", + "queries_count": "QueriesCount", + "get_more_time": "GetMoreTime", + "get_more_count": "GetMoreCount", + "insert_time": "InsertTime", + "insert_count": "InsertCount", + "update_time": "UpdateTime", + "update_count": "UpdateCount", + "remove_time": "RemoveTime", + "remove_count": "RemoveCount", + "commands_time": "CommandsTime", + "commands_count": "CommandsCount", +} + func (d *MongodbData) AddDbStats() { for _, dbstat := range d.StatLine.DbStatsLines { dbStatLine := reflect.ValueOf(&dbstat).Elem() @@ -272,7 +294,7 @@ func (d *MongodbData) AddDbStats() { Fields: make(map[string]interface{}), } newDbData.Fields["type"] = "db_stat" - for key, value := range DbDataStats { + for key, value := range dbDataStats { val := dbStatLine.FieldByName(value).Interface() newDbData.Fields[key] = val } @@ -289,7 +311,7 @@ func (d *MongodbData) AddColStats() { Fields: make(map[string]interface{}), } newColData.Fields["type"] = "col_stat" - for key, value := range ColDataStats { + for key, value := range colDataStats { val := colStatLine.FieldByName(value).Interface() newColData.Fields[key] = val } @@ -305,7 +327,7 @@ func (d *MongodbData) AddShardHostStats() { Fields: make(map[string]interface{}), } newDbData.Fields["type"] = "shard_host_stat" - for k, v := range ShardHostStats { + for k, v := range shardHostStats { val := hostStatLine.FieldByName(v).Interface() newDbData.Fields[k] = val } @@ -313,16 +335,32 @@ func (d *MongodbData) AddShardHostStats() { } } +func (d *MongodbData) AddTopStats() { + for _, topStat := range d.StatLine.TopStatLines { + topStatLine := reflect.ValueOf(&topStat).Elem() + newTopStatData := &DbData{ + Name: topStat.CollectionName, + Fields: make(map[string]interface{}), + } + newTopStatData.Fields["type"] = "top_stat" + for key, value := range topDataStats { + val := topStatLine.FieldByName(value).Interface() + newTopStatData.Fields[key] = val + } + d.TopStatsData = append(d.TopStatsData, *newTopStatData) + } +} + func (d *MongodbData) AddDefaultStats() { statLine := reflect.ValueOf(d.StatLine).Elem() - d.addStat(statLine, DefaultStats) + d.addStat(statLine, defaultStats) if d.StatLine.NodeType != "" { - d.addStat(statLine, DefaultReplStats) + d.addStat(statLine, defaultReplStats) d.Tags["node_type"] = d.StatLine.NodeType } if d.StatLine.ReadLatency > 0 { - d.addStat(statLine, DefaultLatencyStats) + d.addStat(statLine, defaultLatencyStats) } if d.StatLine.ReplSetName != "" { @@ -337,23 +375,23 @@ func (d *MongodbData) AddDefaultStats() { d.add("version", d.StatLine.Version) } - d.addStat(statLine, DefaultAssertsStats) - d.addStat(statLine, DefaultClusterStats) - d.addStat(statLine, DefaultCommandsStats) - d.addStat(statLine, DefaultShardStats) - d.addStat(statLine, DefaultStorageStats) - d.addStat(statLine, DefaultTCMallocStats) + d.addStat(statLine, defaultAssertsStats) + d.addStat(statLine, defaultClusterStats) + d.addStat(statLine, defaultCommandsStats) + d.addStat(statLine, defaultShardStats) + d.addStat(statLine, defaultStorageStats) + d.addStat(statLine, defaultTCMallocStats) if d.StatLine.StorageEngine == "mmapv1" || d.StatLine.StorageEngine == "rocksdb" { - d.addStat(statLine, MmapStats) + d.addStat(statLine, mmapStats) } else if d.StatLine.StorageEngine == "wiredTiger" { - for key, value := range WiredTigerStats { + for key, value := range wiredTigerStats { val := statLine.FieldByName(value).Interface() percentVal := fmt.Sprintf("%.1f", val.(float64)*100) floatVal, _ := strconv.ParseFloat(percentVal, 64) d.add(key, floatVal) } - d.addStat(statLine, WiredTigerExtStats) + d.addStat(statLine, wiredTigerExtStats) d.add("page_faults", d.StatLine.FaultsCnt) } } @@ -409,4 +447,14 @@ func (d *MongodbData) flush(acc telegraf.Accumulator) { ) host.Fields = make(map[string]interface{}) } + for _, col := range d.TopStatsData { + d.Tags["collection"] = col.Name + acc.AddFields( + "mongodb_top_stats", + col.Fields, + d.Tags, + d.StatLine.Time, + ) + col.Fields = make(map[string]interface{}) + } } diff --git a/plugins/inputs/mongodb/mongodb_data_test.go b/plugins/inputs/mongodb/mongodb_data_test.go index 4a1730211b594..378268916054d 100644 --- a/plugins/inputs/mongodb/mongodb_data_test.go +++ b/plugins/inputs/mongodb/mongodb_data_test.go @@ -64,7 +64,7 @@ func TestAddNonReplStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range DefaultStats { + for key := range defaultStats { assert.True(t, acc.HasFloatField("mongodb", key) || acc.HasInt64Field("mongodb", key), key) } } @@ -85,7 +85,7 @@ func TestAddReplStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range MmapStats { + for key := range mmapStats { assert.True(t, acc.HasInt64Field("mongodb", key), key) } } @@ -119,11 +119,11 @@ func TestAddWiredTigerStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range WiredTigerStats { + for key := range wiredTigerStats { assert.True(t, acc.HasFloatField("mongodb", key), key) } - for key := range WiredTigerExtStats { + for key := range wiredTigerExtStats { assert.True(t, acc.HasFloatField("mongodb", key) || acc.HasInt64Field("mongodb", key), key) } @@ -146,7 +146,7 @@ func TestAddShardStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range DefaultShardStats { + for key := range defaultShardStats { assert.True(t, acc.HasInt64Field("mongodb", key)) } } @@ -169,7 +169,7 @@ func TestAddLatencyStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range DefaultLatencyStats { + for key := range defaultLatencyStats { assert.True(t, acc.HasInt64Field("mongodb", key)) } } @@ -191,7 +191,7 @@ func TestAddAssertsStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range DefaultAssertsStats { + for key := range defaultAssertsStats { assert.True(t, acc.HasInt64Field("mongodb", key)) } } @@ -226,7 +226,7 @@ func TestAddCommandsStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range DefaultCommandsStats { + for key := range defaultCommandsStats { assert.True(t, acc.HasInt64Field("mongodb", key)) } } @@ -262,7 +262,7 @@ func TestAddTCMallocStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range DefaultTCMallocStats { + for key := range defaultTCMallocStats { assert.True(t, acc.HasInt64Field("mongodb", key)) } } @@ -282,7 +282,7 @@ func TestAddStorageStats(t *testing.T) { d.AddDefaultStats() d.flush(&acc) - for key := range DefaultStorageStats { + for key := range defaultStorageStats { assert.True(t, acc.HasInt64Field("mongodb", key)) } } @@ -312,7 +312,7 @@ func TestAddShardHostStats(t *testing.T) { var hostsFound []string for host := range hostStatLines { - for key := range ShardHostStats { + for key := range shardHostStats { assert.True(t, acc.HasInt64Field("mongodb_shard_stats", key)) } @@ -485,3 +485,49 @@ func TestStateTag(t *testing.T) { } acc.AssertContainsTaggedFields(t, "mongodb", fields, stateTags) } + +func TestAddTopStats(t *testing.T) { + collections := []string{"collectionOne", "collectionTwo"} + var topStatLines []TopStatLine + for _, collection := range collections { + topStatLine := TopStatLine{ + CollectionName: collection, + TotalTime: 0, + TotalCount: 0, + ReadLockTime: 0, + ReadLockCount: 0, + WriteLockTime: 0, + WriteLockCount: 0, + QueriesTime: 0, + QueriesCount: 0, + GetMoreTime: 0, + GetMoreCount: 0, + InsertTime: 0, + InsertCount: 0, + UpdateTime: 0, + UpdateCount: 0, + RemoveTime: 0, + RemoveCount: 0, + CommandsTime: 0, + CommandsCount: 0, + } + topStatLines = append(topStatLines, topStatLine) + } + + d := NewMongodbData( + &StatLine{ + TopStatLines: topStatLines, + }, + tags, + ) + + var acc testutil.Accumulator + d.AddTopStats() + d.flush(&acc) + + for range topStatLines { + for key := range topDataStats { + assert.True(t, acc.HasInt64Field("mongodb_top_stats", key)) + } + } +} diff --git a/plugins/inputs/mongodb/mongodb_server.go b/plugins/inputs/mongodb/mongodb_server.go index 9553a578c04da..e362a0bd7f008 100644 --- a/plugins/inputs/mongodb/mongodb_server.go +++ b/plugins/inputs/mongodb/mongodb_server.go @@ -73,6 +73,20 @@ func (s *Server) gatherReplSetStatus() (*ReplSetStatus, error) { return replSetStatus, nil } +func (s *Server) gatherTopStatData() (*TopStats, error) { + topStats := &TopStats{} + err := s.Session.DB("admin").Run(bson.D{ + { + Name: "top", + Value: 1, + }, + }, topStats) + if err != nil { + return nil, err + } + return topStats, nil +} + func (s *Server) gatherClusterStatus() (*ClusterStatus, error) { chunkCount, err := s.Session.DB("config").C("chunks").Find(bson.M{"jumbo": true}).Count() if err != nil { @@ -192,7 +206,7 @@ func (s *Server) gatherCollectionStats(colStatsDbs []string) (*ColStats, error) return results, nil } -func (s *Server) gatherData(acc telegraf.Accumulator, gatherClusterStatus bool, gatherDbStats bool, gatherColStats bool, colStatsDbs []string) error { +func (s *Server) gatherData(acc telegraf.Accumulator, gatherClusterStatus bool, gatherDbStats bool, gatherColStats bool, gatherTopStat bool, colStatsDbs []string) error { s.Session.SetMode(mgo.Eventual, true) s.Session.SetSocketTimeout(0) @@ -257,6 +271,16 @@ func (s *Server) gatherData(acc telegraf.Accumulator, gatherClusterStatus bool, } } + topStatData := &TopStats{} + if gatherTopStat { + topStats, err := s.gatherTopStatData() + if err != nil { + s.Log.Debugf("Unable to gather top stat data: %s", err.Error()) + return err + } + topStatData = topStats + } + result := &MongoStatus{ ServerStatus: serverStatus, ReplSetStatus: replSetStatus, @@ -265,6 +289,7 @@ func (s *Server) gatherData(acc telegraf.Accumulator, gatherClusterStatus bool, ColStats: collectionStats, ShardStats: shardStats, OplogStats: oplogStats, + TopStats: topStatData, } result.SampleTime = time.Now() @@ -282,6 +307,7 @@ func (s *Server) gatherData(acc telegraf.Accumulator, gatherClusterStatus bool, data.AddDbStats() data.AddColStats() data.AddShardHostStats() + data.AddTopStats() data.flush(acc) } diff --git a/plugins/inputs/mongodb/mongodb_server_test.go b/plugins/inputs/mongodb/mongodb_server_test.go index 91a3c0709f0d4..463d7af1b1f65 100644 --- a/plugins/inputs/mongodb/mongodb_server_test.go +++ b/plugins/inputs/mongodb/mongodb_server_test.go @@ -35,7 +35,7 @@ func TestAddDefaultStats(t *testing.T) { err = server.gatherData(&acc, false) require.NoError(t, err) - for key := range DefaultStats { + for key := range defaultStats { assert.True(t, acc.HasInt64Field("mongodb", key)) } } diff --git a/plugins/inputs/mongodb/mongostat.go b/plugins/inputs/mongodb/mongostat.go index 6210b782e7884..3cfa9e9747bc9 100644 --- a/plugins/inputs/mongodb/mongostat.go +++ b/plugins/inputs/mongodb/mongostat.go @@ -37,6 +37,7 @@ type MongoStatus struct { ColStats *ColStats ShardStats *ShardStats OplogStats *OplogStats + TopStats *TopStats } type ServerStatus struct { @@ -169,6 +170,31 @@ type ShardHostStatsData struct { Refreshing int64 `bson:"refreshing"` } +type TopStats struct { + Totals map[string]TopStatCollections `bson:"totals"` +} + +type TopStatCollections struct { + TSCollection TopStatCollection `bson:",inline"` +} + +type TopStatCollection struct { + Total TopStatCollectionData `bson:"total"` + ReadLock TopStatCollectionData `bson:"readLock"` + WriteLock TopStatCollectionData `bson:"writeLock"` + Queries TopStatCollectionData `bson:"queries"` + GetMore TopStatCollectionData `bson:"getmore"` + Insert TopStatCollectionData `bson:"insert"` + Update TopStatCollectionData `bson:"update"` + Remove TopStatCollectionData `bson:"remove"` + Commands TopStatCollectionData `bson:"commands"` +} + +type TopStatCollectionData struct { + Time int64 `bson:"time"` + Count int64 `bson:"count"` +} + type ConcurrentTransactions struct { Write ConcurrentTransStats `bson:"write"` Read ConcurrentTransStats `bson:"read"` @@ -768,6 +794,8 @@ type StatLine struct { // Shard Hosts stats field ShardHostStatsLines map[string]ShardHostStatLine + TopStatLines []TopStatLine + // TCMalloc stats field TCMallocCurrentAllocatedBytes int64 TCMallocHeapSize int64 @@ -825,6 +853,19 @@ type ShardHostStatLine struct { Refreshing int64 } +type TopStatLine struct { + CollectionName string + TotalTime, TotalCount int64 + ReadLockTime, ReadLockCount int64 + WriteLockTime, WriteLockCount int64 + QueriesTime, QueriesCount int64 + GetMoreTime, GetMoreCount int64 + InsertTime, InsertCount int64 + UpdateTime, UpdateCount int64 + RemoveTime, RemoveCount int64 + CommandsTime, CommandsCount int64 +} + func parseLocks(stat ServerStatus) map[string]LockUsage { returnVal := map[string]LockUsage{} for namespace, lockInfo := range stat.Locks { @@ -1101,7 +1142,7 @@ func NewStatLine(oldMongo, newMongo MongoStatus, key string, all bool, sampleSec returnVal.Time = newMongo.SampleTime returnVal.IsMongos = - (newStat.ShardCursorType != nil || strings.HasPrefix(newStat.Process, MongosProcess)) + newStat.ShardCursorType != nil || strings.HasPrefix(newStat.Process, MongosProcess) // BEGIN code modification if oldStat.Mem.Supported.(bool) { @@ -1209,7 +1250,7 @@ func NewStatLine(oldMongo, newMongo MongoStatus, key string, all bool, sampleSec } if newStat.GlobalLock != nil { - hasWT := (newStat.WiredTiger != nil && oldStat.WiredTiger != nil) + hasWT := newStat.WiredTiger != nil && oldStat.WiredTiger != nil //If we have wiredtiger stats, use those instead if newStat.GlobalLock.CurrentQueue != nil { if hasWT { @@ -1364,5 +1405,32 @@ func NewStatLine(oldMongo, newMongo MongoStatus, key string, all bool, sampleSec } } + if newMongo.TopStats != nil { + for collection, data := range newMongo.TopStats.Totals { + topStatDataLine := &TopStatLine{ + CollectionName: collection, + TotalTime: data.TSCollection.Total.Time, + TotalCount: data.TSCollection.Total.Count, + ReadLockTime: data.TSCollection.ReadLock.Time, + ReadLockCount: data.TSCollection.ReadLock.Count, + WriteLockTime: data.TSCollection.WriteLock.Time, + WriteLockCount: data.TSCollection.WriteLock.Count, + QueriesTime: data.TSCollection.Queries.Time, + QueriesCount: data.TSCollection.Queries.Count, + GetMoreTime: data.TSCollection.GetMore.Time, + GetMoreCount: data.TSCollection.GetMore.Count, + InsertTime: data.TSCollection.Insert.Time, + InsertCount: data.TSCollection.Insert.Count, + UpdateTime: data.TSCollection.Update.Time, + UpdateCount: data.TSCollection.Update.Count, + RemoveTime: data.TSCollection.Remove.Time, + RemoveCount: data.TSCollection.Remove.Count, + CommandsTime: data.TSCollection.Commands.Time, + CommandsCount: data.TSCollection.Commands.Count, + } + returnVal.TopStatLines = append(returnVal.TopStatLines, *topStatDataLine) + } + } + return returnVal }