Escrito por

Sales Engineer at InterSystems Iberia
Artículo Ricardo Paiva · dic 26, 2022 4m read

Cómo usar Grafana directamente desde IRIS

Se han publicado en la Comunidad varios artículos muy útiles que muestran cómo usar Grafana con IRIS (o Cache/Ensemble) usando una base de datos intermedia.

Pero yo quería llegar directamente a las estructuras de IRIS. En particular, quería acceder a los datos del Cache History monitor, que es accessible a través de SQL, como se describe aquí:

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

y no quería nada entre los datos y yo.

Ya tenía consultas de clase que devuelven los datos que quiero, así que solo necesitaba embeberlos en una clase REST que devolviera JSON. No he incluido mi clase Grafana.MonitorData porque podría ser cualquier cosa, pero puedo hacerlo si la gente lo quiere.

Solo había dos puntos difíciles. Uno era asegurarse de que el tiempo local y el tiempo UTC cuadraban en cada punto. El otro era que a Grafana no le gustan los valores como .25 sin el cero inicial y da errores de javascript - “t.dataList.map no es a función”. Que es por lo que tengo la línea con $FN(tValue,,4).

He simplificado mi código de producción para aclarar los principios. Podría ponerlo en github, pero de tan simple que es, aquí os lo dejo.


 

Solución

 

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)
    "["
    set sub=""
    set firsttime=1
    do 
      set sub=$o(metrics(sub))
      quit:sub=""
    if firsttime=0 ","
     set firsttime=0
     """",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 ","
"{""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
}
}

Comments

Esther Sanchez · dic 27, 2022

Este artículo ha sido etiquetado como "Mejores prácticas" ("Best practices").

enlightenedLos artículos con la etiqueta "Mejores prácticas" incluyen recomendaciones sobre cómo desarrollar, probar, implementar y administrar mejor las soluciones de InterSystems.enlightened

0