2015-07-07 09:20:11 +08:00
|
|
|
package mongodb
|
|
|
|
|
|
|
|
|
|
import (
|
2021-07-23 04:50:23 +08:00
|
|
|
"context"
|
2024-02-09 01:32:30 +08:00
|
|
|
"errors"
|
2019-09-24 06:39:50 +08:00
|
|
|
"fmt"
|
2021-08-27 04:32:48 +08:00
|
|
|
"strconv"
|
2018-10-18 02:44:48 +08:00
|
|
|
"strings"
|
2015-07-07 09:20:11 +08:00
|
|
|
"time"
|
|
|
|
|
|
2021-07-23 04:50:23 +08:00
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
2022-06-22 01:16:12 +08:00
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
2021-07-23 04:50:23 +08:00
|
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
|
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
2022-11-11 02:55:58 +08:00
|
|
|
|
|
|
|
|
"github.com/influxdata/telegraf"
|
2015-07-07 09:20:11 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Server struct {
|
2021-07-23 04:50:23 +08:00
|
|
|
client *mongo.Client
|
|
|
|
|
hostname string
|
2024-09-13 04:58:57 +08:00
|
|
|
lastResult *mongoStatus
|
2019-09-24 06:39:50 +08:00
|
|
|
|
|
|
|
|
Log telegraf.Logger
|
2015-07-07 09:20:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *Server) getDefaultTags() map[string]string {
|
|
|
|
|
tags := make(map[string]string)
|
2021-07-23 04:50:23 +08:00
|
|
|
tags["hostname"] = s.hostname
|
2015-07-07 09:20:11 +08:00
|
|
|
return tags
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-07 07:34:47 +08:00
|
|
|
type oplogEntry struct {
|
2021-07-23 04:50:23 +08:00
|
|
|
Timestamp primitive.Timestamp `bson:"ts"`
|
2018-04-07 07:34:47 +08:00
|
|
|
}
|
|
|
|
|
|
2018-10-18 02:44:48 +08:00
|
|
|
func IsAuthorization(err error) bool {
|
|
|
|
|
return strings.Contains(err.Error(), "not authorized")
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-08 03:25:32 +08:00
|
|
|
func (s *Server) ping() error {
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
|
|
return s.client.Ping(ctx, nil)
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-24 06:39:50 +08:00
|
|
|
func (s *Server) authLog(err error) {
|
2019-08-15 07:59:02 +08:00
|
|
|
if IsAuthorization(err) {
|
2019-09-24 06:39:50 +08:00
|
|
|
s.Log.Debug(err.Error())
|
2019-08-15 07:59:02 +08:00
|
|
|
} else {
|
2019-09-24 06:39:50 +08:00
|
|
|
s.Log.Error(err.Error())
|
2019-08-15 07:59:02 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-14 01:47:18 +08:00
|
|
|
func (s *Server) runCommand(database string, cmd, result interface{}) error {
|
2021-07-23 04:50:23 +08:00
|
|
|
r := s.client.Database(database).RunCommand(context.Background(), cmd)
|
|
|
|
|
if r.Err() != nil {
|
|
|
|
|
return r.Err()
|
|
|
|
|
}
|
|
|
|
|
return r.Decode(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) gatherServerStatus() (*serverStatus, error) {
|
|
|
|
|
serverStatus := &serverStatus{}
|
2021-07-23 04:50:23 +08:00
|
|
|
err := s.runCommand("admin", bson.D{
|
2019-08-28 01:31:42 +08:00
|
|
|
{
|
2021-07-23 04:50:23 +08:00
|
|
|
Key: "serverStatus",
|
2019-08-28 01:31:42 +08:00
|
|
|
Value: 1,
|
|
|
|
|
},
|
|
|
|
|
{
|
2021-07-23 04:50:23 +08:00
|
|
|
Key: "recordStats",
|
2019-08-28 01:31:42 +08:00
|
|
|
Value: 0,
|
|
|
|
|
},
|
|
|
|
|
}, serverStatus)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return serverStatus, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) gatherReplSetStatus() (*replSetStatus, error) {
|
|
|
|
|
replSetStatus := &replSetStatus{}
|
2021-07-23 04:50:23 +08:00
|
|
|
err := s.runCommand("admin", bson.D{
|
2019-08-28 01:31:42 +08:00
|
|
|
{
|
2021-07-23 04:50:23 +08:00
|
|
|
Key: "replSetGetStatus",
|
2019-08-28 01:31:42 +08:00
|
|
|
Value: 1,
|
|
|
|
|
},
|
|
|
|
|
}, replSetStatus)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return replSetStatus, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) gatherTopStatData() (*topStats, error) {
|
2023-08-09 04:16:40 +08:00
|
|
|
var dest map[string]interface{}
|
2021-07-23 04:50:23 +08:00
|
|
|
err := s.runCommand("admin", bson.D{
|
2021-03-17 04:54:57 +08:00
|
|
|
{
|
2021-07-23 04:50:23 +08:00
|
|
|
Key: "top",
|
2021-03-17 04:54:57 +08:00
|
|
|
Value: 1,
|
|
|
|
|
},
|
2023-08-09 04:16:40 +08:00
|
|
|
}, &dest)
|
2021-07-23 04:50:23 +08:00
|
|
|
if err != nil {
|
2023-08-09 04:16:40 +08:00
|
|
|
return nil, fmt.Errorf("failed running admin cmd: %w", err)
|
2021-07-23 04:50:23 +08:00
|
|
|
}
|
|
|
|
|
|
2023-08-09 04:16:40 +08:00
|
|
|
totals, ok := dest["totals"].(map[string]interface{})
|
|
|
|
|
if !ok {
|
2024-02-09 01:32:30 +08:00
|
|
|
return nil, errors.New("collection totals not found or not a map")
|
2021-07-23 04:50:23 +08:00
|
|
|
}
|
2023-08-09 04:16:40 +08:00
|
|
|
delete(totals, "note")
|
|
|
|
|
|
|
|
|
|
recorded, err := bson.Marshal(totals)
|
2021-03-17 04:54:57 +08:00
|
|
|
if err != nil {
|
2024-02-09 01:32:30 +08:00
|
|
|
return nil, errors.New("unable to marshal totals")
|
2021-03-17 04:54:57 +08:00
|
|
|
}
|
2023-08-09 04:16:40 +08:00
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
topInfo := make(map[string]topStatCollection)
|
2023-08-09 04:16:40 +08:00
|
|
|
if err := bson.Unmarshal(recorded, &topInfo); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed unmarshalling records: %w", err)
|
2021-07-23 04:50:23 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
return &topStats{Totals: topInfo}, nil
|
2021-03-17 04:54:57 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) gatherClusterStatus() (*clusterStatus, error) {
|
2021-07-23 04:50:23 +08:00
|
|
|
chunkCount, err := s.client.Database("config").Collection("chunks").CountDocuments(context.Background(), bson.M{"jumbo": true})
|
2019-08-28 01:31:42 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
return &clusterStatus{
|
2021-07-23 04:50:23 +08:00
|
|
|
JumboChunksCount: chunkCount,
|
2019-08-28 01:31:42 +08:00
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-27 04:32:48 +08:00
|
|
|
func poolStatsCommand(version string) (string, error) {
|
|
|
|
|
majorPart := string(version[0])
|
|
|
|
|
major, err := strconv.ParseInt(majorPart, 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-08 23:37:52 +08:00
|
|
|
if major >= 5 {
|
2021-08-27 04:32:48 +08:00
|
|
|
return "connPoolStats", nil
|
|
|
|
|
}
|
|
|
|
|
return "shardConnPoolStats", nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) gatherShardConnPoolStats(version string) (*shardStats, error) {
|
2021-08-27 04:32:48 +08:00
|
|
|
command, err := poolStatsCommand(version)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
shardStats := &shardStats{}
|
2021-08-27 04:32:48 +08:00
|
|
|
err = s.runCommand("admin", bson.D{
|
2019-08-28 01:31:42 +08:00
|
|
|
{
|
2021-08-27 04:32:48 +08:00
|
|
|
Key: command,
|
2019-08-28 01:31:42 +08:00
|
|
|
Value: 1,
|
|
|
|
|
},
|
|
|
|
|
}, &shardStats)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return shardStats, nil
|
|
|
|
|
}
|
2018-04-07 07:34:47 +08:00
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) gatherDBStats(name string) (*db, error) {
|
|
|
|
|
stats := &dbStatsData{}
|
2021-07-23 04:50:23 +08:00
|
|
|
err := s.runCommand(name, bson.D{
|
2019-08-28 01:31:42 +08:00
|
|
|
{
|
2021-07-23 04:50:23 +08:00
|
|
|
Key: "dbStats",
|
2019-08-28 01:31:42 +08:00
|
|
|
Value: 1,
|
|
|
|
|
},
|
|
|
|
|
}, stats)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
return &db{
|
2019-08-28 01:31:42 +08:00
|
|
|
Name: name,
|
|
|
|
|
DbStatsData: stats,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) getOplogReplLag(collection string) (*oplogStats, error) {
|
2018-04-07 07:34:47 +08:00
|
|
|
query := bson.M{"ts": bson.M{"$exists": true}}
|
|
|
|
|
|
2019-08-28 01:31:42 +08:00
|
|
|
var first oplogEntry
|
2021-07-23 04:50:23 +08:00
|
|
|
firstResult := s.client.Database("local").Collection(collection).FindOne(context.Background(), query, options.FindOne().SetSort(bson.M{"$natural": 1}))
|
|
|
|
|
if firstResult.Err() != nil {
|
|
|
|
|
return nil, firstResult.Err()
|
|
|
|
|
}
|
|
|
|
|
if err := firstResult.Decode(&first); err != nil {
|
2019-08-28 01:31:42 +08:00
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var last oplogEntry
|
2021-07-23 04:50:23 +08:00
|
|
|
lastResult := s.client.Database("local").Collection(collection).FindOne(context.Background(), query, options.FindOne().SetSort(bson.M{"$natural": -1}))
|
|
|
|
|
if lastResult.Err() != nil {
|
|
|
|
|
return nil, lastResult.Err()
|
|
|
|
|
}
|
|
|
|
|
if err := lastResult.Decode(&last); err != nil {
|
2019-08-28 01:31:42 +08:00
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-23 04:50:23 +08:00
|
|
|
firstTime := time.Unix(int64(first.Timestamp.T), 0)
|
|
|
|
|
lastTime := time.Unix(int64(last.Timestamp.T), 0)
|
2024-09-13 04:58:57 +08:00
|
|
|
stats := &oplogStats{
|
2019-08-28 01:31:42 +08:00
|
|
|
TimeDiff: int64(lastTime.Sub(firstTime).Seconds()),
|
|
|
|
|
}
|
|
|
|
|
return stats, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The "oplog.rs" collection is stored on all replica set members.
|
|
|
|
|
//
|
|
|
|
|
// The "oplog.$main" collection is created on the master node of a
|
|
|
|
|
// master-slave replicated deployment. As of MongoDB 3.2, master-slave
|
|
|
|
|
// replication has been deprecated.
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) gatherOplogStats() (*oplogStats, error) {
|
2019-08-28 01:31:42 +08:00
|
|
|
stats, err := s.getOplogReplLag("oplog.rs")
|
|
|
|
|
if err == nil {
|
|
|
|
|
return stats, nil
|
2018-04-07 07:34:47 +08:00
|
|
|
}
|
|
|
|
|
|
2019-08-28 01:31:42 +08:00
|
|
|
return s.getOplogReplLag("oplog.$main")
|
2018-04-07 07:34:47 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
func (s *Server) gatherCollectionStats(colStatsDbs []string) (*colStats, error) {
|
2021-07-23 04:50:23 +08:00
|
|
|
names, err := s.client.ListDatabaseNames(context.Background(), bson.D{})
|
2019-08-15 07:59:02 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
results := &colStats{}
|
2019-09-24 06:39:50 +08:00
|
|
|
for _, dbName := range names {
|
|
|
|
|
if stringInSlice(dbName, colStatsDbs) || len(colStatsDbs) == 0 {
|
2022-06-22 01:16:12 +08:00
|
|
|
// skip views as they fail on collStats below
|
|
|
|
|
filter := bson.M{"type": bson.M{"$in": bson.A{"collection", "timeseries"}}}
|
|
|
|
|
|
2019-08-15 07:59:02 +08:00
|
|
|
var colls []string
|
2022-06-22 01:16:12 +08:00
|
|
|
colls, err = s.client.Database(dbName).ListCollectionNames(context.Background(), filter)
|
2019-08-15 07:59:02 +08:00
|
|
|
if err != nil {
|
2019-09-24 06:39:50 +08:00
|
|
|
s.Log.Errorf("Error getting collection names: %s", err.Error())
|
2019-08-15 07:59:02 +08:00
|
|
|
continue
|
|
|
|
|
}
|
2019-09-24 06:39:50 +08:00
|
|
|
for _, colName := range colls {
|
2024-09-13 04:58:57 +08:00
|
|
|
colStatLine := &colStatsData{}
|
2021-07-23 04:50:23 +08:00
|
|
|
err = s.runCommand(dbName, bson.D{
|
2019-08-15 07:59:02 +08:00
|
|
|
{
|
2021-07-23 04:50:23 +08:00
|
|
|
Key: "collStats",
|
2019-09-24 06:39:50 +08:00
|
|
|
Value: colName,
|
2019-08-15 07:59:02 +08:00
|
|
|
},
|
2019-09-24 06:39:50 +08:00
|
|
|
}, colStatLine)
|
2019-08-15 07:59:02 +08:00
|
|
|
if err != nil {
|
2023-03-02 05:18:35 +08:00
|
|
|
s.authLog(fmt.Errorf("error getting col stats from %q: %w", colName, err))
|
2019-08-15 07:59:02 +08:00
|
|
|
continue
|
|
|
|
|
}
|
2024-09-13 04:58:57 +08:00
|
|
|
collection := &collection{
|
2019-09-24 06:39:50 +08:00
|
|
|
Name: colName,
|
|
|
|
|
DbName: dbName,
|
|
|
|
|
ColStatsData: colStatLine,
|
2019-08-15 07:59:02 +08:00
|
|
|
}
|
|
|
|
|
results.Collections = append(results.Collections, *collection)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return results, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-14 01:47:18 +08:00
|
|
|
func (s *Server) gatherData(acc telegraf.Accumulator, gatherClusterStatus, gatherDbStats, gatherColStats, gatherTopStat bool, colStatsDbs []string) error {
|
2019-08-28 01:31:42 +08:00
|
|
|
serverStatus, err := s.gatherServerStatus()
|
2015-07-07 09:20:11 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2016-04-20 07:16:22 +08:00
|
|
|
|
2019-08-28 01:31:42 +08:00
|
|
|
// Get replica set status, an error indicates that the server is not a
|
|
|
|
|
// member of a replica set.
|
|
|
|
|
replSetStatus, err := s.gatherReplSetStatus()
|
|
|
|
|
if err != nil {
|
2019-09-24 06:39:50 +08:00
|
|
|
s.Log.Debugf("Unable to gather replica set status: %s", err.Error())
|
2019-08-28 01:31:42 +08:00
|
|
|
}
|
2016-04-30 00:40:26 +08:00
|
|
|
|
2019-08-28 01:31:42 +08:00
|
|
|
// Gather the oplog if we are a member of a replica set. Non-replica set
|
|
|
|
|
// members do not have the oplog collections.
|
2024-09-13 04:58:57 +08:00
|
|
|
var oplogStats *oplogStats
|
2019-08-28 01:31:42 +08:00
|
|
|
if replSetStatus != nil {
|
|
|
|
|
oplogStats, err = s.gatherOplogStats()
|
|
|
|
|
if err != nil {
|
2023-03-02 05:18:35 +08:00
|
|
|
s.authLog(fmt.Errorf("unable to get oplog stats: %w", err))
|
2019-08-28 01:31:42 +08:00
|
|
|
}
|
2016-04-30 00:40:26 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
var clusterStatus *clusterStatus
|
2020-05-22 15:11:00 +08:00
|
|
|
if gatherClusterStatus {
|
|
|
|
|
status, err := s.gatherClusterStatus()
|
|
|
|
|
if err != nil {
|
|
|
|
|
s.Log.Debugf("Unable to gather cluster status: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
|
clusterStatus = status
|
2018-02-21 05:55:56 +08:00
|
|
|
}
|
2016-07-19 19:47:12 +08:00
|
|
|
|
2021-08-27 04:32:48 +08:00
|
|
|
shardStats, err := s.gatherShardConnPoolStats(serverStatus.Version)
|
2019-08-28 01:31:42 +08:00
|
|
|
if err != nil {
|
2023-03-02 05:18:35 +08:00
|
|
|
s.authLog(fmt.Errorf("unable to gather shard connection pool stats: %w", err))
|
2019-08-28 01:31:42 +08:00
|
|
|
}
|
2018-04-07 07:34:47 +08:00
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
var collectionStats *colStats
|
2019-09-10 06:55:46 +08:00
|
|
|
if gatherColStats {
|
|
|
|
|
stats, err := s.gatherCollectionStats(colStatsDbs)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
collectionStats = stats
|
2019-08-28 01:31:42 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
dbStats := &dbStats{}
|
2019-08-28 01:31:42 +08:00
|
|
|
if gatherDbStats {
|
2021-07-23 04:50:23 +08:00
|
|
|
names, err := s.client.ListDatabaseNames(context.Background(), bson.D{})
|
2016-07-19 19:47:12 +08:00
|
|
|
if err != nil {
|
2019-08-28 01:31:42 +08:00
|
|
|
return err
|
2016-07-19 19:47:12 +08:00
|
|
|
}
|
2019-08-28 01:31:42 +08:00
|
|
|
|
|
|
|
|
for _, name := range names {
|
|
|
|
|
db, err := s.gatherDBStats(name)
|
2016-07-19 19:47:12 +08:00
|
|
|
if err != nil {
|
2019-09-24 06:39:50 +08:00
|
|
|
s.Log.Debugf("Error getting db stats from %q: %s", name, err.Error())
|
2016-07-19 19:47:12 +08:00
|
|
|
}
|
2019-08-28 01:31:42 +08:00
|
|
|
dbStats.Dbs = append(dbStats.Dbs, *db)
|
2016-07-19 19:47:12 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
topStatData := &topStats{}
|
2021-03-17 04:54:57 +08:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-13 04:58:57 +08:00
|
|
|
result := &mongoStatus{
|
2019-08-28 01:31:42 +08:00
|
|
|
ServerStatus: serverStatus,
|
|
|
|
|
ReplSetStatus: replSetStatus,
|
|
|
|
|
ClusterStatus: clusterStatus,
|
|
|
|
|
DbStats: dbStats,
|
|
|
|
|
ColStats: collectionStats,
|
|
|
|
|
ShardStats: shardStats,
|
2018-04-07 07:34:47 +08:00
|
|
|
OplogStats: oplogStats,
|
2021-03-17 04:54:57 +08:00
|
|
|
TopStats: topStatData,
|
2016-04-20 07:16:22 +08:00
|
|
|
}
|
|
|
|
|
|
2015-07-07 09:20:11 +08:00
|
|
|
result.SampleTime = time.Now()
|
|
|
|
|
if s.lastResult != nil && result != nil {
|
|
|
|
|
duration := result.SampleTime.Sub(s.lastResult.SampleTime)
|
|
|
|
|
durationInSeconds := int64(duration.Seconds())
|
|
|
|
|
if durationInSeconds == 0 {
|
|
|
|
|
durationInSeconds = 1
|
|
|
|
|
}
|
|
|
|
|
data := NewMongodbData(
|
2021-07-23 04:50:23 +08:00
|
|
|
NewStatLine(*s.lastResult, *result, s.hostname, true, durationInSeconds),
|
2015-07-07 09:20:11 +08:00
|
|
|
s.getDefaultTags(),
|
|
|
|
|
)
|
2015-12-20 04:31:22 +08:00
|
|
|
data.AddDefaultStats()
|
2016-07-19 19:47:12 +08:00
|
|
|
data.AddDbStats()
|
2019-07-31 12:36:19 +08:00
|
|
|
data.AddColStats()
|
2018-04-11 08:10:29 +08:00
|
|
|
data.AddShardHostStats()
|
2021-03-17 04:54:57 +08:00
|
|
|
data.AddTopStats()
|
2015-12-20 04:31:22 +08:00
|
|
|
data.flush(acc)
|
2015-07-07 09:20:11 +08:00
|
|
|
}
|
2019-08-28 01:31:42 +08:00
|
|
|
|
|
|
|
|
s.lastResult = result
|
2015-07-07 09:20:11 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
2019-07-31 12:36:19 +08:00
|
|
|
|
|
|
|
|
func stringInSlice(a string, list []string) bool {
|
|
|
|
|
for _, b := range list {
|
|
|
|
|
if b == a {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|