Skip to content

Commit 4eb435b

Browse files
PMM-9471 Context deadline (#420)
* PMM-9471 Cover case with limit collections -1 (auto). * PMM-9471 Logic, nil fixies. Reflect timeout from VM. * PMM-9471 Revert dynamic timeout for now. * Revert "PMM-9471 Revert dynamic timeout for now." This reverts commit 02cb9b7. * PMM-9471 New default timeout. * PMM-9471 Fix missing flag. * PMM-9471 support of collect[] query parameter * PMM-9471 Another changes in exporter. Context background. Co-authored-by: Nurlan Moldomurov <[email protected]>
1 parent 16a3f51 commit 4eb435b

File tree

4 files changed

+66
-27
lines changed

4 files changed

+66
-27
lines changed

exporter/diagnostic_data_collector.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ func (d *diagnosticDataCollector) Collect(ch chan<- prometheus.Metric) {
5353
d.logger.Errorf("cannot run getDiagnosticData: %s", err)
5454
}
5555

56+
if m == nil || m["data"] == nil {
57+
d.logger.Error("cannot run getDiagnosticData: response is empty")
58+
}
59+
5660
m, ok := m["data"].(bson.M)
5761
if !ok {
5862
err := errors.Wrapf(errUnexpectedDataType, "%T for data field", m["data"])

exporter/exporter.go

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"net/http"
2424
"os"
25+
"strconv"
2526
"sync"
2627
"time"
2728

@@ -96,7 +97,7 @@ func New(opts *Opts) *Exporter {
9697
opts: opts,
9798
webListenAddress: opts.WebListenAddress,
9899
lock: &sync.Mutex{},
99-
totalCollectionsCount: -1, // not calculated yet. waiting the db connection.
100+
totalCollectionsCount: -1, // Not calculated yet. waiting the db connection.
100101
}
101102
// Try initial connect. Connection will be retried with every scrape.
102103
go func() {
@@ -116,7 +117,7 @@ func (e *Exporter) getTotalCollectionsCount() int {
116117
return e.totalCollectionsCount
117118
}
118119

119-
func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topologyInfo labelsGetter) *prometheus.Registry {
120+
func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topologyInfo labelsGetter, requestOpts Opts) *prometheus.Registry {
120121
registry := prometheus.NewRegistry()
121122

122123
gc := generalCollector{
@@ -135,11 +136,11 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
135136
e.logger.Errorf("Cannot get node type to check if this is a mongos: %s", err)
136137
}
137138

138-
// enable collectors like collstats and indexstats depending on the number of collections
139+
// Enable collectors like collstats and indexstats depending on the number of collections
139140
// present in the database.
140141
limitsOk := false
141-
if e.opts.CollStatsLimit == 0 || // Unlimited
142-
(e.getTotalCollectionsCount() > 0 && e.getTotalCollectionsCount() < e.opts.CollStatsLimit) {
142+
if e.opts.CollStatsLimit <= 0 || // Unlimited
143+
e.getTotalCollectionsCount() <= e.opts.CollStatsLimit {
143144
limitsOk = true
144145
}
145146

@@ -149,12 +150,14 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
149150
}
150151
e.opts.EnableDiagnosticData = true
151152
e.opts.EnableDBStats = true
153+
e.opts.EnableCollStats = true
152154
e.opts.EnableTopMetrics = true
153155
e.opts.EnableReplicasetStatus = true
156+
e.opts.EnableIndexStats = true
154157
}
155158

156-
// if we manually set the collection names we want or auto discovery is set
157-
if (len(e.opts.CollStatsNamespaces) > 0 || e.opts.DiscoveringMode) && e.opts.EnableCollStats && limitsOk {
159+
// If we manually set the collection names we want or auto discovery is set.
160+
if (len(e.opts.CollStatsNamespaces) > 0 || e.opts.DiscoveringMode) && e.opts.EnableCollStats && limitsOk && requestOpts.EnableCollStats {
158161
cc := collstatsCollector{
159162
ctx: ctx,
160163
client: client,
@@ -167,8 +170,8 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
167170
registry.MustRegister(&cc)
168171
}
169172

170-
// if we manually set the collection names we want or auto discovery is set
171-
if (len(e.opts.IndexStatsCollections) > 0 || e.opts.DiscoveringMode) && e.opts.EnableIndexStats && limitsOk {
173+
// If we manually set the collection names we want or auto discovery is set.
174+
if (len(e.opts.IndexStatsCollections) > 0 || e.opts.DiscoveringMode) && e.opts.EnableIndexStats && limitsOk && requestOpts.EnableIndexStats {
172175
ic := indexstatsCollector{
173176
ctx: ctx,
174177
client: client,
@@ -180,7 +183,7 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
180183
registry.MustRegister(&ic)
181184
}
182185

183-
if e.opts.EnableDiagnosticData {
186+
if e.opts.EnableDiagnosticData && requestOpts.EnableDiagnosticData {
184187
ddc := diagnosticDataCollector{
185188
ctx: ctx,
186189
client: client,
@@ -191,7 +194,7 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
191194
registry.MustRegister(&ddc)
192195
}
193196

194-
if e.opts.EnableDBStats {
197+
if e.opts.EnableDBStats && requestOpts.EnableDBStats {
195198
cc := dbstatsCollector{
196199
ctx: ctx,
197200
client: client,
@@ -202,7 +205,7 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
202205
registry.MustRegister(&cc)
203206
}
204207

205-
if e.opts.EnableTopMetrics && nodeType != typeMongos {
208+
if e.opts.EnableTopMetrics && nodeType != typeMongos && requestOpts.EnableTopMetrics {
206209
tc := topCollector{
207210
ctx: ctx,
208211
client: client,
@@ -213,8 +216,8 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
213216
registry.MustRegister(&tc)
214217
}
215218

216-
// replSetGetStatus is not supported through mongos
217-
if e.opts.EnableReplicasetStatus && nodeType != typeMongos {
219+
// replSetGetStatus is not supported through mongos.
220+
if e.opts.EnableReplicasetStatus && nodeType != typeMongos && requestOpts.EnableReplicasetStatus {
218221
rsgsc := replSetGetStatusCollector{
219222
ctx: ctx,
220223
client: client,
@@ -230,17 +233,17 @@ func (e *Exporter) makeRegistry(ctx context.Context, client *mongo.Client, topol
230233

231234
func (e *Exporter) getClient(ctx context.Context) (*mongo.Client, error) {
232235
if e.opts.GlobalConnPool {
233-
// get global client. Maybe it must be initialized first.
236+
// Get global client. Maybe it must be initialized first.
234237
// Initialization is retried with every scrape until it succeeds once.
235238
e.clientMu.Lock()
236239
defer e.clientMu.Unlock()
237240

238-
// if client is already initialized, return it
241+
// If client is already initialized, return it.
239242
if e.client != nil {
240243
return e.client, nil
241244
}
242245

243-
client, err := connect(ctx, e.opts.URI, e.opts.DirectConnect)
246+
client, err := connect(context.Background(), e.opts.URI, e.opts.DirectConnect)
244247
if err != nil {
245248
return nil, err
246249
}
@@ -249,7 +252,7 @@ func (e *Exporter) getClient(ctx context.Context) (*mongo.Client, error) {
249252
return client, nil
250253
}
251254

252-
// !e.opts.GlobalConnPool: create new client for every scrape
255+
// !e.opts.GlobalConnPool: create new client for every scrape.
253256
client, err := connect(ctx, e.opts.URI, e.opts.DirectConnect)
254257
if err != nil {
255258
return nil, err
@@ -259,19 +262,50 @@ func (e *Exporter) getClient(ctx context.Context) (*mongo.Client, error) {
259262
}
260263

261264
// Handler returns an http.Handler that serves metrics. Can be used instead of
262-
// Run for hooking up custom HTTP servers.
265+
// run for hooking up custom HTTP servers.
263266
func (e *Exporter) Handler() http.Handler {
264267
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
268+
seconds, err := strconv.Atoi(r.Header.Get("X-Prometheus-Scrape-Timeout-Seconds"))
269+
// To support also older ones vmagents.
270+
if err != nil {
271+
seconds = 10
272+
}
273+
265274
var client *mongo.Client
266-
ctx, cancel := context.WithTimeout(r.Context(), time.Second)
275+
ctx, cancel := context.WithTimeout(r.Context(), time.Duration(seconds)*time.Second)
267276
defer cancel()
268277

269-
client, err := e.getClient(ctx)
278+
filters := r.URL.Query()["collect[]"]
279+
280+
requestOpts := Opts{}
281+
282+
if len(filters) == 0 {
283+
requestOpts = *e.opts
284+
}
285+
286+
for _, filter := range filters {
287+
switch filter {
288+
case "diagnosticdata":
289+
requestOpts.EnableDiagnosticData = true
290+
case "replicasetstatus":
291+
requestOpts.EnableReplicasetStatus = true
292+
case "dbstats":
293+
requestOpts.EnableDBStats = true
294+
case "topmetrics":
295+
requestOpts.EnableTopMetrics = true
296+
case "indexstats":
297+
requestOpts.EnableIndexStats = true
298+
case "collstats":
299+
requestOpts.EnableCollStats = true
300+
}
301+
}
302+
303+
client, err = e.getClient(ctx)
270304
if err != nil {
271305
e.logger.Errorf("Cannot connect to MongoDB: %v", err)
272306
}
273307

274-
if client != nil && e.getTotalCollectionsCount() < 0 {
308+
if client != nil && e.getTotalCollectionsCount() <= 0 {
275309
count, err := nonSystemCollectionsCount(ctx, client, nil, nil)
276310
if err == nil {
277311
e.lock.Lock()
@@ -280,7 +314,7 @@ func (e *Exporter) Handler() http.Handler {
280314
}
281315
}
282316

283-
// Close client after usage
317+
// Close client after usage.
284318
if !e.opts.GlobalConnPool {
285319
defer func() {
286320
if client != nil {
@@ -292,7 +326,7 @@ func (e *Exporter) Handler() http.Handler {
292326
}()
293327
}
294328

295-
// topology can change between requests, so we need to get it every time
329+
// Topology can change between requests, so we need to get it every time.
296330
var ti *topologyInfo
297331
if client != nil {
298332
ti, err = newTopologyInfo(ctx, client)
@@ -306,7 +340,7 @@ func (e *Exporter) Handler() http.Handler {
306340
}
307341
}
308342

309-
registry := e.makeRegistry(ctx, client, ti)
343+
registry := e.makeRegistry(ctx, client, ti, requestOpts)
310344

311345
var gatherers prometheus.Gatherers
312346

exporter/exporter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func TestMongoS(t *testing.T) {
187187
topologyInfo: new(labelsGetterMock),
188188
}
189189

190-
r := e.makeRegistry(ctx, client, new(labelsGetterMock))
190+
r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts)
191191

192192
res := r.Unregister(&rsgsc)
193193
assert.Equal(t, test.want, res, fmt.Sprintf("Port: %v", test.port))
@@ -218,7 +218,7 @@ func TestMongoUp(t *testing.T) {
218218
logger: e.opts.Logger,
219219
}
220220

221-
r := e.makeRegistry(ctx, client, new(labelsGetterMock))
221+
r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts)
222222

223223
res := r.Unregister(&gc)
224224
assert.Equal(t, true, res)

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ func buildExporter(opts GlobalFlags) *exporter.Exporter {
127127
EnableCollStats: opts.EnableCollStats,
128128

129129
CollStatsLimit: opts.CollStatsLimit,
130+
CollectAll: opts.CollectAll,
130131
}
131132

132133
e := exporter.New(exporterOpts)

0 commit comments

Comments
 (0)