Artículo
· 3 mayo, 2022 Lectura de 14 min

Depuración tradicional en ObjectScript

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
    •  Property 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>
      es obvio que la depuración de %0AmBk1+5^%sqlcq.DEMO.cls33.1 está fuera de nuestro alcance
      •  
    • 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: &lt;&lt;nothing>>.
        Enter &lt;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
                                     ^
        &lt;BREAK>%0AmBk1+5^%sqlcq.DEMO.cls33.1
        DEMO 10d3>zw %SNGetQueryStats=1
        SQLCODE=0
        rcc=1
        
        DEMO 10d3>zwrite $this
        45@%sqlcq.DEMO.cls33  ; &lt;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 = ""  &lt;Set>
        |   r%%PrivateTables = ""  &lt;Set>
        |    (i%%ProcCursor) = ""
        |    (r%%ProcCursor) = ""
        |          (i%%rsmd) = ""
        |          (r%%rsmd) = "50@%SQL.StatementMetadata"
        +--------------- calculated references ---------------
        | %StatementTypeName   &lt;Get>
        |                 ID   &lt;Get>  [ Aliases - id ]
        |               Name   &lt;Get>  [ Aliases - name,NAME ]
        |             Random   &lt;Get>  [ Aliases - random,RANDOM ]
        +----------------------------------------------------- DEMO 10d3>g
                Newton,Olga Z.  1  . try {  Set rcc=$Random(5) BREAK  Set i%RandomO1 = $Random(10)/rcc
                                     ^
        &lt;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
                                     ^
        &lt;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: &lt;-350>]
        [%msg: &lt;Unexpected error executing SqlCompute code for field 'Random': &lt;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.
Comentarios (0)2
Inicie sesión o regístrese para continuar