summaryrefslogtreecommitdiffstats
path: root/glances/exports/glances_graph/__init__.py
blob: 24d4a98a557d0c3251243cbd9a4bd2e4253155dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# -*- coding: utf-8 -*-
#
# This file is part of Glances.
#
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <nicolas@nicolargo.com>
#
# SPDX-License-Identifier: LGPL-3.0-only
#

"""Graph exporter interface class."""

from pygal import DateTimeLine
import pygal.style
import sys
import os
import tempfile
import errno

from glances.logger import logger
from glances.timer import Timer
from glances.globals import iteritems, time_serie_subsample
from glances.exports.export import GlancesExport


class Export(GlancesExport):

    """This class manages the Graph export module."""

    def __init__(self, config=None, args=None):
        """Init the export IF."""
        super(Export, self).__init__(config=config, args=args)

        # Load the Graph configuration file section (is exists)
        self.export_enable = self.load_conf('graph', options=['path', 'generate_every', 'width', 'height', 'style'])

        # Manage options (command line arguments overwrite configuration file)
        self.path = args.export_graph_path or self.path
        self.generate_every = int(getattr(self, 'generate_every', 0))
        self.width = int(getattr(self, 'width', 800))
        self.height = int(getattr(self, 'height', 600))
        self.style = getattr(pygal.style, getattr(self, 'style', 'DarkStyle'), pygal.style.DarkStyle)

        # Create export folder
        try:
            os.makedirs(self.path)
        except OSError as e:
            if e.errno != errno.EEXIST:
                logger.critical("Cannot create the Graph output folder {} ({})".format(self.path, e))
                sys.exit(2)

        # Check if output folder is writeable
        try:
            tempfile.TemporaryFile(dir=self.path)
        except OSError:
            logger.critical("Graph output folder {} is not writeable".format(self.path))
            sys.exit(2)

        logger.info("Graphs will be created in the {} folder".format(self.path))
        if self.generate_every != 0:
            logger.info("Graphs will be created automatically every {} seconds".format(self.generate_every))
            logger.info("or when 'g' key is pressed (only through the CLI interface)")
            # Start the timer
            self._timer = Timer(self.generate_every)
        else:
            logger.info("Graphs will be created  when 'g' key is pressed (in the CLI interface)")
            self._timer = None

    def exit(self):
        """Close the files."""
        logger.debug("Finalise export interface %s" % self.export_name)

    def update(self, stats):
        """Generate Graph file in the output folder."""

        if self.generate_every != 0 and self._timer.finished():
            self.args.generate_graph = True
            self._timer.reset()

        if not self.args.generate_graph:
            return

        plugins = stats.getPluginsList()
        for plugin_name in plugins:
            plugin = stats._plugins[plugin_name]
            if plugin_name in self.plugins_to_export(stats):
                self.export(plugin_name, plugin.get_export_history())

        logger.info("Graphs created in {}".format(self.path))
        self.args.generate_graph = False

    def export(self, title, data):
        """Generate graph from the data.

        Example for the mem plugin:
        {'percent': [
            (datetime.datetime(2018, 3, 24, 16, 27, 47, 282070), 51.8),
            (datetime.datetime(2018, 3, 24, 16, 27, 47, 540999), 51.9),
            (datetime.datetime(2018, 3, 24, 16, 27, 50, 653390), 52.0),
            (datetime.datetime(2018, 3, 24, 16, 27, 53, 749702), 52.0),
            (datetime.datetime(2018, 3, 24, 16, 27, 56, 825660), 52.0),
            ...
            ]
        }

        Return:
        * True if the graph have been generated
        * False if the graph have not been generated
        """
        if data == {}:
            return False

        chart = DateTimeLine(
            title=title.capitalize(),
            width=self.width,
            height=self.height,
            style=self.style,
            show_dots=False,
            legend_at_bottom=True,
            x_label_rotation=20,
            x_value_formatter=lambda dt: dt.strftime('%Y/%m/%d %H:%M:%S'),
        )
        for k, v in iteritems(time_serie_subsample(data, self.width)):
            chart.add(k, v)
        chart.render_to_file(os.path.join(self.path, title + '.svg'))
        return True