1

I remember seeing an article somewhere that outlined a clever way to wrap a UniVerse verb, like SELECT, in a custom basic program in order to record some metrics such as elapsed time. The easy answer is to share that link, if you are familiar with that article.

Otherwise, I appreciate any sample code you might be able to share that exemplifies the proper way to create such a wrapper.

I would like to write some data to a file, and capture things like the user, the file involved, the amount of time used to perform the selection, and whatever phrase was included with the SELECT statement. I plan to send this data to another system for analysis and reporting, so that we can better visualize how well various selections are performing.

Thanks for your time and I am looking forward to discussing a solution with you!

UPDATE!

After seeing Van's answer, I must clarify that I am most interested in recording the processing time of the statement, and gleaning some other information purely for logging purposes. My goal is to make it transparent so that I don't end up breaking everything or anything.

My logic is something more like this:

  • Statement is fired, and wrapper program makes note of the current time.
  • The plain vanilla sentence is executed by the wrapper.
  • When the selection is complete, wrapper notes the current time again and records the difference from start time.
  • While we're in here, use various SYSTEM(x) and/or @ values to capture user name and maybe the number of records.
  • Use some logic to parse the statement and record other interesting tidbits.
  • Write the interesting values to one log file, with incrementing ID.
  • User or proc is oblivious and ends up with the select list as usual (somehow... insert magic here)
  • Some other decoupled process feeds each record to a reporting system in regular batches.

Does that make more sense?

wags
  • 149
  • 12

2 Answers2

1

I will caveat this by saying that I would be terrified to try anything liek this on a production system for 3 reasons.

  1. SELECT is used in lots of places and this could quickly become an I/O issue if you have lots of Phantoms and users running stuff at the same time which leads into...
  2. Depending on the number of files your system has finding a way to meaningfully organizing the data in a way that does not invite locking or overwriting issues would be a large challenge.
  3. SELECT has a pick style usage and a SQL style usage and they do not behave the same.
  4. This is hacky as all get out.
  5. Counting is for wimps.

That said, you can pretty much replace any word in the VOC. You could copy the VOC entry for SELECT into SELECT.BASE and then replace it with your own cataloged SELECT where you catch the command line parameters as such.

SENTENCE       = @COMMAND
FILE.NAME      = FIELD(SENTENCE,' ',2)
CONDITIONS     = FIELD(SENTENCE,' ',3,999)
NEW.STMT       = "SELECT.BASE ":FILE.NAME:" ":CONDITIONS

You would then do whatever ever sort of processing before or after you EXECUTE NEW.STMT.

I have no idea what this will break so try it at your own risk.

Van Amburg
  • 1,207
  • 9
  • 15
  • Hi Van! I love your list and I appreciate you stepping up with a concept. I see how this can quickly get out of control. Fortunately, I have a development server and will be doing my testing there. I am updating my original question after seeing where you took this. I am trying to do some stealth logging, not break everything! – wags Feb 10 '16 at 01:57
  • Well then, I would start with the method I outlined a above. Make a test wrapper program that executes the base select and just see if that works. From there I would begin implementing your requirements within your overriden SELECT. Going over those in turn would be kind of out of the scope of the normal Stack Exchange paradigm as we would be solutioning instead of problem solving. Like most folks here, I enjoy problem solving but I get paid to solution. :-) – Van Amburg Feb 10 '16 at 16:16
  • Thanks Van. My problem now is returning the list that was gathered in the wrapper program to TCL. The isolated case is running a basic program that gathers a list, and activates that list at TCL when the program is done (so that the prompt turns into `>>`). Is that even possible? – wags Feb 10 '16 at 17:46
  • Check out the VOC section in the System Description guide. You probably need to add a K into line 3 of your VOC entry – Van Amburg Feb 10 '16 at 19:28
  • Sorry, Line 4, not Line 3. – Van Amburg Feb 10 '16 at 20:12
  • I will check that out. Thanks for the guidance! I've only been able to hack on it a little bit between meetings today. – wags Feb 10 '16 at 20:57
  • That VOC section in the System Description guide was the ticket. I don't think I would have found that without your help. Thanks! And for a pro tip... make sure you use `SELECT.BASE` within the basic program, otherwise it will call itself repeatedly and promptly log you off the system. – wags Feb 12 '16 at 21:41
  • Ahh yes, the dreaded "recursion: see recursion" stack overflow, I know it well! I am happy to have been of service. – Van Amburg Feb 14 '16 at 17:19
  • Van, I inadvertently introduced a pretty big bug... any select list already active before my wrapper program is called is ignored. I see that I can use `SYSTEM(11)` to detect if list zero is active. Is it possible to make the selection within the wrapper program respect that original list and return a filtered set of results rather than starting over? – wags Feb 22 '16 at 14:56
  • Are you doing anything with the active list in your procedure? If the list is active and you invoke another query I would expect it execute against the active list. – Van Amburg Feb 22 '16 at 15:35
  • No, I am not doing anything to check for an active list. I am just building a new command and then using the `EXECUTE` command to run it. My guess is that this is running as a sub-process, oblivious to the original context. Are there any special variations of the `EXECUTE` statement that I need to use (I'm on pick flavor)? It currently looks like this: `EXECUTE NEW.CMD SETTING NEW.LIST`. I noticed that the `RTNLIST` clause does not return the list to TCL correctly. Is it possible that list zero is not being used because of the way I have this set up? – wags Feb 22 '16 at 15:48
  • I would just execute it an not set anything. Just do the select and check @SELECTED for the count. – Van Amburg Feb 22 '16 at 20:56
  • I noticed that the sample program does it this way too. (Not sure if you saw it, but I added that link as a separate answer.) Alas, no change. Does my `PICK` flavor on the account make a difference? I'm wondering if I need to be tweaking things like `$OPTIONS -VAR.SELECT` in my wrapper program, but that is only a stab in the dark. Still researching... – wags Feb 22 '16 at 21:12
  • Ok, the solution is to check for an active list, and to get that list if there is one (using `READLIST`). Then, if there is an active list, use the `PASSLIST` parameter with `EXECUTE` to pass that active list. If there isn't an active list, just use plain old `EXECUTE`. This seems to work but I have to beat it up some more. – wags Feb 22 '16 at 21:56
  • The flavor is a likely suspect. My test worked as I would have expected it to in flavor 4. – Van Amburg Feb 22 '16 at 23:13
0

The sample program that I ran into a while ago was in one of Rocket Software's GitHub repos, multivalue-lab. The program there is called VERBTIMER.

However, that program also exhibits the bug I found in my own experimenting, where any previous active select list is ignored.

I opened an issue on GitHub and will update this post if a solution is found.

wags
  • 149
  • 12