From b38920ccf428f7325cb5517acf03466dca6461b0 Mon Sep 17 00:00:00 2001
From: Tudor Golubenco <tudor@elastic.co>
Date: Thu, 7 Sep 2017 11:37:27 +0200
Subject: [PATCH] MB mongodb module: connect on fetch, not on init

Moving the Dial call to the Fetch, so that in case Mongodb is not (yet)
available, Metricbeat doesn't exit with an error, but just reports the
service being down. This is consistent with the way most of the other
modules are working.

Fixes #5090
---
 metricbeat/module/mongodb/dbstats/dbstats.go | 20 ++++++++++----------
 metricbeat/module/mongodb/mongodb.go         |  2 +-
 metricbeat/module/mongodb/status/status.go   | 19 ++++++++++---------
 3 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/metricbeat/module/mongodb/dbstats/dbstats.go b/metricbeat/module/mongodb/dbstats/dbstats.go
index 81870e9d13c..a9b8a1da01e 100644
--- a/metricbeat/module/mongodb/dbstats/dbstats.go
+++ b/metricbeat/module/mongodb/dbstats/dbstats.go
@@ -28,7 +28,7 @@ func init() {
 // multiple fetch calls.
 type MetricSet struct {
 	mb.BaseMetricSet
-	mongoSession *mgo.Session
+	dialInfo *mgo.DialInfo
 }
 
 // New creates a new instance of the MetricSet
@@ -43,15 +43,9 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
 	}
 	dialInfo.Timeout = base.Module().Config().Timeout
 
-	// instantiate direct connections to each of the configured Mongo hosts
-	mongoSession, err := mongodb.NewDirectSession(dialInfo)
-	if err != nil {
-		return nil, err
-	}
-
 	return &MetricSet{
 		BaseMetricSet: base,
-		mongoSession:  mongoSession,
+		dialInfo:      dialInfo,
 	}, nil
 }
 
@@ -62,8 +56,14 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) {
 	// events is the list of events collected from each of the databases.
 	var events []common.MapStr
 
+	// instantiate direct connections to each of the configured Mongo hosts
+	mongoSession, err := mongodb.NewDirectSession(m.dialInfo)
+	if err != nil {
+		return nil, err
+	}
+
 	// Get the list of databases names, which we'll use to call db.stats() on each
-	dbNames, err := m.mongoSession.DatabaseNames()
+	dbNames, err := mongoSession.DatabaseNames()
 	if err != nil {
 		logp.Err("Error retrieving database names from Mongo instance")
 		return events, err
@@ -71,7 +71,7 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) {
 
 	// for each database, call db.stats() and append to events
 	for _, dbName := range dbNames {
-		db := m.mongoSession.DB(dbName)
+		db := mongoSession.DB(dbName)
 
 		result := common.MapStr{}
 
diff --git a/metricbeat/module/mongodb/mongodb.go b/metricbeat/module/mongodb/mongodb.go
index b853b1cc8b2..603a0fe9475 100644
--- a/metricbeat/module/mongodb/mongodb.go
+++ b/metricbeat/module/mongodb/mongodb.go
@@ -74,7 +74,7 @@ func NewDirectSession(dialInfo *mgo.DialInfo) (*mgo.Session, error) {
 	nodeDialInfo.Direct = true
 	nodeDialInfo.FailFast = true
 
-	logp.Info("Connecting to MongoDB node at %v", nodeDialInfo.Addrs)
+	logp.Debug("mongodb", "Connecting to MongoDB node at %v", nodeDialInfo.Addrs)
 
 	session, err := mgo.DialWithInfo(&nodeDialInfo)
 	if err != nil {
diff --git a/metricbeat/module/mongodb/status/status.go b/metricbeat/module/mongodb/status/status.go
index 92b8c8ad645..f25229077d9 100644
--- a/metricbeat/module/mongodb/status/status.go
+++ b/metricbeat/module/mongodb/status/status.go
@@ -30,7 +30,7 @@ func init() {
 // multiple fetch calls.
 type MetricSet struct {
 	mb.BaseMetricSet
-	mongoSession *mgo.Session
+	dialInfo *mgo.DialInfo
 }
 
 // New creates a new instance of the MetricSet
@@ -43,15 +43,9 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
 	}
 	dialInfo.Timeout = base.Module().Config().Timeout
 
-	// instantiate direct connections to Mongo host
-	mongoSession, err := mongodb.NewDirectSession(dialInfo)
-	if err != nil {
-		return nil, err
-	}
-
 	return &MetricSet{
 		BaseMetricSet: base,
-		mongoSession:  mongoSession,
+		dialInfo:      dialInfo,
 	}, nil
 }
 
@@ -59,8 +53,15 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
 // It returns the event which is then forward to the output. In case of an error, a
 // descriptive error must be returned.
 func (m *MetricSet) Fetch() (common.MapStr, error) {
+
+	// instantiate direct connections to each of the configured Mongo hosts
+	mongoSession, err := mongodb.NewDirectSession(m.dialInfo)
+	if err != nil {
+		return nil, err
+	}
+
 	result := map[string]interface{}{}
-	if err := m.mongoSession.DB("admin").Run(bson.D{{Name: "serverStatus", Value: 1}}, &result); err != nil {
+	if err := mongoSession.DB("admin").Run(bson.D{{Name: "serverStatus", Value: 1}}, &result); err != nil {
 		return nil, err
 	}