Added WebAPI support for Grafana data collection
authorEriks Jenkevics <eriks@netxms.org>
Thu, 16 Mar 2017 16:21:32 +0000 (18:21 +0200)
committerEriks Jenkevics <eriks@netxms.org>
Thu, 16 Mar 2017 16:21:37 +0000 (18:21 +0200)
src/server/nxapisrv/java/src/main/java/org/netxms/websvc/WebSvcApplication.java
src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/AlarmsGrafana.java
src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/DataCollectionGrafana.java [new file with mode: 0644]
src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/GrafanaAlarms.java [copied from src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/AlarmsGrafana.java with 75% similarity]
src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/GrafanaDataCollection.java [new file with mode: 0644]

index 42e007b..e3eb817 100644 (file)
@@ -21,7 +21,8 @@ package org.netxms.websvc;
 import java.util.Arrays;
 import java.util.HashSet;
 import org.netxms.websvc.handlers.Alarms;
-import org.netxms.websvc.handlers.AlarmsGrafana;
+import org.netxms.websvc.handlers.GrafanaAlarms;
+import org.netxms.websvc.handlers.GrafanaDataCollection;
 import org.netxms.websvc.handlers.Objects;
 import org.netxms.websvc.handlers.Sessions;
 import org.restlet.Application;
@@ -63,9 +64,10 @@ public class WebSvcApplication extends Application
       Router router = new Router(getContext());
       router.attach("/alarms", Alarms.class);
       router.attach("/alarms/{id}", Alarms.class);
-      router.attach("/grafana/alarms", AlarmsGrafana.class);
+      router.attach("/grafana/alarms", GrafanaAlarms.class);
       router.attach("/objects", Objects.class);
       router.attach("/objects/{id}", Objects.class);
+      router.attach("/grafana/datacollection", GrafanaDataCollection.class);
       router.attach("/sessions", Sessions.class);
       router.attach("/sessions/{id}", Sessions.class);
       return router;
index afca694..9a81fb8 100644 (file)
@@ -1,29 +1,43 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2017 Raden Solutions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 package org.netxms.websvc.handlers;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Map;
 import org.json.JSONException;
-import org.netxms.client.NXCSession;
 import org.netxms.client.events.Alarm;
 import org.netxms.client.objects.AbstractObject;
 import org.netxms.client.users.AbstractUserObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 
 public class AlarmsGrafana extends AbstractHandler
 {
    private String[] states = { "Outstanding", "Acknowledged", "Resolved", "Terminated" };
-   private Logger log = LoggerFactory.getLogger(AlarmsGrafana.class);
    
    /* (non-Javadoc)
     * @see org.netxms.websvc.handlers.AbstractHandler#getCollection(java.util.Map)
     */
    @Override
    public Object getCollection(Map<String, String> query) throws Exception
-   {
+   {      
       JsonObject root = new JsonObject();
 
       JsonArray columns = new JsonArray();
@@ -32,13 +46,11 @@ public class AlarmsGrafana extends AbstractHandler
       columns.add(createColumn("Source", true, false));
       columns.add(createColumn("Message", true, false));
       columns.add(createColumn("Count", true, false));
-      //columns.add(createColumn("Comments", true, false));
       columns.add(createColumn("Helpdesk ID", true, false));
       columns.add(createColumn("Ack/Resolved By", true, false));
       columns.add(createColumn("Created", true, false));
       columns.add(createColumn("Last Change", true, false));
       root.add("columns", columns);
-      log.error(root.toString());
       
       JsonArray rows = new JsonArray();
       
@@ -46,30 +58,29 @@ public class AlarmsGrafana extends AbstractHandler
       DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
       AbstractObject object = null;
       AbstractUserObject user = null;
-
-      NXCSession session = getSession();
-      if (!session.isObjectsSynchronized())
-         session.syncObjects();
       
-      Map<Long, Alarm> alarms = session.getAlarms();
+      Map<Long, Alarm> alarms = getSession().getAlarms();
       for( Alarm a : alarms.values())
       {
          r.add(a.getCurrentSeverity().name());
          r.add(states[a.getState()]);
+         
          object = getSession().findObjectById(a.getSourceObjectId());
          if (object == null)
             r.add(a.getSourceObjectId());
          else
             r.add(object.getObjectName());
+         
          r.add(a.getMessage());
          r.add(a.getRepeatCount());
-         //r.add(a.getCommentsCount());
          r.add(a.getHelpdeskReference());
+         
          user = getSession().findUserDBObjectById(a.getAckByUser());
          if (user == null)
             r.add("");
          else
             r.add(user.getName());
+         
          r.add(df.format(a.getCreationTime()));
          r.add(df.format(a.getLastChangeTime()));
          rows.add(r);
@@ -82,7 +93,6 @@ public class AlarmsGrafana extends AbstractHandler
 
       JsonArray wrapper = new JsonArray();
       wrapper.add(root);
-      log.error(wrapper.toString());
       return wrapper;
    }
    
diff --git a/src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/DataCollectionGrafana.java b/src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/DataCollectionGrafana.java
new file mode 100644 (file)
index 0000000..0bd7666
--- /dev/null
@@ -0,0 +1,175 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2017 Raden Solutions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.netxms.websvc.handlers;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.json.JSONArray;
+import org.json.JSONTokener;
+import org.netxms.client.datacollection.DciData;
+import org.netxms.client.datacollection.DciDataRow;
+import org.netxms.client.datacollection.DciValue;
+import org.netxms.client.objects.AbstractObject;
+import org.netxms.client.objects.DataCollectionTarget;
+import org.netxms.client.objects.Node;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+public class DataCollectionGrafana extends AbstractHandler
+{
+   private List<AbstractObject> objects;
+   
+   /* (non-Javadoc)
+    * @see org.netxms.websvc.handlers.AbstractHandler#getCollection(java.util.Map)
+    */
+   @Override
+   protected Object getCollection(Map<String, String> query) throws Exception
+   {
+      if (!getSession().isObjectsSynchronized())
+         getSession().syncObjects();
+
+      objects = getSession().getAllObjects();
+      
+      if (query.containsKey("targets"))
+      {
+         return getGraphData(query);
+      }
+      else if (query.containsKey("node"))
+      {
+         return getDciList(query.get("node"));
+      }
+      
+      return getNodeList();     
+   }
+   
+   /**
+    * Get query data
+    * 
+    * @param query
+    * @return data
+    * @throws Exception
+    */
+   private JsonArray getGraphData(Map<String, String> query) throws Exception
+   {
+      JSONTokener tokener = new JSONTokener(query.get("targets"));
+      JSONArray targets = new JSONArray(tokener);
+      
+      DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
+      Date from = format.parse(query.get("from").substring(1, query.get("from").length()-1));
+      Date to = format.parse(query.get("to").substring(1, query.get("to").length()-1));
+      
+      JsonObject root;
+      JsonArray result = new JsonArray();
+      for(int i = 0; i < targets.length(); i++)
+      {
+         long nodeId = findNodeByName(targets.getJSONObject(i).getString("node"));
+         DciData data = getSession().getCollectedData(nodeId, findDciByDescription(targets.getJSONObject(i).getString("dci"), nodeId), from, to, 0);
+         root = new JsonObject();
+         JsonArray datapoints = new JsonArray();
+         JsonArray datapoint;         
+         for(DciDataRow r : data.getValues())
+         {
+            datapoint = new JsonArray();
+            datapoint.add(r.getValueAsLong());
+            datapoint.add(r.getTimestamp().getTime());
+            datapoints.add(datapoint);
+         }
+         root.addProperty("target", targets.getJSONObject(i).getString("dci"));
+         root.add("datapoints", datapoints);
+         result.add(root);
+      }
+      return result;
+   }
+   
+   /**
+    * Get list of nodes
+    * 
+    * @return
+    */
+   private Map<Long, String> getNodeList()
+   {
+      Map<Long, String> result = new HashMap<Long, String>();
+      for(AbstractObject o : objects)
+      {
+         if (o instanceof DataCollectionTarget)
+            result.put(o.getObjectId(), o.getObjectName());
+      }
+      return result;
+   }
+   
+   /**
+    * Get list of dci`s for a node
+    * 
+    * @param node
+    * @return dci list
+    */
+   private Map<Long, String> getDciList(String node) throws Exception
+   {
+      Map<Long, String> result = new HashMap<Long, String>();
+      for(AbstractObject o : objects)
+      {
+         if (o.getObjectName().equals(node))
+         {
+            DciValue[] values = getSession().getLastValues(o.getObjectId());
+            for(DciValue v : values)
+            {
+               result.put(v.getId(), v.getDescription());
+            };
+         }
+      }
+      return result;
+   }
+   
+   /**
+    * Find node ID by object name
+    * 
+    * @param name
+    * @return node ID
+    */
+   private long findNodeByName(String name)
+   {
+      for(AbstractObject o : objects)
+      {
+         if (o instanceof Node && o.getObjectName().equals(name))
+            return o.getObjectId();
+      }      
+      return 0;
+   }
+   
+   /**
+    * Find DCI ID by name
+    * 
+    * @param name
+    * @return DCI ID
+    */
+   private long findDciByDescription(String name, long nodeId) throws Exception
+   {
+      DciValue[] values = getSession().getLastValues(nodeId);
+      for(DciValue v : values)
+      {
+         if (v.getDescription().equals(name))
+            return v.getId();
+      }
+      return 0;
+   }
+}
@@ -1,3 +1,21 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2017 Raden Solutions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 package org.netxms.websvc.handlers;
 
 import java.text.DateFormat;
@@ -8,15 +26,12 @@ import org.netxms.client.NXCSession;
 import org.netxms.client.events.Alarm;
 import org.netxms.client.objects.AbstractObject;
 import org.netxms.client.users.AbstractUserObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 
-public class AlarmsGrafana extends AbstractHandler
+public class GrafanaAlarms extends AbstractHandler
 {
    private String[] states = { "Outstanding", "Acknowledged", "Resolved", "Terminated" };
-   private Logger log = LoggerFactory.getLogger(AlarmsGrafana.class);
    
    /* (non-Javadoc)
     * @see org.netxms.websvc.handlers.AbstractHandler#getCollection(java.util.Map)
@@ -24,6 +39,14 @@ public class AlarmsGrafana extends AbstractHandler
    @Override
    public Object getCollection(Map<String, String> query) throws Exception
    {
+      NXCSession session = getSession();
+      if (!session.isObjectsSynchronized())
+         session.syncObjects();
+      
+      if (query.containsKey("node") && query.get("node").equals("Select source"))
+      {
+         
+      }
       JsonObject root = new JsonObject();
 
       JsonArray columns = new JsonArray();
@@ -32,13 +55,11 @@ public class AlarmsGrafana extends AbstractHandler
       columns.add(createColumn("Source", true, false));
       columns.add(createColumn("Message", true, false));
       columns.add(createColumn("Count", true, false));
-      //columns.add(createColumn("Comments", true, false));
       columns.add(createColumn("Helpdesk ID", true, false));
       columns.add(createColumn("Ack/Resolved By", true, false));
       columns.add(createColumn("Created", true, false));
       columns.add(createColumn("Last Change", true, false));
       root.add("columns", columns);
-      log.error(root.toString());
       
       JsonArray rows = new JsonArray();
       
@@ -46,30 +67,29 @@ public class AlarmsGrafana extends AbstractHandler
       DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
       AbstractObject object = null;
       AbstractUserObject user = null;
-
-      NXCSession session = getSession();
-      if (!session.isObjectsSynchronized())
-         session.syncObjects();
       
       Map<Long, Alarm> alarms = session.getAlarms();
       for( Alarm a : alarms.values())
       {
          r.add(a.getCurrentSeverity().name());
          r.add(states[a.getState()]);
+         
          object = getSession().findObjectById(a.getSourceObjectId());
          if (object == null)
             r.add(a.getSourceObjectId());
          else
             r.add(object.getObjectName());
+         
          r.add(a.getMessage());
          r.add(a.getRepeatCount());
-         //r.add(a.getCommentsCount());
          r.add(a.getHelpdeskReference());
+         
          user = getSession().findUserDBObjectById(a.getAckByUser());
          if (user == null)
             r.add("");
          else
             r.add(user.getName());
+         
          r.add(df.format(a.getCreationTime()));
          r.add(df.format(a.getLastChangeTime()));
          rows.add(r);
@@ -82,7 +102,6 @@ public class AlarmsGrafana extends AbstractHandler
 
       JsonArray wrapper = new JsonArray();
       wrapper.add(root);
-      log.error(wrapper.toString());
       return wrapper;
    }
    
@@ -101,4 +120,4 @@ public class AlarmsGrafana extends AbstractHandler
       column.addProperty("sort", desc);
       return column;
    }
-}
+}
\ No newline at end of file
diff --git a/src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/GrafanaDataCollection.java b/src/server/nxapisrv/java/src/main/java/org/netxms/websvc/handlers/GrafanaDataCollection.java
new file mode 100644 (file)
index 0000000..c8472d7
--- /dev/null
@@ -0,0 +1,172 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2017 Raden Solutions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.netxms.websvc.handlers;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.json.JSONArray;
+import org.json.JSONTokener;
+import org.netxms.client.datacollection.DciData;
+import org.netxms.client.datacollection.DciDataRow;
+import org.netxms.client.datacollection.DciValue;
+import org.netxms.client.objects.AbstractObject;
+import org.netxms.client.objects.DataCollectionTarget;
+import org.netxms.client.objects.Node;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+public class GrafanaDataCollection extends AbstractHandler
+{
+   private List<AbstractObject> objects;
+   
+   @Override
+   protected Object getCollection(Map<String, String> query) throws Exception
+   {
+      if (!getSession().isObjectsSynchronized())
+         getSession().syncObjects();
+
+      objects = getSession().getAllObjects();
+      
+      if (query.containsKey("targets"))
+      {
+         return getGraphData(query);
+      }
+      else if (query.containsKey("node"))
+      {
+         return getDciList(query.get("node"));
+      }
+      
+      return getNodeList();     
+   }
+   
+   /**
+    * Get query data
+    * 
+    * @param query
+    * @return data
+    * @throws Exception
+    */
+   private JsonArray getGraphData(Map<String, String> query) throws Exception
+   {
+      JSONTokener tokener = new JSONTokener(query.get("targets"));
+      JSONArray targets = new JSONArray(tokener);
+      
+      DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
+      Date from = format.parse(query.get("from").substring(1, query.get("from").length()-1));
+      Date to = format.parse(query.get("to").substring(1, query.get("to").length()-1));
+      
+      JsonObject root;
+      JsonArray result = new JsonArray();
+      for(int i = 0; i < targets.length(); i++)
+      {
+         long nodeId = findNodeByName(targets.getJSONObject(i).getString("node"));
+         DciData data = getSession().getCollectedData(nodeId, findDciByDescription(targets.getJSONObject(i).getString("dci"), nodeId), from, to, 0);
+         root = new JsonObject();
+         JsonArray datapoints = new JsonArray();
+         JsonArray datapoint;         
+         for(DciDataRow r : data.getValues())
+         {
+            datapoint = new JsonArray();
+            datapoint.add(r.getValueAsLong());
+            datapoint.add(r.getTimestamp().getTime());
+            datapoints.add(datapoint);
+         }
+         root.addProperty("target", targets.getJSONObject(i).getString("dci"));
+         root.add("datapoints", datapoints);
+         result.add(root);
+      }
+      return result;
+   }
+   
+   /**
+    * Get list of nodes
+    * 
+    * @return
+    */
+   private Map<Long, String> getNodeList()
+   {
+      Map<Long, String> result = new HashMap<Long, String>();
+      for(AbstractObject o : objects)
+      {
+         if (o instanceof DataCollectionTarget)
+            result.put(o.getObjectId(), o.getObjectName());
+      }
+      return result;
+   }
+   
+   /**
+    * Get list of dci`s for a node
+    * 
+    * @param node
+    * @return dci list
+    */
+   private Map<Long, String> getDciList(String node) throws Exception
+   {
+      Map<Long, String> result = new HashMap<Long, String>();
+      for(AbstractObject o : objects)
+      {
+         if (o.getObjectName().equals(node))
+         {
+            DciValue[] values = getSession().getLastValues(o.getObjectId());
+            for(DciValue v : values)
+            {
+               result.put(v.getId(), v.getDescription());
+            };
+         }
+      }
+      return result;
+   }
+   
+   /**
+    * Find node ID by object name
+    * 
+    * @param name
+    * @return node ID
+    */
+   private long findNodeByName(String name)
+   {
+      for(AbstractObject o : objects)
+      {
+         if (o instanceof Node && o.getObjectName().equals(name))
+            return o.getObjectId();
+      }      
+      return 0;
+   }
+   
+   /**
+    * Find DCI ID by name
+    * 
+    * @param name
+    * @return DCI ID
+    */
+   private long findDciByDescription(String name, long nodeId) throws Exception
+   {
+      DciValue[] values = getSession().getLastValues(nodeId);
+      for(DciValue v : values)
+      {
+         if (v.getDescription().equals(name))
+            return v.getId();
+      }
+      return 0;
+   }
+}