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
}
}
And just to add some more details
I am using the SimpleJson plugin from Grafana Labs as my data source - https://grafana.com/plugins/grafana-simple-json-datasource
The url http://localhost:52777/syshistory/ for that points to the REST application that is implemented by the page I included. When setting up the data source, I only checked ‘Basic Auth’ and added the username and password under ‘Basic Auth Details’.
dave
David, thanks for sharing your work.
Does your system work reliable and your approach can be taken into real use? What about performance? I have same intentions: to use Grafana directly with Cache.
@David Loveluck
Could you please share Grafana.MonitorData class?
Hi @David Loveluck, and anybody who wanted it.
Have a look at one of my latest projects. I did Grafana plugin for IRIS, which can connect and gather any data directly. It's in active development and will be extended with much more possibilities very soon. And I'm going to publish it on Grafana Plugins list as well, for easier installation. Stay tuned, and do not hesitate to contact me directly or through issues in the repository, if you have some advice, what would you like to see there first.
💡 This article is considered as InterSystems Data Platform Best Practice.