Passed
Push — master ( cdb6bf...0d35d5 )
by Nicolas
04:08 queued 14s
created

glances.exports.glances_influxdb2.Export.export()   A

Complexity

Conditions 5

Size

Total Lines 19
Code Lines 13

Duplication

Lines 19
Ratio 100 %

Importance

Changes 0
Metric Value
cc 5
eloc 13
nop 4
dl 19
loc 19
rs 9.2833
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2020 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 (from to InfluxDB 1.8+) interface class."""
21
22
import sys
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
23
24
from glances.logger import logger
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
25
from glances.exports.glances_export import GlancesExport
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
26
27
from influxdb_client import InfluxDBClient, WriteOptions
0 ignored issues
show
introduced by
import missing from __future__ import absolute_import
Loading history...
introduced by
Unable to import 'influxdb_client'
Loading history...
28
29
30
class Export(GlancesExport):
0 ignored issues
show
best-practice introduced by
Too many instance attributes (8/7)
Loading history...
31
    """This class manages the InfluxDB export module."""
32
33
    def __init__(self, config=None, args=None):
34
        """Init the InfluxDB export IF."""
35
        super(Export, self).__init__(config=config, args=args)
36
37
        # Mandatories configuration keys (additional to host and port)
38
        self.org = None
39
        self.bucket = None
40
        self.token = None
41
42
        # Optionals configuration keys
43
        self.protocol = 'http'
44
        self.prefix = None
45
        self.tags = None
46
47
        # Load the InfluxDB configuration file
48
        self.export_enable = self.load_conf('influxdb2',
49
                                            mandatories=['host', 'port',
50
                                                         'user', 'password',
51
                                                         'org', 'bucket', 'token'],
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (83/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
52
                                            options=['protocol',
53
                                                     'prefix',
54
                                                     'tags'])
55
        if not self.export_enable:
56
            sys.exit(2)
57
58
        # Init the InfluxDB client
59
        self.client = self.init()
60
61
    def init(self):
62
        """Init the connection to the InfluxDB server."""
63
        if not self.export_enable:
64
            return None
65
66
        url = '{}://{}:{}'.format(self.protocol, self.host, self.port)
67
        try:
68
            client = InfluxDBClient(url=url,
69
                                    enable_gzip=False,
70
                                    org=self.org, 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
71
                                    token=self.token)
72
        except Exception as e:
0 ignored issues
show
Best Practice introduced by
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
Coding Style Naming introduced by
The name e does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
73
            logger.critical("Cannot connect to InfluxDB server '%s' (%s)" % (url, e))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (85/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
74
            sys.exit(2)
75
        else:
76
            logger.info("Connected to InfluxDB server version {} ({})".format(client.health().version,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (102/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
77
                                                                              client.health().message))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (103/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
78
79
80
        # Create the write client
81
        write_client = client.write_api(write_options=WriteOptions(batch_size=500,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
82
                                                                   flush_interval=10000,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (88/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
83
                                                                   jitter_interval=2000,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (88/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
84
                                                                   retry_interval=5000,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (87/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
85
                                                                   max_retries=5,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
86
                                                                   max_retry_delay=30000,
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (89/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
87
                                                                   exponential_base=2))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (87/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
88
        return write_client
89
90 View Code Duplication
    def _normalize(self, name, columns, points):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
91
        """Normalize data for the InfluxDB's data model."""
92
93
        for i, _ in enumerate(points):
94
            # Supported type:
95
            # https://docs.influxdata.com/influxdb/v2.0/reference/syntax/line-protocol/
96
            if points[i] is None:
97
                # Ignore points with None value
98
                del(points[i])
0 ignored issues
show
Unused Code Coding Style introduced by
Unnecessary parens after u'del' keyword
Loading history...
99
                del(columns[i])
0 ignored issues
show
Unused Code Coding Style introduced by
Unnecessary parens after u'del' keyword
Loading history...
100
                continue
101
            try:
102
                points[i] = float(points[i])
103
            except (TypeError, ValueError):
104
                pass
105
            else:
106
                continue
107
            try:
108
                points[i] = str(points[i])
109
            except (TypeError, ValueError):
110
                pass
111
            else:
112
                continue
113
114
        return [{'measurement': name,
115
                 'tags': self.parse_tags(self.tags),
116
                 'fields': dict(zip(columns, points))}]
117
118 View Code Duplication
    def export(self, name, columns, points):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
119
        """Write the points to the InfluxDB server."""
120
        # Manage prefix
121
        if self.prefix is not None:
122
            name = self.prefix + '.' + name
123
        # Write input to the InfluxDB database
124
        if len(points) == 0:
0 ignored issues
show
Unused Code introduced by
Do not use len(SEQUENCE) as condition value
Loading history...
125
            logger.debug("Cannot export empty {} stats to InfluxDB".format(name))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
126
        else:
127
            try:
128
                self.client.write(self.bucket,
129
                                  self.org,
130
                                  self._normalize(name, columns, points), 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
131
                                  time_precision="s")
132
            except Exception as e:
0 ignored issues
show
Best Practice introduced by
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
Coding Style Naming introduced by
The name e does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
133
                # Log level set to debug instead of error (see: issue #1561)
134
                logger.debug("Cannot export {} stats to InfluxDB ({})".format(name, e))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (87/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
135
            else:
136
                logger.debug("Export {} stats to InfluxDB".format(name))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
137