Test Failed
Push — develop ( 66c9ff...e21229 )
by Nicolas
05:06
created

glances/exports/glances_csv.py (2 issues)

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2019 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
"""CSV interface class."""
21
22
import os.path
23
import csv
0 ignored issues
show
import missing from __future__ import absolute_import
Loading history...
24
import sys
25
import time
26
27
from glances.compat import PY3, iterkeys, itervalues
28
from glances.logger import logger
29
from glances.exports.glances_export import GlancesExport
30
31
32
class Export(GlancesExport):
33
34
    """This class manages the CSV export module."""
35
36
    def __init__(self, config=None, args=None):
37
        """Init the CSV export IF."""
38
        super(Export, self).__init__(config=config, args=args)
39
40
        # CSV file name
41
        self.csv_filename = args.export_csv_file
42
43
        # Set the CSV output file
44
        # (see https://github.com/nicolargo/glances/issues/1525)
45
        if not os.path.isfile(self.csv_filename) or args.export_csv_overwrite:
46
            # File did not exist, create it
47
            file_mode = 'w'
48
            self.old_header = None
49
        else:
50
            # A CSV file already exit, append new data
51
            file_mode = 'a'
52
            # Header will be check later
53
            # Get the existing one
54
            try:
55
                self.csv_file = open_csv_file(self.csv_filename, 'r')
56
                reader = csv.reader(self.csv_file)
57
            except IOError as e:
58
                logger.critical("Cannot open existing CSV file: {}".format(e))
59
                sys.exit(2)
60
            self.old_header = next(reader, None)
61
            self.csv_file.close()
62
63
        try:
64
            self.csv_file = open_csv_file(self.csv_filename, file_mode)
65
            self.writer = csv.writer(self.csv_file)
66
        except IOError as e:
67
            logger.critical("Cannot create the CSV file: {}".format(e))
68
            sys.exit(2)
69
70
        logger.info("Stats exported to CSV file: {}".format(self.csv_filename))
71
72
        self.export_enable = True
73
74
        self.first_line = True
75
76
    def exit(self):
77
        """Close the CSV file."""
78
        logger.debug("Finalise export interface %s" % self.export_name)
79
        self.csv_file.close()
80
81
    def update(self, stats):
82
        """Update stats in the CSV output file."""
83
        # Get the stats
84
        all_stats = stats.getAllExportsAsDict(plugin_list=self.plugins_to_export())
0 ignored issues
show
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...
85
86
        # Init data with timestamp (issue#708)
87
        if self.first_line:
88
            csv_header = ['timestamp']
89
        csv_data = [time.strftime('%Y-%m-%d %H:%M:%S')]
90
91
        # Loop over plugins to export
92
        for plugin in self.plugins_to_export():
93
            if isinstance(all_stats[plugin], list):
94
                for stat in all_stats[plugin]:
95
                    # First line: header
96
                    if self.first_line:
97
                        csv_header += ('{}_{}_{}'.format(
98
                            plugin, self.get_item_key(stat), item) for item in stat)
99
                    # Others lines: stats
100
                    csv_data += itervalues(stat)
101
            elif isinstance(all_stats[plugin], dict):
102
                # First line: header
103
                if self.first_line:
104
                    fieldnames = iterkeys(all_stats[plugin])
105
                    csv_header += ('{}_{}'.format(plugin, fieldname)
106
                                   for fieldname in fieldnames)
107
                # Others lines: stats
108
                csv_data += itervalues(all_stats[plugin])
109
110
        # Export to CSV
111
        # Manage header
112
        if self.first_line:
113
            if self.old_header is None:
114
                # New file, write the header on top on the CSV file
115
                self.writer.writerow(csv_header)
116
            # File already exist, check if header are compatible
117
            if self.old_header != csv_header:
118
                # Header are differents, log an error and do not write data
119
                logger.error("Cannot append data to existing CSV file. Headers are differents.")
120
                logger.debug("Old header: {}".format(self.old_header))
121
                logger.debug("New header: {}".format(csv_header))
122
            else:
123
                # Header are equals, ready to write data
124
                self.old_header = None
125
            # Only do this once
126
            self.first_line = False
127
        # Manage data
128
        if self.old_header is None:
129
            self.writer.writerow(csv_data)
130
            self.csv_file.flush()
131
132
133
def open_csv_file(file_name, file_mode):
134
    if PY3:
135
        csv_file = open(file_name, file_mode, newline='')
136
    else:
137
        csv_file = open(file_name, file_mode + 'b')
138
    return csv_file
139