Skip to content

Commit 39c5710

Browse files
authored
Issue251 help matplotlib load times (#255)
* add controls to subplot * convert plot() so that it can be called more than once to show Metrics on the same graph * moved plot() call into it's own file and more importantly, made the loading of matplotlib lazy loaded only on plot() call. Also added some additional code as a direction for later
1 parent 922b937 commit 39c5710

File tree

2 files changed

+83
-18
lines changed

2 files changed

+83
-18
lines changed

prometheus_api_client/metric.py

+18-18
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,6 @@
55

66
from prometheus_api_client.exceptions import MetricValueConversionError
77

8-
try:
9-
import matplotlib.pyplot as plt
10-
from pandas.plotting import register_matplotlib_converters
11-
12-
register_matplotlib_converters()
13-
_MPL_FOUND = True
14-
except ImportError as exce: # noqa F841
15-
_MPL_FOUND = False
16-
17-
188
class Metric:
199
r"""
2010
A Class for `Metric` object.
@@ -91,6 +81,9 @@ def __init__(self, metric, oldest_data_datetime=None):
9181
self.start_time = self.metric_values.iloc[0, 0]
9282
self.end_time = self.metric_values.iloc[-1, 0]
9383

84+
# We store the plot information as Class variable
85+
Metric._plot = None
86+
9487
def __eq__(self, other):
9588
"""
9689
Overloading operator ``=``.
@@ -187,12 +180,19 @@ def __add__(self, other):
187180
error_string = "Different metric labels"
188181
raise TypeError("Cannot Add different metric types. " + error_string)
189182

190-
def plot(self):
183+
_metric_plot = None
184+
185+
def plot(self, *args, **kwargs):
191186
"""Plot a very simple line graph for the metric time-series."""
192-
if _MPL_FOUND:
193-
fig, axis = plt.subplots()
194-
axis.plot_date(self.metric_values.ds, self.metric_values.y, linestyle=":")
195-
fig.autofmt_xdate()
196-
# if matplotlib was not imported
197-
else:
198-
raise ImportError("matplotlib was not found")
187+
if not Metric._metric_plot:
188+
from prometheus_api_client.metric_plot import MetricPlot
189+
Metric._metric_plot = MetricPlot(*args, **kwargs)
190+
metric = self
191+
Metric._metric_plot.plot_date(metric)
192+
193+
def show(self, block=None):
194+
"""Plot a very simple line graph for the metric time-series."""
195+
if not Metric._metric_plot:
196+
# can't show before plot
197+
TypeError("Invalid operation: Can't show() before plot()")
198+
Metric._metric_plot.show(block)

prometheus_api_client/metric_plot.py

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""plot code for metric class."""
2+
3+
# This only gets called if there's a plot() call
4+
# This speeds up load time for all the non plot() users
5+
#
6+
# Only loads matplotlib etc during __init__
7+
#
8+
9+
class MetricPlot:
10+
r"""
11+
A Class for `MetricPlot` object.
12+
13+
Internal use only at present
14+
15+
"""
16+
17+
def __init__(self, *args, **kwargs):
18+
"""Functions as a Constructor for the Metric object."""
19+
try:
20+
import matplotlib.pyplot as plt
21+
from pandas.plotting import register_matplotlib_converters
22+
23+
register_matplotlib_converters()
24+
except ImportError as exce: # noqa F841
25+
raise ImportError("matplotlib was not found")
26+
27+
# One graph with potentially N lines - if plot() is called twice
28+
self._plt = plt
29+
self._fig, self._axis = self._plt.subplots(*args, **kwargs)
30+
31+
def plot_date(self, metric):
32+
"""Plot a very simple line graph for the metric time-series."""
33+
34+
# If we made it here, then we know matplotlib is installed and available
35+
self._axis.plot_date(metric.metric_values.ds, metric.metric_values.y,
36+
linestyle="solid",
37+
label=str(metric.metric_name),
38+
)
39+
self._fig.autofmt_xdate()
40+
# These are provided for documentation reasons only - it's presumptuous for this code to call them
41+
# self._axis.set_xlabel('Date/Time')
42+
# self._axis.set_ylabel('Metric')
43+
# self._axis.set_title('Prometheus')
44+
if len(self._axis.lines) > 1:
45+
# We show a legend (or update the legend) if there's more than line on the plot
46+
self._axis.legend()
47+
48+
def show(self, block=None):
49+
"""convience show() call."""
50+
self._plt.show(block=block)
51+
52+
@property
53+
def plt(self):
54+
""" pyplot value for present plotting """
55+
return self._plt
56+
57+
@property
58+
def axis(self):
59+
""" Axis value for present plotting """
60+
return self._axis
61+
62+
@property
63+
def fig(self):
64+
""" Figure value for present plotting """
65+
return self._fig

0 commit comments

Comments
 (0)