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 ^ISCLOGen 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:
- Navegación de globals: Fluidez con $ORDER, $DATA, $GET y ZWRITE para examinar y recorrer globals
- 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
- 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
- Contadores de rendimiento: Saber cómo usar los métodos de $SYSTEM.Process para medir referencias a globals, líneas ejecutadas y tiempos
- ^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