1/*
2** Zabbix
3** Copyright (C) 2001-2021 Zabbix SIA
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18**/
19
20package mongodb
21
22import (
23	"time"
24
25	"gopkg.in/mgo.v2"
26
27	"zabbix.com/pkg/uri"
28	"zabbix.com/pkg/zbxerr"
29
30	"zabbix.com/pkg/plugin"
31)
32
33const pluginName = "Mongo"
34
35const hkInterval = 10
36
37// Plugin inherits plugin.Base and store plugin-specific data.
38type Plugin struct {
39	plugin.Base
40	connMgr *ConnManager
41	options PluginOptions
42}
43
44// impl is the pointer to the plugin implementation.
45var impl Plugin
46
47// Export implements the Exporter interface.
48func (p *Plugin) Export(key string, rawParams []string, _ plugin.ContextProvider) (result interface{}, err error) {
49	params, err := metrics[key].EvalParams(rawParams, p.options.Sessions)
50	if err != nil {
51		return nil, err
52	}
53
54	uri, err := uri.NewWithCreds(params["URI"], params["User"], params["Password"], uriDefaults)
55	if err != nil {
56		return nil, err
57	}
58
59	handleMetric := getHandlerFunc(key)
60	if handleMetric == nil {
61		return nil, zbxerr.ErrorUnsupportedMetric
62	}
63
64	conn, err := p.connMgr.GetConnection(*uri)
65	if err != nil {
66		// Special logic of processing connection errors should be used if mongodb.ping is requested
67		// because it must return pingFailed if any error occurred.
68		if key == keyPing {
69			return pingFailed, nil
70		}
71
72		p.Errf(err.Error())
73
74		return nil, err
75	}
76
77	result, err = handleMetric(conn, params)
78	if err != nil {
79		p.Errf(err.Error())
80	}
81
82	return result, err
83}
84
85// Start implements the Runner interface and performs initialization when plugin is activated.
86func (p *Plugin) Start() {
87	p.connMgr = NewConnManager(
88		time.Duration(p.options.KeepAlive)*time.Second,
89		time.Duration(p.options.Timeout)*time.Second,
90		hkInterval*time.Second,
91	)
92}
93
94// Stop implements the Runner interface and frees resources when plugin is deactivated.
95func (p *Plugin) Stop() {
96	p.connMgr.Destroy()
97	p.connMgr = nil
98}
99
100type MongoLogger struct {
101	Debugf func(format string, args ...interface{})
102}
103
104func (l MongoLogger) Output(_ int, msg string) error {
105	l.Debugf(msg)
106	return nil
107}
108
109func init() {
110	logger := MongoLogger{Debugf: impl.Tracef}
111
112	mgo.SetDebug(true)
113	mgo.SetLogger(logger)
114}
115