Published on InterSystems Developer Community (https://community.intersystems.com)

Home > Using Grafana directly from IRIS

Article
David Loveluck · Feb 25, 2019 4m read

Using Grafana directly from IRIS

There have been some very helpful articles in the community that show how to use Grafana with IRIS (or Cache/Ensemble) by using an intermediate database.

But I wanted to get at IRIS structures directly. In particular, i wanted to access the Cache History monitor data that is accessible by SQL as described here

https://community.intersystems.com/post/apm-using-cach%C3%A9-history-mon...

and didn't want anything between me and the data.

I already had class queries that returned the data i wanted, so i just needed to embed them in a REST class that returned JSON. I haven't included my class Grafana.MonitorData because it could be anything but i can if people want it.

There were only two difficult points. One was making sure i had local time and utc time worked out at each point. The other was that Grafana doesn't like values like .25 without the leading zero and gives javascript errors  - “t.dataList.map is not a function”. which is why i have the line with  $FN(tValue,,4).

I have simplified my production code to make the principals clear. I could put it on github but it is so simple, it doesn't really warrant that.


 
Spoiler
 

Class Grafana.SYSHistory Extends %CSP.REST
{


XData UrlMap
{
<Routes>
    <Route Url="/" Method="GET" Call="testAvailability" Cors="true" />
    <Route Url="/search" Method="POST" Call="metricFindQuery" Cors="true" />
    <Route Url="/query" Method="POST" Call="query" Cors="true" />
    </Routes>
}

ClassMethod testAvailability() As %Status
{
    write "ok"
    quit $$$OK
}

/// This method returns list of available metrics.
ClassMethod metricFindQuery() As %Status
{
    do ##class(Grafana.MonitorData).GetSupportedMetrics(.metrics)
    w "["
    set sub=""
    set firsttime=1
    do { 
      set sub=$o(metrics(sub))
      quit:sub=""
    if firsttime=0 w ","
     set firsttime=0
     w """",sub,"""" 
} while sub'=""
write "]"
quit $$$OK
}

/// Data format for Grafana - http://docs.grafana.org/plugins/developing/datasources/
ClassMethod query() As %Status
{

set obj = {}.%FromJSON(%request.Content)

 if obj="" {
 write "no object found"
 quit $$$OK   
    
   }
    
    set iter=obj.targets.%GetIterator()
    set tMetrics=0
    while iter.%GetNext(.key,.value) {
    set tMetrics=tMetrics+1
    set tMetrics(tMetrics) = value.target
    }
    set from = obj.range.from
    set to = obj.range.to
#define classname 1
#define queryname 2
set (className,queryName)=""
//hard code the class and use 'NamedQuery' items so we don't allow any access to any data via any query...
set className="Grafana.MonitorData"
set queryName="SysMonHistorySummary"

write "["
for i=1:1:tMetrics {
if i>1 w ","
w "{""target"":"""_tMetrics(i)_""",""datapoints"":["
do ..ExportJSON(className,queryName,from,to,tMetrics(i))
write "]}"
}
write "]"
quit $$$OK
}

/// The className and QueryName determing the query to be executed.
/// from and to are local time in %Date (a.k.k. $horolog) format.
/// The query must return a value for the metric. This code assumes the values are returned
/// as Avg_Metric and RunDate, but you could change that


ClassMethod ExportJSON(className As %String, queryName As %String, from, to, pMetric As %String) As %Status
{
if className="" quit $$$OK
if queryName="" quit $$$OK
set rs=##class(%ResultSet).%New(className_":"_queryName)
if rs="" quit $$$ERROR($$$QueryDoesNotExist,className_":"_queryName)
// use this just for param info
set sc=$classmethod(className,queryName_"GetInfo",.colinfo,.paraminfo,.idinfo,.QHandle,0,.extinfo)
  
//The request must contain data with names matching the parameters of the query.
//Convert date and time parameters from strings to $h

set from=$e(from,1,19)
set to=$e(to,1,19)
set RunDateUTCFromH=$zdth(from,3)
set RunDateFromH=$zdth(RunDateUTCFromH,-3)
set RunDateUTCToH=$zdth(to,3)
set RunDateToH=$zdth(RunDateUTCToH,-3)

set tSc=rs.Execute(RunDateFromH,RunDateToH,"live",pMetric) //param(1),param(2))

if $$$ISERR(tSc) quit tSc

set rowcnt=0
while rs.Next() {
set rowcnt=rowcnt+1
if rowcnt>1 write ","
write "["

set tRunDate=rs.Data("RunDate")
set tUtcRunDate=$zdt(tRunDate,-3)
set tValue=rs.Data("Avg_Metric")
set tPosixTime=##class(%Library.PosixTime).OdbcToLogical($zdt(tUtcRunDate,3,3))
set tUnixTime=##class(%Library.PosixTime).LogicalToUnixTime(tPosixTime)_"000"

write $fn(tValue,,4),",",tUnixTime

write "]"
}
quit $$$OK
}

}

#Best Practices #Monitoring #InterSystems IRIS

Source URL:https://community.intersystems.com/post/using-grafana-directly-iris