T2.2: Tracks Application Data

Knowledge Review - InterSystems ObjectScript Specialist

1. Localiza y accede a globals de aplicación

Puntos Clave

  • Globals (^name): Arrays multidimensionales persistentes almacenados en bases de datos; el mecanismo fundamental de almacenamiento en InterSystems IRIS
  • ZWRITE: Muestra el contenido de un global o subárbol en un formato legible
  • $DATA: Verifica si un nodo de global existe y si tiene descendientes
  • $ORDER: Itera a través de los subíndices de un global en un nivel dado
  • $GET: Recupera de forma segura el valor de un nodo de global, devolviendo un valor por defecto si el nodo no existe
  • Portal de Administración: System Explorer > Globals proporciona un visor y editor visual de globals

Notas Detalladas

Comprender la estructura de globals

Los globals son arrays multidimensionales dispersos y jerárquicos almacenados en disco. Persisten entre procesos y reinicios del sistema. Cada clase persistente almacena sus datos en globals -- entender la estructura subyacente de globals es esencial para la depuración y el análisis de rendimiento.

 // Establecer nodos de global
 SET ^Customer(1, "Name") = "John Smith"
 SET ^Customer(1, "Email") = "john@example.com"
 SET ^Customer(2, "Name") = "Jane Doe"
 SET ^Customer(2, "Email") = "jane@example.com"

 // Mostrar todo el árbol del global
 ZWRITE ^Customer
 // Salida:
 // ^Customer(1,"Email")="john@example.com"
 // ^Customer(1,"Name")="John Smith"
 // ^Customer(2,"Email")="jane@example.com"
 // ^Customer(2,"Name")="Jane Doe"

Navegar globals con $ORDER

$ORDER devuelve el siguiente subíndice en un nivel dado, permitiendo el recorrido de nodos de global:

 // Iterar a través de todos los IDs de clientes
 SET id = ""
 FOR {
     SET id = $ORDER(^Customer(id))
     QUIT:id=""
     WRITE "Customer ", id, ": ", ^Customer(id, "Name"), !
 }

Usar $DATA para verificar la existencia de nodos

$DATA devuelve un valor que indica si un nodo existe y/o tiene hijos:

  • 0 = el nodo no existe y no tiene descendientes
  • 1 = el nodo existe pero no tiene descendientes
  • 10 = el nodo no existe pero tiene descendientes
  • 11 = el nodo existe Y tiene descendientes
 IF $DATA(^Customer(1)) {
     WRITE "Customer 1 exists", !
 }
 // Usar $DATA para verificar antes de acceder
 IF $DATA(^Config("settings", "timeout"))#2 {
     SET timeout = ^Config("settings", "timeout")
 }

Visor de globals del Portal de Administración

Navegar a System Explorer > Globals para examinar, buscar y editar globals. Puede:

  • Ver globals en todos los namespaces
  • Filtrar por prefijo de nombre de global
  • Profundizar en niveles de subíndices
  • Exportar e importar datos de globals
  • Eliminar globals o nodos individuales

Localizar globals de datos de clase

Las clases persistentes almacenan datos en globals nombrados según la clase. Use la definición de almacenamiento en Studio/VS Code para encontrar el nombre exacto del global:

 // Para la clase MyApp.Customer, los datos típicamente están en:
 // ^MyApp.CustomerD (global de datos)
 // ^MyApp.CustomerI (global de índices)
 // ^MyApp.CustomerS (contador de secuencia)
 ZWRITE ^MyApp.CustomerD

Referencias de Documentación

2. Usa logging para rastrear datos de aplicación

Puntos Clave

  • ^%ISCLOG: Logging de diagnóstico integrado utilizado por el código del framework de InterSystems (gateway CSP, servicios web, producciones); controlado por el global ^%ISCLOG, entradas almacenadas en ^ISCLOG en el namespace %SYS
  • Globals de logging personalizados: Globals definidos por la aplicación (ej., ^MyApp.Log) para logging estructurado a nivel de aplicación
  • %Library.File: Escribir datos de log en archivos externos para integración con sistemas externos de gestión de logs
  • $HOROLOG / $ZTIMESTAMP: Marcas de tiempo para entradas de log; $ZTIMESTAMP incluye hora UTC con fracciones de segundo
  • Niveles de log: Implementar niveles de severidad (ERROR, WARN, INFO, DEBUG) para filtrado y análisis

Notas Detalladas

^%ISCLOG: Logging de diagnóstico integrado

^%ISCLOG es una facilidad de logging de diagnóstico utilizada por el código del framework de InterSystems — gateway CSP, servicios web, producciones de Interoperability y otros componentes del sistema. Normalmente no se llama directamente desde el código de aplicación; en su lugar, el código del sistema llama a las macros $$$ISCLOG y $$$SysLog (definidas en %occDiagnostics.inc) para generar entradas de log.

Cómo funciona:

  • El global ^%ISCLOG (valor de nivel superior) controla el nivel de logging: 0=deshabilitado, 1=solo errores, 2=advertencias y errores, 3=todos los mensajes (más detallado)
  • Las entradas de log se escriben en el global ^ISCLOG (sin el prefijo %) en el namespace %SYS
  • Las entradas se pueden ver usando la clase %Library.SysLog o haciendo ZWRITE ^ISCLOG en el namespace %SYS
 // Habilitar logging de diagnóstico en máxima verbosidad
 SET ^%ISCLOG = 3

 // Opcionalmente limitar el tamaño del log (por defecto es ilimitado)
 SET ^%ISCLOG("MaxLogEntries") = 10000

 // Después de la resolución de problemas, deshabilitar el logging (impacta el rendimiento cuando está habilitado)
 SET ^%ISCLOG = 0
 // Ver entradas de log — cambiar al namespace %SYS primero
 ZN "%SYS"
 ZWRITE ^ISCLOG

 // O usar la clase %Library.SysLog para consultar entradas programáticamente
 SET rs = ##class(%Library.SysLog).FindAll()
 WHILE rs.%Next() {
     WRITE rs.%Get("TimeStamp"), " ", rs.%Get("Message"), !
 }

Importante: Recuerde establecer ^%ISCLOG a 0 después de la resolución de problemas, ya que el logging detallado consume espacio en disco e impacta el rendimiento.

Construir logs de aplicación personalizados

Para logging específico de la aplicación, cree globals estructurados con marcas de tiempo, severidad y contexto. A diferencia de ^%ISCLOG (que es para diagnósticos del sistema/framework), los globals de logging personalizados le dan control total sobre lo que su aplicación registra:

ClassMethod Log(level As %String, message As %String, context As %String = "")
{
    SET seq = $INCREMENT(^MyApp.Log)
    SET ^MyApp.Log(seq) = $LISTBUILD(
        $ZTIMESTAMP,
        level,
        $USERNAME,
        $JOB,
        context,
        message
    )
    // También mantener un índice basado en fecha para recuperación eficiente
    SET date = +$HOROLOG
    SET ^MyApp.Log("date", date, seq) = ""
}
 // Uso
 DO ##class(MyApp.Logger).Log("INFO", "Order created", "OrderId=1234")
 DO ##class(MyApp.Logger).Log("ERROR", "Payment failed: timeout", "OrderId=1234")

Recuperar y analizar datos de log

 // Iterar a través de entradas de log recientes
 SET id = ""
 FOR {
     SET id = $ORDER(^MyApp.Log(id), -1)  // Orden inverso (más reciente primero)
     QUIT:id=""
     SET entry = ^MyApp.Log(id)
     SET timestamp = $LISTGET(entry, 1)
     SET level = $LISTGET(entry, 2)
     SET message = $LISTGET(entry, 6)
     WRITE id, " [", level, "] ", message, !
 }

Logging basado en archivos

Para integración con sistemas externos de gestión de logs, escribir en archivos:

 SET file = ##class(%Library.File).%New("/var/log/myapp/application.log")
 DO file.Open("WSA")   // Write, Stream, Append
 DO file.WriteLine($ZDATETIME($ZTIMESTAMP, 3, 1) _ " [INFO] Application started")
 DO file.Close()

Referencias de Documentación

3. Agrega y rastrea métricas para monitoreo de rendimiento

Puntos Clave

  • $SYSTEM.Process: Proporciona contadores de rendimiento por proceso (referencias a globals, líneas ejecutadas, etc.)
  • Globals ^IRIS.Temp: Globals temporales para almacenar métricas transitorias sin sobrecarga de journaling
  • $SYSTEM.SQL.Stats: Estadísticas de consultas SQL y datos de rendimiento
  • ^%SYS.MONLBL: Datos de monitoreo línea por línea para profiling de código
  • %SYSTEM.Process.GetMetric(): Recuperar métricas específicas a nivel de proceso programáticamente

Notas Detalladas

Métricas a nivel de proceso con $SYSTEM.Process

$SYSTEM.Process proporciona acceso a contadores detallados de rendimiento del proceso:

 // Obtener el conteo de referencias a globals del proceso actual
 WRITE $SYSTEM.Process.GlobalReferences(), !

 // Obtener líneas de ObjectScript ejecutadas
 WRITE $SYSTEM.Process.LinesExecuted(), !

 // Obtener conteo de lecturas de disco
 WRITE $SYSTEM.Process.DiskReadCount(), !

 // Medir el rendimiento de un bloque de código
 SET startGref = $SYSTEM.Process.GlobalReferences()
 SET startLines = $SYSTEM.Process.LinesExecuted()
 SET startTime = $ZHOROLOG  // Marca de tiempo de alta precisión

 // ... código siendo medido ...
 DO ##class(MyApp.DataLoader).ProcessBatch()

 SET elapsedTime = $ZHOROLOG - startTime
 SET globalRefs = $SYSTEM.Process.GlobalReferences() - startGref
 SET linesExec = $SYSTEM.Process.LinesExecuted() - startLines

 WRITE "Time: ", elapsedTime, " seconds", !
 WRITE "Global refs: ", globalRefs, !
 WRITE "Lines executed: ", linesExec, !

Uso de ^IRIS.Temp para métricas transitorias

Los globals ^IRIS.Temp residen en la base de datos IRISTEMP, que nunca se registra en el journal. Esto los hace ideales para almacenar contadores de rendimiento y métricas temporales sin impactar el rendimiento de transacciones ni el volumen del journal:

 // Rastrear conteos de llamadas API por endpoint
 SET ^IRIS.Temp.Metrics("API", endpoint, $PIECE($HOROLOG, ",", 1)) =
     $INCREMENT(^IRIS.Temp.Metrics("API", endpoint, $PIECE($HOROLOG, ",", 1)))

 // Rastrear tiempos de ejecución de métodos
 SET startTime = $ZHOROLOG
 // ... ejecución del método ...
 SET elapsed = $ZHOROLOG - startTime
 SET ^IRIS.Temp.Metrics("Timing", methodName, $JOB) = elapsed

Estadísticas de rendimiento SQL

Use $SYSTEM.SQL.Stats para analizar el rendimiento de consultas SQL:

 // Obtener estadísticas SQL
 DO $SYSTEM.SQL.Stats.DisplayStats()

 // Para una consulta específica, examinar el plan de consulta
 SET stmt = ##class(%SQL.Statement).%New()
 SET sc = stmt.%Prepare("SELECT * FROM MyApp.Customer WHERE State = ?")
 DO stmt.%ShowPlan()

Monitoreo línea por línea

Habilitar monitoreo línea por línea para profiling de ejecución de código:

 // Habilitar monitoreo para una rutina
 DO $SYSTEM.Monitor.LineLevelMonStart("MyApp.DataLoader")

 // Ejecutar el código
 DO ##class(MyApp.DataLoader).ProcessBatch()

 // Detener el monitoreo y ver resultados
 DO $SYSTEM.Monitor.LineLevelMonStop()

 // Resultados almacenados en ^%SYS.MONLBL
 ZWRITE ^%SYS.MONLBL

Construir un panel de rendimiento

Combinar métricas para una vista integral:

ClassMethod CollectMetrics() As %Status
{
    SET timestamp = $ZTIMESTAMP
    SET metrics = $LISTBUILD(
        $SYSTEM.Process.GlobalReferences(),
        $SYSTEM.Process.LinesExecuted(),
        $SYSTEM.Process.DiskReadCount(),
        $SYSTEM.Process.JournalEntryCount()
    )
    SET ^IRIS.Temp.PerfLog($INCREMENT(^IRIS.Temp.PerfLog)) =
        $LISTBUILD(timestamp) _ metrics
    RETURN $$$OK
}

Referencias de Documentación

Resumen de Preparación para el Examen

Conceptos críticos a dominar:

  1. Navegación de globals: Fluidez con $ORDER, $DATA, $GET y ZWRITE para examinar y recorrer globals
  2. Valores de retorno de $DATA: Saber qué significan 0, 1, 10 y 11 y cómo usar aritmética modular (#2, #10) para probar condiciones específicas
  3. Estrategias de logging: Entender ^%ISCLOG para diagnósticos del sistema/framework vs globals de logging personalizados para datos de aplicación vs logging basado en archivos para integración externa
  4. Contadores de rendimiento: Saber cómo usar los métodos de $SYSTEM.Process para medir referencias a globals, líneas ejecutadas y tiempos
  5. ^IRIS.Temp: Entender que los globals de IRISTEMP no se registran en el journal, haciéndolos ideales para datos transitorios y métricas

Escenarios comunes de examen:

  • Escribir bucles $ORDER para iterar a través de una estructura de global
  • Interpretar valores de retorno de $DATA para varias configuraciones de nodos de global
  • Elegir mecanismos de logging apropiados para diferentes escenarios
  • Medir rendimiento de código usando contadores de $SYSTEM.Process y $ZHOROLOG
  • Identificar el nombre correcto del global para el almacenamiento de datos de una clase persistente
  • Usar ZWRITE para depurar contenidos de globals

Recomendaciones de práctica:

  • Crear globals con varias estructuras y practicar la navegación con $ORDER en diferentes niveles de subíndices
  • Construir una clase de logging simple y probarla con diferentes niveles de log
  • Usar $SYSTEM.Process.GlobalReferences() para comparar el rendimiento de diferentes patrones de acceso a datos
  • Explorar el visor de globals del Portal de Administración (System Explorer > Globals) en diferentes namespaces
  • Habilitar ^%ISCLOG en diferentes niveles, luego cambiar al namespace %SYS para examinar las entradas de ^ISCLOG
  • Escribir código que almacene métricas en ^IRIS.Temp y verificar que los datos no se registran en el journal

Report an Issue