Written by

ERP Developer
Question João Carlos Azevedo · 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

Comments

Robert Cemper · Oct 23, 2023

Part of it (KILL, SET, TSTART, TCOMMIT, TROLLBACK) by global by process can be traced by examination of JOURNAL

There is nothing similar for Global READ
  

0
João Carlos Azevedo  Oct 23, 2023 to Robert Cemper

Robert, Hi! Thanks for the reply!
I checked the Journaling built-in function, but as you know, it lacks the ability to get what was just referenced. I will use the journal to get what has changed during the process, but this is just a small part of what I need.

0
Dmitry Maslennikov  Oct 24, 2023 to Cristiano Silva

No, do not touch $View and View, if you don't know what you are doing, this is low-level work, and you can damage the database file.

0
João Carlos Azevedo  Oct 24, 2023 to Dmitry Maslennikov

Hi!
Can you elaborate on what I should look into more carefully when using $View?
We have several databases for development, all backed up, and can clone whenever, so to mess with it would not be a problem. The tool itself is meant to be run by developers.

I'm interested on what I should not touch there, though.
Thanks!

0
Dmitry Maslennikov  Oct 24, 2023 to João Carlos Azevedo

$view, as far as I know has nothing to do with the question, view together with $view operates with Database blocks, read, and the dangerous part is to write to, if you wrongly use parameters, you can destroy the database file. 

0
João Carlos Azevedo  Oct 26, 2023 to Dmitry Maslennikov

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.

0
Dmitry Maslennikov  Oct 26, 2023 to João Carlos Azevedo

I got you, and I think, that Robert's suggestion is the best at the moment.

0
Paul Waterman · Oct 31, 2023

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.

0
Dmitry Maslennikov  Nov 1, 2023 to Paul Waterman

well, this is a good hack, but there are a few notes worth mentioning

  • it will affect the performance of the code
  • it will not work on processes that running not from Terminal

So, it is only suitable for debugging purposes, do not use in production

0
Julius Kavay  Nov 1, 2023 to Dmitry Maslennikov

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.

0