-
Notifications
You must be signed in to change notification settings - Fork 450
PMM-1764 Various small improvements #85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b836caa
b6b8e6e
f08e2e2
7c439c1
24a1cbc
2e2b7e9
dfde402
e08ab38
73540ad
9a29c00
b912f8c
7da4844
fbe1f0c
0cf5091
eaf2f65
a804b8e
f58598a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,15 @@ | |
|
|
||
| ## v0.4.0 (not released yet) | ||
|
|
||
| * New flags `-collect.database` and `-collect.collection` can be used to enable collection of database and collection | ||
| metrics. They are disabled by default. | ||
| * MongoDB connections are now kept between the scrapes. New flag `-mongodb.max-connections` (with the default value `1`) | ||
| controls the maximum number of established connections. | ||
| * Add standard metrics: | ||
| * `mongodb_scrape_errors_total` | ||
| * `mongodb_up` | ||
| * Some queries now contain [cursor comments](https://www.percona.com/blog/2017/06/21/tracing-mongodb-queries-to-code-with-cursor-comments/) | ||
| with source code locations. | ||
| * Go vendoring switched to [dep](https://github.com/golang/dep). | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this is not the part of this PR but when and why we switched to dep for this repo? Upstream still uses
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are on our own now. :) |
||
|
|
||
| ## v0.3.1 (2017-09-08) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,6 +64,12 @@ db.getSiblingDB("admin").createUser({ | |
| export MONGODB_URL=mongodb://mongodb_exporter:s3cr3tpassw0rd@localhost:27017 | ||
| ``` | ||
|
|
||
| If you use [x.509 Certificates to Authenticate Clients](https://docs.mongodb.com/manual/tutorial/configure-x509-client-authentication/), pass in username and `authMechanism` via [connection options](https://docs.mongodb.com/manual/reference/connection-string/#connections-connection-options) to the MongoDB uri. Eg: | ||
|
|
||
| ``` | ||
| mongodb://CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry@localhost:27017/?authMechanism=MONGODB-X509 | ||
| ``` | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did we test that? I know it's
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's wasn't required. |
||
| ## Note about how this works | ||
|
|
||
| Point the process to any mongo port and it will detect if it is a mongos, replicaset member, or stand alone mongod and return the appropriate metrics for that type of node. This was done to preent the need to an exporter per type of process. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| package collector_mongod | ||
|
|
||
| import ( | ||
| "github.com/prometheus/client_golang/prometheus" | ||
| "github.com/prometheus/common/log" | ||
| "gopkg.in/mgo.v2" | ||
| "gopkg.in/mgo.v2/bson" | ||
| ) | ||
|
|
||
| var ( | ||
| collectionSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db_coll", | ||
| Name: "size", | ||
| Help: "The total size in memory of all records in a collection", | ||
| }, []string{"db", "coll"}) | ||
| collectionObjectCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db_coll", | ||
| Name: "count", | ||
| Help: "The number of objects or documents in this collection", | ||
| }, []string{"db", "coll"}) | ||
| collectionAvgObjSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db_coll", | ||
| Name: "avgobjsize", | ||
| Help: "The average size of an object in the collection (plus any padding)", | ||
| }, []string{"db", "coll"}) | ||
| collectionStorageSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db_coll", | ||
| Name: "storage_size", | ||
| Help: "The total amount of storage allocated to this collection for document storage", | ||
| }, []string{"db", "coll"}) | ||
| collectionIndexes = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db_coll", | ||
| Name: "indexes", | ||
| Help: "The number of indexes on the collection", | ||
| }, []string{"db", "coll"}) | ||
| collectionIndexesSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db_coll", | ||
| Name: "indexes_size", | ||
| Help: "The total size of all indexes", | ||
| }, []string{"db", "coll"}) | ||
| ) | ||
|
|
||
| // CollectionStatList contains stats from all collections | ||
| type CollectionStatList struct { | ||
| Members []CollectionStatus | ||
| } | ||
|
|
||
| // CollectionStatus represents stats about a collection in database (mongod and raw from mongos) | ||
| type CollectionStatus struct { | ||
| Database string | ||
| Name string | ||
| Size int `bson:"size,omitempty"` | ||
| Count int `bson:"count,omitempty"` | ||
| AvgObjSize int `bson:"avgObjSize,omitempty"` | ||
| StorageSize int `bson:"storageSize,omitempty"` | ||
| Indexes int `bson:"indexSizes,omitempty"` | ||
| IndexesSize int `bson:"totalIndexSize,omitempty"` | ||
| } | ||
|
|
||
| // Export exports database stats to prometheus | ||
| func (collStatList *CollectionStatList) Export(ch chan<- prometheus.Metric) { | ||
| for _, member := range collStatList.Members { | ||
| ls := prometheus.Labels{ | ||
| "db": member.Database, | ||
| "coll": member.Name, | ||
| } | ||
| collectionSize.With(ls).Set(float64(member.Size)) | ||
| collectionObjectCount.With(ls).Set(float64(member.Count)) | ||
| collectionAvgObjSize.With(ls).Set(float64(member.AvgObjSize)) | ||
| collectionStorageSize.With(ls).Set(float64(member.StorageSize)) | ||
| collectionIndexes.With(ls).Set(float64(member.Indexes)) | ||
| collectionIndexesSize.With(ls).Set(float64(member.IndexesSize)) | ||
| } | ||
| collectionSize.Collect(ch) | ||
| collectionObjectCount.Collect(ch) | ||
| collectionAvgObjSize.Collect(ch) | ||
| collectionStorageSize.Collect(ch) | ||
| collectionIndexes.Collect(ch) | ||
| collectionIndexesSize.Collect(ch) | ||
| } | ||
|
|
||
| // Describe describes database stats for prometheus | ||
| func (collStatList *CollectionStatList) Describe(ch chan<- *prometheus.Desc) { | ||
| collectionSize.Describe(ch) | ||
| collectionObjectCount.Describe(ch) | ||
| collectionAvgObjSize.Describe(ch) | ||
| collectionStorageSize.Describe(ch) | ||
| collectionIndexes.Describe(ch) | ||
| collectionIndexesSize.Describe(ch) | ||
| } | ||
|
|
||
| // GetDatabaseStatus returns stats for a given database | ||
| func GetCollectionStatList(session *mgo.Session) *CollectionStatList { | ||
| collectionStatList := &CollectionStatList{} | ||
| database_names, err := session.DatabaseNames() | ||
| if err != nil { | ||
| log.Error("Failed to get database names") | ||
| return nil | ||
| } | ||
| for _, db := range database_names { | ||
| collection_names, err := session.DB(db).CollectionNames() | ||
| if err != nil { | ||
| log.Error("Failed to get collection names for db=" + db) | ||
| return nil | ||
| } | ||
| for _, collection_name := range collection_names { | ||
| collStatus := CollectionStatus{} | ||
| err := session.DB(db).Run(bson.D{{"collStats", collection_name}, {"scale", 1}}, &collStatus) | ||
| collStatus.Database = db | ||
| collStatus.Name = collection_name | ||
| if err != nil { | ||
| log.Error("Failed to get collection status.") | ||
| return nil | ||
| } | ||
| collectionStatList.Members = append(collectionStatList.Members, collStatus) | ||
| } | ||
| } | ||
|
|
||
| return collectionStatList | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| package collector_mongod | ||
|
|
||
| import ( | ||
| "github.com/prometheus/client_golang/prometheus" | ||
| "github.com/prometheus/common/log" | ||
| "gopkg.in/mgo.v2" | ||
| "gopkg.in/mgo.v2/bson" | ||
| ) | ||
|
|
||
| var ( | ||
| indexSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db", | ||
| Name: "index_size_bytes", | ||
| Help: "The total size in bytes of all indexes created on this database", | ||
| }, []string{"db"}) | ||
| dataSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db", | ||
| Name: "data_size_bytes", | ||
| Help: "The total size in bytes of the uncompressed data held in this database", | ||
| }, []string{"db"}) | ||
| collectionsTotal = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db", | ||
| Name: "collections_total", | ||
| Help: "Contains a count of the number of collections in that database", | ||
| }, []string{"db"}) | ||
| indexesTotal = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db", | ||
| Name: "indexes_total", | ||
| Help: "Contains a count of the total number of indexes across all collections in the database", | ||
| }, []string{"db"}) | ||
| objectsTotal = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "db", | ||
| Name: "objects_total", | ||
| Help: "Contains a count of the number of objects (i.e. documents) in the database across all collections", | ||
| }, []string{"db"}) | ||
| ) | ||
|
|
||
| // DatabaseStatList contains stats from all databases | ||
| type DatabaseStatList struct { | ||
| Members []DatabaseStatus | ||
| } | ||
|
|
||
| // DatabaseStatus represents stats about a database (mongod and raw from mongos) | ||
| type DatabaseStatus struct { | ||
| Name string `bson:"db,omitempty"` | ||
| IndexSize int `bson:"indexSize,omitempty"` | ||
| DataSize int `bson:"dataSize,omitempty"` | ||
| Collections int `bson:"collections,omitempty"` | ||
| Objects int `bson:"objects,omitempty"` | ||
| Indexes int `bson:"indexes,omitempty"` | ||
| } | ||
|
|
||
| // Export exports database stats to prometheus | ||
| func (dbStatList *DatabaseStatList) Export(ch chan<- prometheus.Metric) { | ||
| for _, member := range dbStatList.Members { | ||
| ls := prometheus.Labels{"db": member.Name} | ||
| indexSize.With(ls).Set(float64(member.IndexSize)) | ||
| dataSize.With(ls).Set(float64(member.DataSize)) | ||
| collectionsTotal.With(ls).Set(float64(member.Collections)) | ||
| indexesTotal.With(ls).Set(float64(member.Indexes)) | ||
| objectsTotal.With(ls).Set(float64(member.Objects)) | ||
| } | ||
| indexSize.Collect(ch) | ||
| dataSize.Collect(ch) | ||
| collectionsTotal.Collect(ch) | ||
| indexesTotal.Collect(ch) | ||
| objectsTotal.Collect(ch) | ||
|
|
||
| } | ||
|
|
||
| // Describe describes database stats for prometheus | ||
| func (dbStatList *DatabaseStatList) Describe(ch chan<- *prometheus.Desc) { | ||
| indexSize.Describe(ch) | ||
| dataSize.Describe(ch) | ||
| collectionsTotal.Describe(ch) | ||
| indexesTotal.Describe(ch) | ||
| objectsTotal.Describe(ch) | ||
| } | ||
|
|
||
| // GetDatabaseStatList returns stats for all databases | ||
| func GetDatabaseStatList(session *mgo.Session) *DatabaseStatList { | ||
| dbStatList := &DatabaseStatList{} | ||
| database_names, err := session.DatabaseNames() | ||
| if err != nil { | ||
| log.Error("Failed to get database names") | ||
| return nil | ||
| } | ||
| for _, db := range database_names { | ||
| dbStatus := DatabaseStatus{} | ||
| err := session.DB(db).Run(bson.D{{"dbStats", 1}, {"scale", 1}}, &dbStatus) | ||
| if err != nil { | ||
| log.Error("Failed to get database status.") | ||
| return nil | ||
| } | ||
| dbStatList.Members = append(dbStatList.Members, dbStatus) | ||
| } | ||
|
|
||
| return dbStatList | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,12 +31,6 @@ var ( | |
| Name: "total", | ||
| Help: "The value of totalTime represents the time, in microseconds, since the database last started and creation of the globalLock. This is roughly equivalent to total server uptime", | ||
| }) | ||
| globalLockLockTotal = prometheus.NewCounter(prometheus.CounterOpts{ | ||
| Namespace: Namespace, | ||
| Subsystem: "global_lock", | ||
| Name: "lock_total", | ||
| Help: "The value of lockTime represents the time, in microseconds, since the database last started, that the globalLock has been held", | ||
| }) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reason for removal?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That variable wasn't referenced/used. |
||
| ) | ||
| var ( | ||
| globalLockCurrentQueue = prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this somewhere requested? Jira issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's #84.