Encontrar errores en tu código o examinar un comportamiento inesperado es el principal objetivo de la depuración.
Trataré de actualizar las herramientas tradicionales aparte de las ayudas que tienen Studio, VScode, Serenji... Las herramientas básicas que han estado ahí antes de que tu EDI preferido lo utilizara en segundo plano. Observamos 3 situaciones habituales:
- Depuración desde la línea de comandos en primer plano desde un terminal o una sesión similar.
- Si es posible, el antiguo comando BREAK (también con una postcondición) Te permite detenerte y examinar la situación cuando lo necesites. Es la opción más antigua, que se remonta al periodo anterior a ObjectScript.
- Más nuevo, pero similar, el comando ZBREAK, introduce puntos de control, además de simples Puntos de interrupción y un sofisticado conjunto de condiciones.
- Aquí puedes consultar más información sobre la Depuración desde la línea de comandos
- Depuración en segundo plano
- Todo lo que se describe aquí es, por supuesto, igualmente útil y está disponible para la depuración desde la línea de comandos
- Primero, tienes la opción de escribir información adicional en un Global (temporal).
- Esto es útil si ya tienes una sospecha bastante clara de lo que hay que revisar
- Después, puedes volcar sus variables reales también a SPOOL o utilizar una salida redirigida
- o llamar a LOG^%ETN() para volcar toda la partición en ^ERRORS Global
- y examinarlo con SMP/System Operation/Application error log
- Como forma de mover el código de background al primer plano en la línea de comandos, puedes utilizar la depuración desde el intérprete de comandos o Shell.
- Esto se aplica normalmente a SQL y CSP/ZEN
- Depuración desde el intérprete de comandos
- Empiezo con una página CSP bastante simple como un ejemplo que contiene este código:
. . . </head> <script language="Cache" method="init" arguments="file,.tName" returntype="%Integer"> BREAK ;; <<<< for debugging if 'file { set tName="*** no file ***",index="" } elseif $D(^ImportFile(file,-1)) { set tName=$O(^ImportFile(file,-1,"Class",""),1,index) } Else { set tName=$g(^ImportFile(file)),index=0 } quit index </script> <script language="Cache" method=
- Ahora ejecuto esto desde mi CSPshell y puedo ver y acceder a todas las variables y objetos
-
IRISAPP> IRISAPP>do $system.CSP.Shell() CSP Shell CSP:IRISAPP>>> GET /csp/irisapp/Details.csp HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Set-Cookie: CSPSESSIONID-UP-csp-irisapp-=15340 15340; path=/csp/irisapp/; httpOnly; sameSite=strict; Cache-Control: no-cache Date: Tue, 23 Nov 2021 19:03:29 GMT Expires: Thu, 29 Oct 1998 17:04:19 GMT Pragma: no-cache <html> <head> <!-- Put your page Title here --> <title> Details </title> <script language="javascript"> window.onmessage = function(event){ }; </script> <!-- function postDebug(item, index) { var escape = item.replace(/\//g, '-'); // fix slashes in dates //var escape = encodeURI(escape); var escape = encodeURIComponent(escape); // fix % and more if (item == '') escape = 'NULL'; //document.getElementById("div_debug").innerHTML += index + "," + escape + "<br>"; var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { //document.getElementById("div_debug").innerHTML += this.responseText; } if (this.readyState == 4 && this.status != 200) { //document.getElementById("div_debug").innerHTML += this.responseText; } }; //xhttp.open("GET", "/restAll/debug", true, "_SYSTEM", "SYS"); //xhttp.open("POST", "/restAll/click/" + escape + '/' + index, true, "_SYSTEM", "abc123"); xhttp.open("POST", "/restAll/click/" + escape + '/' + index, true, "_SYSTEM", "SYS"); ;xhttp.send(); } </script --> </head> <body> <table> <BREAK>zinit+1^csp.details.1 ;<<<<<<<<<<<<<<<<<<<<<<<<<<< IRISAPP 15e1>zwrite %CSPsc=1 %SYSLOG=1 %request=<OBJECT REFERENCE>[4@%CSP.Request] %response=<OBJECT REFERENCE>[1@%CSP.Response] %session=<OBJECT REFERENCE>[2@%CSP.Session] file=0 tDEBUG=3 tData="class,dc.data.rcc.GMbadge" tFile1=0 tFile2=0 tWhat="class" IRISAPP 15e1>zwrite %request %request=4@%CSP.Request ; <OREF> +----------------- general information --------------- | oref value: 4 | class name: %CSP.Request | reference count: 5 +----------------- attribute values ------------------ | AppData = $lb("",64,1,"","/csp/irisapp/","",1,"","",0,1,"","","/csp/irisapp","IRISAPP","","c:\intersystems\iris\csp\irisapp\",1,"","",1,"",900,2,2,"",3600,0,1,1,"",1,"","",1,1,0,2,2) <Set> | AppMatch = "/csp/irisapp/" <Set> | Application = "/csp/irisapp/" <Set> | CSPGatewayRequest = 0 <Set> | CharSet = "" <Set> | Class = "csp.details" <Set> | ContentType = "" <Set> | (ConvertCharSet) = "UTF8" | GatewayApplication = "" <Set> | GatewayBuild = "" <Set> |GatewayConnectionName = "" <Set> | GatewayError = "" | GatewayFunctions = "" <Set> |GatewayInstanceName = "" <Set> | GatewayNewId = 0 |GatewaySessionCookie = "" <Set> |GatewaySessionIdSource = "" <Set> | GatewayTimeout = 60 | Method = "GET" | NoResetTimeout = 0 | PageName = "Details.csp" |ProcessedRequestType = 1 | Protocol = "HTTP/1.1" <Set> | RegistryMethods = 1 | RequestId = "" | Secure = 0 <Set> | Service = "CSP" <Set> | URL = "/csp/irisapp/Details.csp" | URLPrefix = "" | UserAgent = "" <Set> +----------------- swizzled references --------------- | i%Content = "" | r%Content = "" +----------------------------------------------------- IRISAPP 15e1>zwrite %session %session=2@%CSP.Session ; <OREF> +----------------- general information --------------- | oref value: 2 | class name: %CSP.Session | %%OID: $lb("15340","%CSP.Session") | reference count: 5 +----------------- attribute values ------------------ | %Concurrency = 1 <Set> | AppTimeout = 900 | Application = "/csp/irisapp/" <Set> |ApplicationLicenses = "" | BrowserName = "" <Get> | BrowserPlatform = "" <Get> | BrowserVersion = "" <Get> | ByIdGroups = "" | CSPSessionCookie = "15340 15340" | CookiePath = "/csp/irisapp/" | CreateTime = "2021-11-23 18:56:54" <Set> | Debug = 0 <Set> | EndSession = 0 <Set> | ErrorPage = "" |(EventClassContext) = "" | GetNewId = 0 | GroupId = "" | HttpAuthorization = "" | KeepAlive = 1 | Key = "3"_$c(3)_"±Ð~"_$c(129)_"t¼Ø´0"_$c(0)_"òÆÆùXNX"_$c(158)_"Å="_$c(152,1)_"T*"_$c(10)_"®«®"_$c(21) <Set> | Language = "de" | LastModified = "2021-11-23 18:58:28" <Set> | LicenseId = "_SYSTEM" <Set> | LogoutCleanup = 0 | MessageNumber = 1 <Set> | Namespace = "IRISAPP" | NewSession = 0 <Set> | (NoLicense) = 0 | OldTimeout = 5708603608 <Set> | PersistentHeaders = "" <Set> | Preserve = 0 <Set> | ProcessId = "" | Referrer = "" <Set> | RunNamespace = "" <Get,Set> | SOAPRequestCount = 0 |SecureSessionCookie = 0 | SecurityContext = $lb("_SYSTEM","%All,%DB_IRISLIB,%DB_IRISSYS","%All,%DB_IRISLIB,%DB_IRISSYS",32,-559038737) <Set> | SessionId = 15340 | SessionScope = 2 | (StickyLogin) = $lb("/csp/irisapp/","_SYSTEM",$lb("_SYSTEM","%All,%DB_IRISLIB,%DB_IRISSYS","%All,%DB_IRISLIB,%DB_IRISSYS",32,-559038737),"",0,0,0,1) <Get,Set> | UseSessionCookie = 2 | UserAgent = "" | UserCookieScope = 2 | nosave = 0 +--------------- calculated references --------------- | EventClass <Get,Set> | Username <Get> +----------------------------------------------------- IRISAPP 15e1>zwrite %response %response=1@%CSP.Response ; <OREF> +----------------- general information --------------- | oref value: 1 | class name: %CSP.Response | reference count: 5 +----------------- attribute values ------------------ | AllowOutputFlush = 0 |AvoidPartitionCleanup = 0 | (CSPGatewayData) = "" <Set> | CharSet = "utf-8" | ContentLength = "" | ContentType = "text/html" | CookiePath = "/csp/irisapp/" | Domain = "" | GzipOutput = "" <Set> | HTTPVersion = "" | HeaderCharSet = "" |Headers("CACHE-CONTROL") = "no-cache" | Headers("DATE") = "Tue, 23 Nov 2021 19:03:29 GMT" | Headers("EXPIRES") = "Thu, 29 Oct 1998 17:04:19 GMT" | Headers("PRAGMA") = "no-cache" | IgnoreRESTOutput = "" | InProgress = 1 <Set> | Language = "de" <Set> | NoCharSetConvert = 0 | OutputSessionToken = 1 | Redirect = "" | ServerSideRedirect = "" | Status = "200 OK" | Timeout = "" <Set> | TraceDump = 0 | UseASPredirect = 0 <Set> | UseHttpOnly = 1 | VaryByParam = "" +--------------- calculated references --------------- | Expires <Get,Set> +----------------------------------------------------- IRISAPP 15e1>g <BREAK>zinit+1^csp.details.1 IRISAPP 15e1>g <!-- tr><th colspan="3">#(tName)#</th></tr --> <tr><th>Line</th><th>*** no file ***</th><th>Line</th><th>*** no file ***</th></tr> </table> </body> </html>
- El siguiente ejemplo se refiere a SQL y utilizo esta propiedad calculada que falla de vez en cuando
es obvio que la depuración de %0AmBk1+5^%sqlcq.DEMO.cls33.1 está fuera de nuestro alcanceProperty Random As %Numeric(SCALE = 2) [ Calculated, SqlComputed, SqlComputeCode = { Set rcc=$Random(5) BREAK Set {*} = $Random(10)/rcc} ]; ---------------------------------------------------------------------------- SQLquery= "select top 10 id,name,random from Sample.Person" ---------------------------------------------------------------------------- throws [SQLCODE: <-350> . . . ] [%msg: <Unexpected error executing SqlCompute code for field 'Random': <DIVIDE>%0AmBk1+5^%sqlcq.DEMO.cls33.1>]</pre></li> - Para la depuración yo utilizo el SQLshell para aprovechar mi BREAK para ver todas las variables y objetos
-
DEMO> DEMO>do $system.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: <<nothing>>. Enter <command>, 'q' to quit, '?' for help. [SQL]DEMO>>select top 10 id,name,random from Sample.Person 2. select top 10 id,name,random from Sample.Person ID Name Random . try { Set rcc=$Random(5) BREAK Set i%RandomO1 = $Random(10)/rcc ^ <BREAK>%0AmBk1+5^%sqlcq.DEMO.cls33.1 DEMO 10d3>zw %SNGetQueryStats=1 SQLCODE=0 rcc=1 DEMO 10d3>zwrite $this 45@%sqlcq.DEMO.cls33 ; <OREF> +----------------- general information --------------- | oref value: 45 | class name: %sqlcq.DEMO.cls33 | reference count: 6 +----------------- attribute values ------------------ | %CurrentResult = "45@%sqlcq.DEMO.cls33" | %CursorNumber = 1 | %ExtendedMetadata = $lb($lb("Sample.Person||ID","%Library.BigInt",18),$lb("Sample.Person||Name","%Library.String",10),$lb("Sample.Person||Random","%Library.Numeric",14)) | %Message = "" | %Metadata(0) = $lb(3,"ID",-5,19,"0",1,"ID","Person","Sample",0,$c(0,0,0,1,0,0,0,0,0,0,0,0,0),"Name",12,50,"0",0,"Name","Person","Sample",0,$c(0,0,0,0,0,0,0,0,0,0,0,0,0),"Random",2,15,"2",1,"Random","Person","Sample",0,$c(0,0,0,0,0,0,0,0,0,0,0,0,0)) | (%NextColumn) = 1 | %Objects = "" | %OutputColumnCount = 0 | %Parameters = "" | %ROWCOUNT = 0 | %ROWID = "" | %ResultColumnCount = 3 | %SQLCODE = 0 | (%SelectMode) = 0 | %StatementType = 1 | (%delock11) = "" | %routine = "" | CursorState = 1 | (ID1) = 1 | (IDO1) = "" | (NameO1) = "Newton,Olga Z." | (PpCallArgs1) = 10 | (Vrowcnt17) = 0 | (isolationMode) = 0 | (lockstat11) = 0 | (node2val21) = $lb("",82732383,"OptiPlex Media Inc.",34350,"V968","P1169","OR","E8259","Z4197","","Newton,Olga Z.","U4734","P4","U8988","W9047","992-61-9877",-92713954810893571,"2018-07-16 17:44:34") | (rowcnt) = 0 | (rowlimit) = 9223372036854775807 | (starttime) = 9966.938434 | (time) = .000001 | (vpRUNTIMEOUT3) = "Newton,Olga Z." +----------------- swizzled references --------------- | i%%PrivateTables = "" <Set> | r%%PrivateTables = "" <Set> | (i%%ProcCursor) = "" | (r%%ProcCursor) = "" | (i%%rsmd) = "" | (r%%rsmd) = "50@%SQL.StatementMetadata" +--------------- calculated references --------------- | %StatementTypeName <Get> | ID <Get> [ Aliases - id ] | Name <Get> [ Aliases - name,NAME ] | Random <Get> [ Aliases - random,RANDOM ] +----------------------------------------------------- DEMO 10d3>g Newton,Olga Z. 1 . try { Set rcc=$Random(5) BREAK Set i%RandomO1 = $Random(10)/rcc ^ <BREAK>%0AmBk1+5^%sqlcq.DEMO.cls33.1 DEMO 10d3>zwrite %SNGetQueryStats=1 SQLCODE=0 rcc=1 DEMO 10d3>g Adam,Emily G. 7 . try { Set rcc=$Random(5) BREAK Set i%RandomO1 = $Random(10)/rcc ^ <BREAK>%0AmBk1+5^%sqlcq.DEMO.cls33.1 DEMO 10d3>zw %SNGetQueryStats=1 SQLCODE=0 rcc=0 DEMO 10d3>g ; now we get the error [SQLCODE: <-350>] [%msg: <Unexpected error executing SqlCompute code for field 'Random': <DIVIDE>%0AmBk1+5^%sqlcq.DEMO.cls33.1>] 2 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0003s/4/137/0ms execute time(s)/globals/cmds/disk: 44.5198s/37/839/0ms cached query class: %sqlcq.DEMO.cls33 --------------------------------------------------------------------------- [SQL]DEMO>>q DEMO>
- Y, como puedes ver, estos métodos de depuración actualmente también funcionan en IRIS.
- Esta es una práctica personal recomendada por Robert Cemper.
-
- Empiezo con una página CSP bastante simple como un ejemplo que contiene este código: