From 8b37126169f292a6d3e7e6e716e3d08192b8e20b Mon Sep 17 00:00:00 2001
From: msimonin <matthieu.simonin@inria.fr>
Date: Sun, 20 Mar 2022 21:59:32 +0100
Subject: [PATCH] Update metric endpoint

---
 README.org                 | 79 ++++++++------------------------------
 examples/job_timeseries.py | 36 -----------------
 examples/timeseries.py     | 37 ++++++++----------
 grid5000/base.py           |  4 ++
 grid5000/objects.py        |  9 +++++
 5 files changed, 46 insertions(+), 119 deletions(-)
 delete mode 100644 examples/job_timeseries.py

diff --git a/README.org b/README.org
index 6445c33..726ba72 100644
--- a/README.org
+++ b/README.org
@@ -594,47 +594,6 @@ In [2]: # gk is your entry point
    #+END_SRC
 
 ** Metrics API
-*** Get the timeseries corresponding to a job
-    Credits to ~lturpin~.
-    #+BEGIN_SRC python :exports code :tangle examples/job_timeseries.py
-import logging
-import os
-
-from grid5000 import Grid5000
-
-
-logging.basicConfig(level=logging.DEBUG)
-
-
-def get_job_consumption(job_id, gk, site):
-    metrics = gk.sites[site].metrics
-    job = gk.sites[site].jobs[job_id]
-    # nodes as list : "cluster-number.site.grid5000.fr"
-    nodes_dom = job.assigned_nodes
-    # nodes as list : "cluster-number"
-    nodes = map(lambda node_dom: node_dom.split('.')[0], nodes_dom)
-    # nodes as string : "cluster-number,cluster-number,..."
-    nodes_str = ','.join(nodes)
-
-    start = job.started_at
-    end = job.stopped_at
-    kwargs = {
-        "only": nodes_str,
-        "resolution": 1,
-        "from": start,
-        "to": end
-    }
-    timeseries = metrics["power"].timeseries.list(**kwargs)
-    return timeseries
-
-
-conf_file = os.path.join(os.environ.get("HOME"), ".python-grid5000.yaml")
-gk = Grid5000.from_yaml(conf_file)
-
-timeseries = get_job_consumption("1092446", gk, "lyon")
-print(timeseries)
-    #+END_SRC
-
 *** Get some timeseries (and plot them)
     For this example you'll need ~matplotlib~, ~seaborn~ and ~pandas~.
 
@@ -649,47 +608,43 @@ print(timeseries)
     import seaborn as sns
     import time
 
-    logging.basicConfig(level=logging.DEBUG)
+    logging.basicConfig(level=logging.INFO)
 
     conf_file = os.path.join(os.environ.get("HOME"), ".python-grid5000.yaml")
     gk = Grid5000.from_yaml(conf_file)
 
-    metrics = gk.sites["lyon"].metrics
+    metrics = gk.sites["lyon"].clusters["nova"].metrics
     print("--- available metrics")
-    print(metrics.list())
-
-    print("---- power metric")
-    print(metrics["power"])
+    print(metrics)
 
     print("----- a timeserie")
     now = time.time()
+    # NOTE that you can pass a job_id here
     kwargs = {
-        "only": "nova-1,nova-2,nova-3",
-        "resolution": 1,
-        "from": int(now - 600),
-        "to": int(now)
+        "nodes": "nova-1,nova-2,nova-3",
+        "metrics": "wattmetre_power_watt",
+        "start_time": int(now - 600),
     }
-    timeseries = metrics["power"].timeseries.list(**kwargs)
+    metrics = gk.sites["lyon"].metrics.list(**kwargs)
 
     # let's visualize this
     df = pd.DataFrame()
-    for timeserie in timeseries:
-        print(timeserie)
-        timestamp = timeserie.timestamps
-        value = timeserie.values
-        measurement = timeserie.uid
+    for metric in metrics:
+        timestamp = metric.timestamp
+        value = metric.value
+        device_id = metric.device_id
         df = pd.concat([df, pd.DataFrame({
-            "timestamp": timestamp,
-            "value": value,
-            "measurement": [measurement]*len(timestamp)
+            "timestamp": [timestamp],
+            "value": [value],
+            "device_id": [device_id]
         })])
-
     sns.relplot(data=df,
                 x="timestamp",
                 y="value",
-                hue="measurement",
+                hue="device_id",
                 kind="line")
     plt.show()
+
     #+END_SRC
 
 
diff --git a/examples/job_timeseries.py b/examples/job_timeseries.py
deleted file mode 100644
index 492477a..0000000
--- a/examples/job_timeseries.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import logging
-import os
-
-from grid5000 import Grid5000
-
-
-logging.basicConfig(level=logging.DEBUG)
-
-
-def get_job_consumption(job_id, gk, site):
-    metrics = gk.sites[site].metrics
-    job = gk.sites[site].jobs[job_id]
-    # nodes as list : "cluster-number.site.grid5000.fr"
-    nodes_dom = job.assigned_nodes
-    # nodes as list : "cluster-number"
-    nodes = map(lambda node_dom: node_dom.split('.')[0], nodes_dom)
-    # nodes as string : "cluster-number,cluster-number,..."
-    nodes_str = ','.join(nodes)
-
-    start = job.started_at
-    end = job.stopped_at
-    kwargs = {
-        "only": nodes_str,
-        "resolution": 1,
-        "from": start,
-        "to": end
-    }
-    timeseries = metrics["power"].timeseries.list(**kwargs)
-    return timeseries
-
-
-conf_file = os.path.join(os.environ.get("HOME"), ".python-grid5000.yaml")
-gk = Grid5000.from_yaml(conf_file)
-
-timeseries = get_job_consumption("1092446", gk, "lyon")
-print(timeseries)
diff --git a/examples/timeseries.py b/examples/timeseries.py
index 82a7ba0..af6ce84 100644
--- a/examples/timeseries.py
+++ b/examples/timeseries.py
@@ -8,44 +8,39 @@ import matplotlib.pyplot as plt
 import seaborn as sns
 import time
 
-logging.basicConfig(level=logging.DEBUG)
+logging.basicConfig(level=logging.INFO)
 
 conf_file = os.path.join(os.environ.get("HOME"), ".python-grid5000.yaml")
 gk = Grid5000.from_yaml(conf_file)
 
-metrics = gk.sites["lyon"].metrics
+metrics = gk.sites["lyon"].clusters["nova"].metrics
 print("--- available metrics")
-print(metrics.list())
-
-print("---- power metric")
-print(metrics["power"])
+print(metrics)
 
 print("----- a timeserie")
 now = time.time()
+# NOTE that you can pass a job_id here
 kwargs = {
-    "only": "nova-1,nova-2,nova-3",
-    "resolution": 1,
-    "from": int(now - 600),
-    "to": int(now)
+    "nodes": "nova-1,nova-2,nova-3",
+    "metrics": "wattmetre_power_watt",
+    "start_time": int(now - 600),
 }
-timeseries = metrics["power"].timeseries.list(**kwargs)
+metrics = gk.sites["lyon"].metrics.list(**kwargs)
 
 # let's visualize this
 df = pd.DataFrame()
-for timeserie in timeseries:
-    print(timeserie)
-    timestamp = timeserie.timestamps
-    value = timeserie.values
-    measurement = timeserie.uid
+for metric in metrics:
+    timestamp = metric.timestamp
+    value = metric.value
+    device_id = metric.device_id
     df = pd.concat([df, pd.DataFrame({
-        "timestamp": timestamp,
-        "value": value,
-        "measurement": [measurement]*len(timestamp)
+        "timestamp": [timestamp],
+        "value": [value],
+        "device_id": [device_id]
     })])
-
 sns.relplot(data=df,
             x="timestamp",
             y="value",
-            hue="measurement",
+            hue="device_id",
             kind="line")
 plt.show()
diff --git a/grid5000/base.py b/grid5000/base.py
index fe28466..74044ac 100644
--- a/grid5000/base.py
+++ b/grid5000/base.py
@@ -1,3 +1,4 @@
+import copy
 import importlib
 import json
 
@@ -164,3 +165,6 @@ class RESTObject(object):
 
     def __eq__(self, value):
         return self.get_id() == value.get_id()
+
+    def to_dict(self):
+        return copy.deepcopy(self._attrs)
\ No newline at end of file
diff --git a/grid5000/objects.py b/grid5000/objects.py
index d3ebca3..73d54e5 100644
--- a/grid5000/objects.py
+++ b/grid5000/objects.py
@@ -16,6 +16,15 @@ class Timeserie(RESTObject):
 
 class Metric(RESTObject):
     _managers = (("timeseries", "TimeserieManager"),)
+    _id_attr = None
+
+    def __repr__(self):
+        keys = ["timestamp", "value", "metric_id", "device_id"]
+        try:
+            _repr = ["%s:%s" % (k, getattr(self, k)) for k in keys]
+            return "<%s %s>" % (self.__class__.__name__, " ".join(_repr))
+        except Exception:
+            return super().__repr__()
 
 
 class Server(RESTObject):
-- 
GitLab