diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 8911b84ee95..e82c45fe395 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -267,6 +267,10 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff] - Added Palo Alto Networks module {pull}40686[40686] - Restore docker.network.in.* and docker.network.out.* fields in docker module {pull}40968[40968] - Collect .NET CLR (IIS) Memory, Exceptions and LocksAndThreads metrics {pull}41929[41929] +- Added `tier_preference`, `creation_date` and `version` fields to the `elasticsearch.index` metricset. {pull}41944[41944] +- Add `use_performance_counters` to collect CPU metrics using performance counters on Windows for `system/cpu` and `system/core` {pull}41965[41965] +- Add support of additional `collstats` metrics in mongodb module. {pull}42171[42171] +- Preserve queries for debugging when `merge_results: true` in SQL module {pull}42271[42271] *Metricbeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index fca8cdbeda3..09c68fa85f8 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -50967,6 +50967,87 @@ type: long Number of database commands executed. +type: long + +-- + + +*`mongodb.collstats.stats.stats.size`*:: ++ +-- +The total uncompressed size in memory of all records in a collection. + + +type: long + +-- + +*`mongodb.collstats.stats.stats.count`*:: ++ +-- +The number of objects or documents in this collection. + + +type: long + +-- + +*`mongodb.collstats.stats.stats.avgObjSize`*:: ++ +-- +The average size of an object in the collection (in bytes). + + +type: long + +-- + +*`mongodb.collstats.stats.stats.storageSize`*:: ++ +-- +The total amount of storage allocated to this collection for document storage (in bytes). + + +type: long + +-- + +*`mongodb.collstats.stats.stats.totalIndexSize`*:: ++ +-- +The total size of all indexes (in bytes). + + +type: long + +-- + +*`mongodb.collstats.stats.stats.totalSize`*:: ++ +-- +The sum of the storageSize and totalIndexSize (in bytes). + + +type: long + +-- + +*`mongodb.collstats.stats.stats.max`*:: ++ +-- +Shows the maximum number of documents that may be present in a capped collection. + + +type: long + +-- + +*`mongodb.collstats.stats.stats.nindexes`*:: ++ +-- +The number of indexes on the collection. All collections have at least one index on the _id field. + + type: long -- diff --git a/metricbeat/module/mongodb/collstats/_meta/data.json b/metricbeat/module/mongodb/collstats/_meta/data.json index 0d77b425007..0eceb667ba8 100644 --- a/metricbeat/module/mongodb/collstats/_meta/data.json +++ b/metricbeat/module/mongodb/collstats/_meta/data.json @@ -69,6 +69,16 @@ "time": { "us": 0 } + }, + "stats": { + "totalSize": 8192, + "max": 5000, + "nindexes": 1, + "size": 36, + "count": 1, + "avgObjSize": 36, + "storageSize": 4096, + "totalIndexSize": 4096 } } }, @@ -76,4 +86,4 @@ "address": "172.28.0.5:27017", "type": "mongodb" } -} \ No newline at end of file +} diff --git a/metricbeat/module/mongodb/collstats/_meta/fields.yml b/metricbeat/module/mongodb/collstats/_meta/fields.yml index 5b255dba1e3..a4a09f8d090 100644 --- a/metricbeat/module/mongodb/collstats/_meta/fields.yml +++ b/metricbeat/module/mongodb/collstats/_meta/fields.yml @@ -102,3 +102,39 @@ type: long description: > Number of database commands executed. + + - name: stats + type: group + fields: + - name: stats.size + type: long + description: > + The total uncompressed size in memory of all records in a collection. + - name: stats.count + type: long + description: > + The number of objects or documents in this collection. + - name: stats.avgObjSize + type: long + description: > + The average size of an object in the collection (in bytes). + - name: stats.storageSize + type: long + description: > + The total amount of storage allocated to this collection for document storage (in bytes). + - name: stats.totalIndexSize + type: long + description: > + The total size of all indexes (in bytes). + - name: stats.totalSize + type: long + description: > + The sum of the storageSize and totalIndexSize (in bytes). + - name: stats.max + type: long + description: > + Shows the maximum number of documents that may be present in a capped collection. + - name: stats.nindexes + type: long + description: > + The number of indexes on the collection. All collections have at least one index on the _id field. diff --git a/metricbeat/module/mongodb/collstats/collstats.go b/metricbeat/module/mongodb/collstats/collstats.go index 43b05ed30ec..85bbc1692a6 100644 --- a/metricbeat/module/mongodb/collstats/collstats.go +++ b/metricbeat/module/mongodb/collstats/collstats.go @@ -22,10 +22,13 @@ import ( "errors" "fmt" + "golang.org/x/sync/errgroup" + "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/module/mongodb" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" ) func init() { @@ -70,10 +73,6 @@ func (m *Metricset) Fetch(reporter mb.ReporterV2) error { } }() - if err != nil { - return fmt.Errorf("could not get a list of databases: %w", err) - } - // This info is only stored in 'admin' database db := client.Database("admin") res := db.RunCommand(context.Background(), bson.D{bson.E{Key: "top"}}) @@ -92,10 +91,19 @@ func (m *Metricset) Fetch(reporter mb.ReporterV2) error { totals, ok := result["totals"].(map[string]interface{}) if !ok { - return errors.New("collection 'totals' are not a map") + return errors.New("collection 'totals' is not a map") + } + + if err = res.Err(); err != nil { + return fmt.Errorf("'top' command failed: %w", err) } + collStatsErrGroup := &errgroup.Group{} + collStatsErrGroup.SetLimit(10) // limit number of goroutines running at the same time + for group, info := range totals { + group := group // make sure it works properly on older Go versions + if group == "note" { continue } @@ -106,16 +114,60 @@ func (m *Metricset) Fetch(reporter mb.ReporterV2) error { continue } - event, err := eventMapping(group, infoMap) - if err != nil { - reporter.Error(fmt.Errorf("mapping of the event data filed: %w", err)) - continue - } + collStatsErrGroup.Go(func() error { + names, err := splitKey(group) + if err != nil { + reporter.Error(fmt.Errorf("splitting a collection key failed: %w", err)) + + // the error is captured by reporter. no need to return it (to avoid double reporting of the same error) + return nil + } + + database, collection := names[0], names[1] - reporter.Event(mb.Event{ - MetricSetFields: event, + collStats, err := fetchCollStats(client, database, collection) + if err != nil { + reporter.Error(fmt.Errorf("fetching collStats failed: %w", err)) + + // the error is captured by reporter. no need to return it (to avoid double reporting of the same error) + return nil + } + + infoMap["stats"] = collStats + + event, err := eventMapping(group, infoMap) + if err != nil { + reporter.Error(fmt.Errorf("mapping of the event data failed: %w", err)) + + // the error is captured by reporter. no need to return it (to avoid double reporting of the same error) + return nil + } + + reporter.Event(mb.Event{ + MetricSetFields: event, + }) + + return nil }) } + if err := collStatsErrGroup.Wait(); err != nil { + return fmt.Errorf("error processing mongodb collstats: %w", err) + } + return nil } + +func fetchCollStats(client *mongo.Client, dbName, collectionName string) (map[string]interface{}, error) { + db := client.Database(dbName) + collStats := db.RunCommand(context.Background(), bson.M{"collStats": collectionName}) + if err := collStats.Err(); err != nil { + return nil, fmt.Errorf("collStats command failed: %w", err) + } + var statsRes map[string]interface{} + if err := collStats.Decode(&statsRes); err != nil { + return nil, fmt.Errorf("could not decode mongo response for database=%s, collection=%s: %w", dbName, collectionName, err) + } + + return statsRes, nil +} diff --git a/metricbeat/module/mongodb/collstats/data.go b/metricbeat/module/mongodb/collstats/data.go index c62379d24a3..e9600fb83ec 100644 --- a/metricbeat/module/mongodb/collstats/data.go +++ b/metricbeat/module/mongodb/collstats/data.go @@ -25,15 +25,17 @@ import ( ) func eventMapping(key string, data mapstr.M) (mapstr.M, error) { - names := strings.SplitN(key, ".", 2) - - if len(names) < 2 { - return nil, errors.New("collection name invalid") + names, err := splitKey(key) + if err != nil { + return nil, err } + // NOTE: splitKey handles the case where the collection can have "." in the name + database, collection := names[0], names[1] + event := mapstr.M{ - "db": names[0], - "collection": names[1], + "db": database, + "collection": collection, "name": key, "total": mapstr.M{ "time": mapstr.M{ @@ -91,6 +93,16 @@ func eventMapping(key string, data mapstr.M) (mapstr.M, error) { }, "count": mustGetMapStrValue(data, "commands.count"), }, + "stats": mapstr.M{ + "size": mustGetMapStrValue(data, "stats.size"), + "count": mustGetMapStrValue(data, "stats.count"), + "avgObjSize": mustGetMapStrValue(data, "stats.avgObjSize"), + "storageSize": mustGetMapStrValue(data, "stats.storageSize"), + "totalIndexSize": mustGetMapStrValue(data, "stats.totalIndexSize"), + "totalSize": mustGetMapStrValue(data, "stats.totalSize"), + "max": mustGetMapStrValue(data, "stats.max"), + "nindexes": mustGetMapStrValue(data, "stats.nindexes"), + }, } return event, nil @@ -100,3 +112,13 @@ func mustGetMapStrValue(m mapstr.M, key string) interface{} { v, _ := m.GetValue(key) return v } + +func splitKey(key string) ([]string, error) { + dbColl := strings.SplitN(key, ".", 2) + + if len(dbColl) < 2 { + return nil, errors.New("collection name invalid") + } + + return dbColl, nil +} diff --git a/metricbeat/module/mongodb/collstats/data_test.go b/metricbeat/module/mongodb/collstats/data_test.go index a921d14d727..f10e8aa0a8c 100644 --- a/metricbeat/module/mongodb/collstats/data_test.go +++ b/metricbeat/module/mongodb/collstats/data_test.go @@ -21,7 +21,7 @@ package collstats import ( "encoding/json" - "io/ioutil" + "os" "testing" "github.com/stretchr/testify/assert" @@ -31,7 +31,7 @@ import ( func TestEventMapping(t *testing.T) { - content, err := ioutil.ReadFile("./_meta/test/input.json") + content, err := os.ReadFile("./_meta/test/input.json") assert.NoError(t, err) data := mapstr.M{} diff --git a/metricbeat/module/mongodb/fields.go b/metricbeat/module/mongodb/fields.go index 46b78da7a1c..99e278155b0 100644 --- a/metricbeat/module/mongodb/fields.go +++ b/metricbeat/module/mongodb/fields.go @@ -32,5 +32,5 @@ func init() { // AssetMongodb returns asset data. // This is the base64 encoded zlib format compressed contents of module/mongodb. func AssetMongodb() string { - return "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" + return "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" }