Issues (45)

glances/exports/glances_csv/__init__.py (1 issue)

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <[email protected]>
6
#
7
# SPDX-License-Identifier: LGPL-3.0-only
8
#
9
10
"""CSV interface class."""
11
12
import os.path
13
import csv
14
import sys
15
import time
16
17
from glances.globals import iterkeys, itervalues
18
from glances.logger import logger
19
from glances.exports.export import GlancesExport
20
21
22
class Export(GlancesExport):
23
24
    """This class manages the CSV export module."""
25
26
    def __init__(self, config=None, args=None):
27
        """Init the CSV export IF."""
28
        super(Export, self).__init__(config=config, args=args)
29
30
        # CSV file name
31
        self.csv_filename = args.export_csv_file
32
33
        # Set the CSV output file
34
        # (see https://github.com/nicolargo/glances/issues/1525)
35
        if not os.path.isfile(self.csv_filename) or args.export_csv_overwrite:
36
            # File did not exist, create it
37
            file_mode = 'w'
38
            self.old_header = None
39
        else:
40
            # A CSV file already exit, append new data
41
            file_mode = 'a'
42
            # Header will be checked later
43
            # Get the existing one
44
            try:
45
                self.csv_file = open_csv_file(self.csv_filename, 'r')
46
                reader = csv.reader(self.csv_file)
47
            except IOError as e:
48
                logger.critical("Cannot open existing CSV file: {}".format(e))
49
                sys.exit(2)
50
            self.old_header = next(reader, None)
0 ignored issues
show
The variable reader does not seem to be defined for all execution paths.
Loading history...
51
            self.csv_file.close()
52
53
        try:
54
            self.csv_file = open_csv_file(self.csv_filename, file_mode)
55
            self.writer = csv.writer(self.csv_file)
56
        except IOError as e:
57
            logger.critical("Cannot create the CSV file: {}".format(e))
58
            sys.exit(2)
59
60
        logger.info("Stats exported to CSV file: {}".format(self.csv_filename))
61
62
        self.export_enable = True
63
64
        self.first_line = True
65
66
    def exit(self):
67
        """Close the CSV file."""
68
        logger.debug("Finalise export interface %s" % self.export_name)
69
        self.csv_file.close()
70
71
    def update(self, stats):
72
        """Update stats in the CSV output file.
73
        Note: This class overwrite the one in the parent class because we need to manage the header.
74
        """
75
        # Get the stats
76
        all_stats = stats.getAllExportsAsDict(plugin_list=self.plugins_to_export(stats))
77
78
        # Init data with timestamp (issue#708)
79
        if self.first_line:
80
            csv_header = ['timestamp']
81
        csv_data = [time.strftime('%Y-%m-%d %H:%M:%S')]
82
83
        # Loop over plugins to export
84
        for plugin in self.plugins_to_export(stats):
85
            export_names, export_values = self.build_export(all_stats[plugin])
86
            if self.first_line:
87
                csv_header += export_names
88
            csv_data += export_values
89
90
        # Export to CSV
91
        # Manage header
92
        if self.first_line:
93
            if self.old_header is None:
94
                # New file, write the header on top on the CSV file
95
                self.writer.writerow(csv_header)
96
            # File already exist, check if header are compatible
97
            if self.old_header != csv_header and self.old_header is not None:
98
                # Header are different, log an error and do not write data
99
                logger.error("Cannot append data to existing CSV file. Headers are different.")
100
                logger.debug("Old header: {}".format(self.old_header))
101
                logger.debug("New header: {}".format(csv_header))
102
            else:
103
                # Header are equals, ready to write data
104
                self.old_header = None
105
            # Only do this once
106
            self.first_line = False
107
        # Manage data
108
        if self.old_header is None:
109
            self.writer.writerow(csv_data)
110
            self.csv_file.flush()
111
112
    def export(self, name, columns, points):
113
        """Export the stats to the CSV file.
114
        For the moment everything is done in the update method."""
115
        pass
116
117
118
def open_csv_file(file_name, file_mode):
119
    return open(file_name, file_mode, newline='')
120