Completed
Push — master ( 3dcd25...20576f )
by Nicolas
01:26
created

glances/exports/glances_influxdb.py (1 issue)

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2015 Nicolargo <[email protected]>
6
#
7
# Glances is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Glances is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
16
#
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""InfluxDB interface class."""
21
22
import sys
23
24
from glances.compat import NoOptionError, NoSectionError
25
from glances.logger import logger
26
from glances.exports.glances_export import GlancesExport
27
28
from influxdb import InfluxDBClient
29
from influxdb.client import InfluxDBClientError
30
from influxdb.influxdb08 import InfluxDBClient as InfluxDBClient08
31
from influxdb.influxdb08.client import InfluxDBClientError as InfluxDBClientError08
32
33
# Constants for tracking specific behavior
34
INFLUXDB_08 = '0.8'
35
INFLUXDB_09PLUS = '0.9+'
36
37
38
class Export(GlancesExport):
39
40
    """This class manages the InfluxDB export module."""
41
42 View Code Duplication
    def __init__(self, config=None, args=None):
43
        """Init the InfluxDB export IF."""
44
        super(Export, self).__init__(config=config, args=args)
45
46
        # Load the InfluxDB configuration file
47
        self.host = None
48
        self.port = None
49
        self.user = None
50
        self.password = None
51
        self.db = None
52
        self.prefix = None
53
        self.tags = None
54
        self.export_enable = self.load_conf()
55
        if not self.export_enable:
56
            sys.exit(2)
57
58
        # Init the InfluxDB client
59
        self.client = self.init()
60
61 View Code Duplication
    def load_conf(self, section="influxdb"):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
62
        """Load the InfluxDb configuration in the Glances configuration file."""
63
        if self.config is None:
64
            return False
65
        try:
66
            self.host = self.config.get_value(section, 'host')
67
            self.port = self.config.get_value(section, 'port')
68
            self.user = self.config.get_value(section, 'user')
69
            self.password = self.config.get_value(section, 'password')
70
            self.db = self.config.get_value(section, 'db')
71
        except NoSectionError:
72
            logger.critical("No InfluxDB configuration found")
73
            return False
74
        except NoOptionError as e:
75
            logger.critical("Error in the InfluxDB configuration (%s)" % e)
76
            return False
77
        else:
78
            logger.debug("Load InfluxDB from the Glances configuration file")
79
80
        # Prefix is optional
81
        try:
82
            self.prefix = self.config.get_value(section, 'prefix')
83
        except NoOptionError:
84
            pass
85
86
        # Tags are optional, comma separated key:value pairs.
87
        try:
88
            self.tags = self.config.get_value(section, 'tags')
89
        except NoOptionError:
90
            pass
91
92
        return True
93
94
    def init(self):
95
        """Init the connection to the InfluxDB server."""
96
        if not self.export_enable:
97
            return None
98
99
        try:
100
            db = InfluxDBClient(host=self.host,
101
                                port=self.port,
102
                                username=self.user,
103
                                password=self.password,
104
                                database=self.db)
105
            get_all_db = [i['name'] for i in db.get_list_database()]
106
            self.version = INFLUXDB_09PLUS
107
        except InfluxDBClientError:
108
            # https://github.com/influxdb/influxdb-python/issues/138
109
            logger.info("Trying fallback to InfluxDB v0.8")
110
            db = InfluxDBClient08(host=self.host,
111
                                  port=self.port,
112
                                  username=self.user,
113
                                  password=self.password,
114
                                  database=self.db)
115
            get_all_db = [i['name'] for i in db.get_list_database()]
116
            self.version = INFLUXDB_08
117
        except InfluxDBClientError08 as e:
118
            logger.critical("Cannot connect to InfluxDB database '%s' (%s)" % (self.db, e))
119
            sys.exit(2)
120
121
        if self.db in get_all_db:
122
            logger.info(
123
                "Stats will be exported to InfluxDB server: {}".format(db._baseurl))
124
        else:
125
            logger.critical("InfluxDB database '%s' did not exist. Please create it" % self.db)
126
            sys.exit(2)
127
128
        return db
129
130
    def export(self, name, columns, points):
131
        """Write the points to the InfluxDB server."""
132
        logger.debug("Export {} stats to InfluxDB".format(name))
133
        # Manage prefix
134
        if self.prefix is not None:
135
            name = self.prefix + '.' + name
136
        # Create DB input
137
        if self.version == INFLUXDB_08:
138
            data = [{'name': name, 'columns': columns, 'points': [points]}]
139
        else:
140
            # Convert all int to float (mandatory for InfluxDB>0.9.2)
141
            # Correct issue#750 and issue#749
142
            for i, _ in enumerate(points):
143
                try:
144
                    points[i] = float(points[i])
145
                except (TypeError, ValueError) as e:
146
                    logger.debug("InfluxDB error during stat convertion %s=%s (%s)" % (columns[i], points[i], e))
147
148
            data = [{'measurement': name,
149
                     'tags': self.parse_tags(self.tags),
150
                     'fields': dict(zip(columns, points))}]
151
        # Write input to the InfluxDB database
152
        try:
153
            self.client.write_points(data)
154
        except Exception as e:
155
            logger.error("Cannot export {} stats to InfluxDB ({})".format(name, e))
156