Artículo
· 24 feb, 2023 Lectura de 11 min

Depuración web - Parte 2

En el primer artículo hablé sobre probar y depurar aplicaciones web de Caché con herramientas externas. La segunda parte tratará sobre las herramientas de Caché.

Estas son:

  • CSP Gateway y Webapp configuration
  • CSP Gateway logging
  • CSP Gateway tracing
  • ISCLOG
  • Custom logging
  • Session events
  • Output to device

CSP Gateway y Webapp configuration

En primer lugar, si estás depurando y, sobre todo, desarrollando una aplicación front-end, no necesitas caching. Es muy útil en un sistema de producción, pero no durante el desarrollo. Para desactivar el registro de una aplicación web, hay que ir a: SMP → Menu → Manage Web Applications → y definir Serve Files Timeout con la configuración igual a 0. Luego hacer clic en "Save".

Después, hay que purgar el caché de la aplicación web. Para ello, ve a: SMP → System Administration → Configuration → CSP Gateway Management → System Status. Allí se encuentra la tabla "Cached Forms", la última fila es una línea Total, pulsa el botón borrar (con el punto) para borrar el caché de la aplicación web:

CSP Gateway logging

Ya que estamos hablando de CSP Gateway, este es compatible con el registro de las solicitudes de entrada (documentación). En la pestaña Default Parameters, especifica el nivel de registro deseado (por ejemplo, v9a) y guarda los cambios. v9a (consulta otras opciones en la documentación) registra todas las solicitudes HTTP a http.log en el directorio principal de Gateway. Este es un ejemplo de solicitud capturada:

GET /forms/form/info/Form.Test.Person HTTP/1.1
Host: localhost:57772
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:57772/formsui/index.html
Cookie: CSPSESSIONID-SP-57772-UP-forms-=001000000000yxiocLLb8bbc9SVXQJC5WMU831n2sENf4OGeGa; CSPWSERVERID=144zwBTP
Dnt: 1
Connection: keep-alive
Cache-Control: max-age=0
<>

También hay opciones para registrar el rendimiento. Los resultados pueden escribirse en un archivo o visualizarse desde la pestaña View Event Log.

CSP Gateway tracing

Por último, se pueden rastrean las solicitudes y respuestas en la pestaña View HTTP Trace de CSP Gateway. Activa el rastreo y las solicitudes comenzarán a ser capturadas inmediatamente. No olvides apagarlo después de realizar la depuración. Este es un ejemplo de sesión de depuración:

Nota: utiliza el rastreo si puedes identificar cuál es el problema y reproducirlo fácilmente. Utiliza el registro para recoger estadísticas, elaborar perfiles de rendimiento, etc.

Además, la mayoría de los servidores web ofrecen herramientas de registro y seguimiento del rendimiento.

ISCLOG

CSP Gateway es útil para determinar problemas de red y hacer seguimiento del rendimiento, pero para registrar lo que ocurre dentro de Caché se necesitan otras herramientas. Una de las herramientas más versátiles es ISCLOG. Documentación.

Es un global que puede almacenar información sobre el procesamiento de las solicitudes actuales. Para iniciar el registro, ejecuta:

set ^%ISCLOG = 2

Y para terminar el registro, ejecuta:

set ^%ISCLOG = 0

Este es el ejemplo de una solicitud:

^%ISCLOG=0
^%ISCLOG("Data")=24
^%ISCLOG("Data",1)=$lb(2,"CSPServer","Header from CSP Size:3744 CMD:h IdSource:3","4664","FORMS","2017-06-07 10:49:21.341","%SYS.cspServer2","","")
^%ISCLOG("Data",1,0)="^h30000 "_$c(14,0,0)_"A"
^%ISCLOG("Data",2)=$lb(2,"CSPServer","[UpdateURL] Looking up: //localhost/forms/form/info path found: //localhost/forms/ Appl= "_$c(2,1,3,4)_"@"_$c(3,4,1,2,1,9,1)_"/forms/"_$c(2,1,3,4,1,2,1,2,1,2,4,3,4,1,2,1,9,1,7,1)_":%All"_$c(8,1)_"/forms"_$c(7,1)_"FORMS"_$c(2,1,2,1,3,4,1,2,1,2,1,3,4,1,2,1,4,4,132,3,3,4,2,3,4,2,2,1,4,4,16,14,2,4,3,4,1,3,4,1,2,1,3,4,1,2,1,16,1)_"Form.REST.Main"_$c(2,4,2,4),"4664","FORMS","2017-06-07 10:49:21.342","%CSP.Request.1","124","L3DfNILTaE")
^%ISCLOG("Data",3)=$lb(2,"CSPServer","[UpdateURL] Found cls: Form.REST.Main nocharsetconvert:  charset:UTF-8 convert charset:UTF8","4664","FORMS","2017-06-07 10:49:21.342","%CSP.Request.1","124","L3DfNILTaE")
^%ISCLOG("Data",4)=$lb(2,"CSPServer","[HTML] Determined request type","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer2","124","L3DfNILTaE")
^%ISCLOG("Data",4,0)=$lb("usesession",1,"i%Class","Form.REST.Main","i%Service","REST","NOLOCKITEM","","i%GatewayError","")
^%ISCLOG("Data",5)=$lb(2,"CSPSession","[%LoadData] Loading CSP session, nosave=0","4664","FORMS","2017-06-07 10:49:21.342","%CSP.Session.1","","L3DfNILTaE")
^%ISCLOG("Data",5,0)=$lb(900,,0,5567742244,$c(149)_"Ù"_$c(3)_"ó»à"_$c(127)_",½"_$c(149,10)_"\"_$c(18)_"v"_$c(128,135)_"3Vô"_$c(11)_"*"_$c(154)_"PÏG¥"_$c(140,157,145,10,131)_"*",2,"FORMS","001000000000L3DfNILTaE1cDBJNjyQdyLwKq4wCXP82ld8gic",,0,"ru","L3DfNILTaE",2,1,"/forms/",$lb("UnknownUser","%All,%Developer","%All,%Developer",64,-559038737),"","","","2017-06-07 10:48:51","2017-06-07 10:49:04","Basic ZGV2OjEyMw==","Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0","","",0,"/forms/","","","",4,"","","","","http://localhost:57772/formsui/index.html")
^%ISCLOG("Data",6)=$lb(2,"CSPServer","[CSPDispatch]Requested GET /forms/form/info","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",7)=$lb(2,"CSPServer","[CSPDispatch] ** Start processing request newSes=0","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",7,0)="/forms/form/info"
^%ISCLOG("Data",8)=$lb(2,"CSPServer","[CSPDispatch] Service type is REST has-soapaction=0 nosave=0","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",9)=$lb(2,"CSPServer","[CSPDispatch]About to run page: Form.REST.Main","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",9,0)=$lb("UnknownUser","%All,%Developer","%All,%Developer",64,-559038737)
^%ISCLOG("Data",10)=$lb(2,"CSPServer","[callPage] url=/forms/form/info ; Appl: /forms/ newsession=0","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",11)=$lb(2,"CSPServer","[callPage]Imported security context ; User: UnknownUser ; Roles: %All,%Developer","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",12)=$lb(2,"CSPServer","[OutputCSPGatewayData]: chd=1;","4664","FORMS","2017-06-07 10:49:21.431","%CSP.Response.1","","L3DfNILTaE")
^%ISCLOG("Data",13)=$lb(2,"CSPResponse","[WriteHTTPHeaderCookies] Session cookie: CSPSESSIONID-SP-57772-UP-forms-=001000000000L3DfNILTaE1cDBJNjyQdyLwKq4wCXP82ld8gic; path=/forms/;  httpOnly;","4664","FORMS","2017-06-07 10:49:21.431","%CSP.Response.1","124","L3DfNILTaE")
^%ISCLOG("Data",14)=$lb(2,"CSPServer","[callPage] Return Status","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",14,0)=1
^%ISCLOG("Data",15)=$lb(2,"CSPServer","[OutputCSPGatewayData]: chd=1;","4664","FORMS","2017-06-07 10:49:21.431","%CSP.Response.1","","L3DfNILTaE")
^%ISCLOG("Data",16)=$lb(2,"CSPServer","[Cleanup]Page EndSession=0; needToGetALicense=-1; nosave=0; loginredirect=0; sessionContext=1","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",17)=$lb(2,"CSPSession","[Cleanup] EndSession=0 nosave=0","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",18)=$lb(2,"CSPSession","[%SaveData] Saved: ","4664","FORMS","2017-06-07 10:49:21.431","%CSP.Session.1","","L3DfNILTaE")
^%ISCLOG("Data",18,0)=$lb(900,,0,5567742261,$c(149)_"Ù"_$c(3)_"ó»à"_$c(127)_",½"_$c(149,10)_"\"_$c(18)_"v"_$c(128,135)_"3Vô"_$c(11)_"*"_$c(154)_"PÏG¥"_$c(140,157,145,10,131)_"*",2,"FORMS","001000000000L3DfNILTaE1cDBJNjyQdyLwKq4wCXP82ld8gic",,0,"ru","L3DfNILTaE",2,1,"/forms/",$lb("UnknownUser","%All,%Developer","%All,%Developer",64,-559038737),"","","","2017-06-07 10:48:51","2017-06-07 10:49:21","Basic ZGV2OjEyMw==","Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0","","",0,"/forms/","","","",5,"","","","","http://localhost:57772/formsui/index.html")
^%ISCLOG("Data",19)=$lb(2,"CSPServer","[Cleanup] Restoring roles before running destructor","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","","L3DfNILTaE")
^%ISCLOG("Data",19,0)=$lb("UnknownUser","%All,%Developer","%All,%Developer",64,-559038737)
^%ISCLOG("Data",20)=$lb(2,"CSPServer","[Cleanup] End","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","","L3DfNILTaE")
^%ISCLOG("Data",20,0)="<-Finish processing request->"
^%ISCLOG("Data",21)=$lb(2,"GatewayRequest","[CSPGWClientRequest] GWID: ed-pc:57772; Request: sys_get_system_metricsTimeout: 5","11112","%SYS","2017-06-07 10:49:23.141","%SYS.cspServer3","","")
^%ISCLOG("Data",22)=$lb(2,"GatewayRequest","[CSPGWClientRequest] GWID: 127.0.0.1:57772; Request: sys_get_system_metricsTimeout: 5","11112","%SYS","2017-06-07 10:49:23.141","%SYS.cspServer3","","")
^%ISCLOG("Data",23)=$lb(2,"GatewayRequest","[SendSimpleCmd:Server:Failed] WebServer: 127.0.0.1:57772; Gateway Server Request Failed","11112","%SYS","2017-06-07 10:49:23.141","%CSP.Mgr.GatewayMgrImpl.1","","")
^%ISCLOG("Data",23,0)=0
^%ISCLOG("Data",24)=$lb(2,"GatewayRequest","[GetMetrics]","11112","%SYS","2017-06-07 10:49:23.141","%CSP.Mgr.GatewayMgrImpl.1","","")
^%ISCLOG("Data",24,0)="<-End Request Client->"

Además, este es un script rápido para la salida de global a un archivo:

set p="c:\temp\isclog.txt"
open p:"NW"
use p zw ^%ISCLOG
close p

 

Custom logging

Aunque las herramientas de registro predeterminadas son bastante buenas, tienen varios problemas:

  • Son genéricas y no están familiarizadas con tu solicitud
  • Las opciones más detalladas afectan al rendimiento
  • No están bien estructuradas, por lo que puede resultar difícil extraer información

Por lo tanto, se pueden cubrir casos más específicos escribiendo sistemas de registro personalizados. Este es un ejemplo de una clase persistente que registra parte del objeto %request:

/// Incoming request
Class Log.Request Extends %Persistent
{
/// A string indicating HTTP method used for this request.
Property method As %String;
/// A string containing the URL up to and including the page name
/// and extension, but not including the query string.
Property url As %String(MAXLEN = "");
/// A string indicating the type of browser from which the request
/// originated, as determined from the HTTP_USER_AGENT header.
Property userAgent As %String(MAXLEN = "");
/// A string indicating the MIME Content-Type of the request.
Property contentType As %String(MAXLEN = "");
/// Character set this request was send in, if not specified in the HTTP headers
/// it defaults to the character set of the page it is being submitted to.
Property charSet As %String(MAXLEN = "");
/// A <class>%CSP.Stream</class> containing the content submitted
/// with this request.
Property content As %Stream.GlobalBinary;
/// True if the communication between the browser and the web server was using
/// the secure https protocol. False for a normal http connection.
Property secure As %Boolean;
Property cgiEnvs As array Of %String(MAXLEN = "", SQLPROJECTION = "table/column");
Property data As array Of %String(MAXLEN = "", SQLPROJECTION = "table/column");
ClassMethod add() As %Status
{
    set request = ..%New()
    quit request.%Save()
}
Method %OnNew() As %Status [ Private, ServerOnly = 1 ]
{
    #dim %request As %CSP.Request
    #dim sc As %Status = $$$OK
    quit:'$isObject($g(%request)) $$$ERROR($$$GeneralError, "Not a web context")
    set ..charSet = %request.CharSet
    if $isObject(%request.Content) {
        do ..content.CopyFromAndSave(%request.Content)
    } else {
        set ..content = ""
    }
    set ..contentType = %request.ContentType
    set ..method = %request.Method
    set ..secure = %request.Secure
    set ..url = %request.URL
    set ..userAgent = %request.UserAgent
    set cgi = ""
    for {
        set cgi=$order(%request.CgiEnvs(cgi))
        quit:cgi=""
        do ..cgiEnvs.SetAt(%request.CgiEnvs(cgi), cgi)
    }
    // Only gets first data if more than one data with the same name is present
    set data = ""
    for {
        set data=$order(%request.Data(data))
        quit:data=""
        do ..data.SetAt(%request.Get(data), data)
    }
    quit sc
}
}

Para añadir un nuevo registro a la tabla Log.Request, agrega una llamada a tu código:

do ##class(Log.Request).add()

Es un ejemplo muy básico, puede y debe ampliarse para registrar comentarios, variables o cualquier otra cosa que puedas necesitar. La principal ventaja de este enfoque es la posibilidad de ejecutar consultas SQL sobre los datos registrados.  Para obtener más información sobre cómo crear tu propio sistema de registro, consulta este artículo.

Session events

La clase Event (Evento) es una clase que define las interfaces que se llaman durante la vida de un objeto %CSP.Session. Para utilizarla, hay que subclasificar %CSP.SessionEvents e implementar el código del método que quieres ejecutar. A continuación, en la configuración de la aplicación CSP, hay que establecer la clase de evento en la clase que has creado.

Las siguientes devoluciones de llamada están disponibles:

  • OnApplicationChange
  • OnEndRequest
  • OnEndSession
  • OnLogin
  • OnLogout
  • OnStartRequest
  • OnStartSession
    • OnTimeout

    Por ejemplo, los custom loggings comentado anteriormente pueden invocarse desde estos métodos.

    Output to device

    Una de las opciones más sencillas - un método de utilidad CSP que muestra todos los objetos como respuesta. Solo hay que añadir esto a cualquier parte de tu código:

    set %response.ContentType = "html"
    do ##class(%CSP.Utils).DisplayAllObjects()
    return $$$OK

     

    Conclusión

    Hay varias herramientas que se puede utilizar para depurar las aplicaciones web. Elige la más adecuada para la tarea que vayas a realizar.

     
    Y vosotros... ¿tenéis algún consejo o truco para depurar aplicaciones web desde Caché?

    Comentarios (0)2
    Inicie sesión o regístrese para continuar