Question
· Oct 23, 2023

List of global referenced process, similar to $zreference

I need to develop a tool to help to get what data is being consumed by a certain process, in order to get all data used to build an automated test scenario.

For example, some user process will pull data from ^GLOBAL(1)="dataString", ^GLOBAL(2)="dataString2", ^GLOBAL1(1)="data1String", ^GLOBAL2(4)="data2String4". Amidst all other data on these Globals, I will ignore everything that was not used in the user process, and get the specific keys used on it.

I can see that Caché knows which Globals and such being referenced, and which keys were used, when looking at Process Details, on the Administrator Portal.

image

So, my idea is to run this “monitoring” process, and while the system is doing it, execute the user process, and get this list of referenced Globals, so I can build the automated test fairly quick.

What I already tried:

  • $ZREFERENCE
    • It gets exactly what was reference, but it seems it only sees what was used in the same process you run the command. So, it doesn't quite work for what I need.
  • Using LastGlobalReference of ##CLASS(%SYS.ProcessQuery).%OpenId($j)

    • I was able to get a bit far with this one. I was able to access data from other process, but it seems it doesn't update frequently enough.
  • Pull data from %SYS.ProcessQuery using SQL (snippet below)

    • Same problema as with the LastGlobalReference property.

Snippet:

    Set Rset = ##class(%ResultSet).%New("%SYS.ProcessQuery:ListPids")
    d Rset.Execute()
    While Rset.Next() {
     &sql(SELECT CommandsExecuted,GlobalReferences,GlobalUpdates,InTransaction,LastGlobalReference,
     NameSpace,OSUserName,PrivateGlobalReferences,PrivateGlobalUpdates,Routine,State,UserName
     INTO :CommandsExecuted,:GlobalReferences,:GlobalUpdates,:InTransaction,:LastGlobalReference,
     :NameSpace,:OSUserName,:PrivateGlobalReferences,:PrivateGlobalUpdates,:Routine,:State,:UserName
     FROM %SYS.ProcessQuery
     WHERE OSUserName = 'Quarkus')
     i SQLCODE'=0 w !,"SQL Error "_SQLCODE continue ; 100 means process does not exist (halted)7
     ;
     set dados=CommandsExecuted_" | "_GlobalReferences_" | "_GlobalUpdates_" | "_InTransaction_" | "_LastGlobalReference_" | "_
     NameSpace_" | "_OSUserName_" | "_PrivateGlobalReferences_" | "_PrivateGlobalUpdates_" | "_Routine_" | "_State_" | "_UserName
     ;
     set ^mtempCaptura(1,$i(^mtempCaptura(1)),1)="all | "_$get(dados)
    }
    ;
    d Rset.Close()

So, this is where we are at right now.

I believe I might be missing something basic on how to access this data. I was wondering if there is a built-in tool that does what we need, or if somebody else already built something similar to this. Likewise, I don't believe that what I need to do is so specific no one else tried, so, if there isn't something built-in, or no one ever did it, so it might not even be possible. But I will hold on to hope.

Thanks!

$ZV: Cache for Windows (x86-64) 2018.1.3 (Build 414U) Mon Oct 28 2019 11:18:40 EDT
Discussion (12)3
Log in or sign up to continue

Fortunately, I just need to read the data. There won't be anything writing back to the database.

Important to say, this is intended for development purposes only. We need a way to build automated processes faster. So, instead of manually populate the couple dozens Globals we would need to in order to test a simple scenario, we would use would development databases to capture this data.

So, with the same data we use when testing; business-rules and, consequently, interfaces, we can build the automated tests way faster.

The way I would gather the globals the process looks at would be to slip something into the logon code that traced all the $zr changes to a trace file. Its not exactly what you asked for as it wouldn't be on a different process.

    s %oldzr=""

    zbreak /trace:all:"/durable/trace.log"

    zbreak $:"T":"%oldzr'=$zr":"s %oldzr=$zr w $zr"

    d ..yourthing()

You could try to %Studio.Debugger Attach to the user's process and do a similar thing.

the above approach ist the right way. And I do not see any problem there:

First, in the very first line (of the question) it's stated: "I need to develop a tool ... what data is being consumed by a certain process, ... to build an automated test scenario.", which means, this will be used during a development and/or test phase to gather informations about the touched globals (for automated tests). So the performance is not an issue.
 
Second, the suggestion of Paul Waterman can always run, assuming the process runs with the required right and flag. One can always provide the required conditions.