Forum Discussion

Drelo's avatar
Drelo
Icon for Neophyte rankNeophyte
7 days ago

Performance averages over time

Hi,

I’m currently looking for a way to get averages on certain data points & make that data via the API e.g. Average CPU busy per hour, per device.

I've played around with the following approaches but none of them are really what I'm after:

  1. Looping through datasources, getting devices & looping through instances via “/device/devices/{deviceId}/devicedatasources/{hdsId}/instances/{id}/data”. This approach is too cumbersome for the number of devices we have, combined with the other averages we want to pull.
  2. Creating a graph widget & getting the data via the /dashboard/widgets/{widgetId}/data endpoint. This would work if there wasn't a maximum of 100 devices in the widget & deviceIds were clearly linked the graph data.
  3. Generating a trend report & grabbing the link via /report/links/{reportId}. I haven't written this approach off yet but the available formats & the expiry on the generated link isn't ideal.
  4. Dynamic table data is great via the /dashboard/widgets/{widgetId}/data endpoint but I cannot work out a way create a datapoint that has an hourly average value. I'm not sure if it's possible to do something like grab the last x records for a datasource/datapoint on a device & present them in a different datasource/datapoint that could be used in a table widget or to set a custom property value on the device? 
  • What if you used the script cache to keep a running average of the last hour? Then you'd only be pulling the most recent datapoint per device, either through report or widget data.

    • Drelo's avatar
      Drelo
      Icon for Neophyte rankNeophyte

      Thanks Stuart,
      I kind of came to the same conclusion last night. I've been looking at some of the awesome PS module functions shared by Steve_Villardi . I think I'll try & re-using some of Steve's functions, combined with script cache. This should allow me to set an average usage value datapoint for each metric per device hourly, which I can then add to a dynamic table widget & pull via the widget/data endpoint.

    • Drelo's avatar
      Drelo
      Icon for Neophyte rankNeophyte

      Managed to get back to looking at this today. It's an ugly first pass with no debugging or error checking but it appears to validate the approach (I imported more modules that needed :-)). The output lets me set a datapoint for CPU hourly average, I can then present in a dynamic table widget & pull all associated device's avg CPU data in one API call via the  /dashboard/widgets/{widgetId}/data endpoint.

      /***************************************************************************************/
      import org.apache.http.HttpEntity;
      import org.apache.http.client.methods.CloseableHttpResponse;
      import org.apache.http.client.methods.HttpGet;
      import org.apache.http.impl.client.CloseableHttpClient;
      import org.apache.http.impl.client.HttpClients;
      import org.apache.http.util.EntityUtils;
      import javax.crypto.Mac;
      import javax.crypto.spec.SecretKeySpec;
      import java.security.MessageDigest
      import org.apache.commons.codec.binary.Hex;
      import com.santaba.agent.groovyapi.http.*;
      import groovy.json.JsonSlurper;
      import groovy.json.JsonOutput;
      
      // Import relevant properties from the device.
      accessId = hostProps.get("lmaccess.id")
      accessKey = hostProps.get("lmaccess.key")
      account = hostProps.get("lmaccount")
      hostname = hostProps.get("system.hostname")
      deviceId = '##SYSTEM.DEVICEID##'
      dataSourceFilter = 3002393
      
      // Set request target and paramaters to get Device Instances
      resourcePath = '/device/devices/' + deviceId + '/instances'
      queryParameters = '?filter=dataSourceId:' + dataSourceFilter
      url = 'https://' + account + '.logicmonitor.com' + '/santaba/rest' + resourcePath + queryParameters;
      
      // Make HTTP request
      HTTP_Request('GET',url,resourcePath)
      
      def instanceResult(responseBody){
          json_slurper = new JsonSlurper()
          body = json_slurper.parseText(responseBody)
          return body 
      }
      
      def deviceDataSourceId = (instanceResult(responseBody).items.deviceDataSourceId.flatten().first())
      
      resourcePath = '/device/devices/' + deviceId + '/devicedatasources/' + deviceDataSourceId + '/data'
      queryParameters = '?aggregate=average&datapoints=CPUBusyPercent'
      url = 'https://' + account + '.logicmonitor.com' + '/santaba/rest' + resourcePath + queryParameters
      
      // Make HTTP request
      HTTP_Request('GET',url,resourcePath)
      
      def result(responseBody){
          json_slurper = new JsonSlurper()
          body = json_slurper.parseText(responseBody)
          return body 
      }
      
      def dataPointsRaw = result(responseBody).dataPoints
      def valuesRaw = result(responseBody).instances.Microsoft_Windows_CPU.values
      def timeRaw = result(responseBody).instances.Microsoft_Windows_CPU.time
      
      //Cleaned payload objects
      def dataPoints = (dataPointsRaw.flatten().first())
      def values = (valuesRaw.flatten().first())
      def time = (timeRaw.flatten().first())
      
      println("dataPoints=${dataPoints}")
      println("values=${values}")
      println("time=${time}")
      
      return(0)
      
      //Auth and Rest Helpers
      
      // Get current time
      def Find_Epoch(){
          epoch = System.currentTimeMillis()
          return epoch 
      }
      
      // Calculate signature
      def Generate_Signature(verb,resourcePath,data=null){
          if(verb == "GET"){
              requestVars = verb + Find_Epoch() + resourcePath
          }
          else{
              requestVars = verb + Find_Epoch() + data + resourcePath
          }
          hmac = Mac.getInstance("HmacSHA256");
          secret = new SecretKeySpec(accessKey.getBytes(), "HmacSHA256")
          hmac.init(secret);
          hmac_signed = Hex.encodeHexString(hmac.doFinal(requestVars.getBytes()))
          signature = hmac_signed.bytes.encodeBase64()
          return signature
      }
      
      // Build HTTP request.
      def HTTP_Request(verb,url,resourcePath,data=''){
          CloseableHttpClient httpclient = HttpClients.createDefault()
          switch(verb){
              case 'GET':
                  httpReq = new HttpGet(url);
                  break;
          }
          httpReq.addHeader("Authorization" , "LMv1 " + accessId + ":" + Generate_Signature(verb,resourcePath) + ":" + Find_Epoch())
          httpReq.addHeader("X-Version" , "3")
          response = httpclient.execute(httpReq)
          responseBody = EntityUtils.toString(response.getEntity())
          httpclient.close()
          return responseBody 
      }