Monday, 19 May 2025

Program logging

I was asked this morning how often user X had run procedure Y in the past few months. I explained that Priority saves (to the best of my knowledge) such data in the form of saved reports for a few days and then I delete those reports. Of course, I had deleted the reports this morning so I couldn't give any data.

What I could do was add logging procedure usage to Priority. First I defined a table TEST_PROGUSERS:

FieldTypeWidthTitle
PROGINT13> Procedure
USERINT13> User
CURDATEDATE14Date
DETAILSRCHAR48Details

Then I built a read-only form based on this table; this form is a son form of EPROG, the procedure generator. In the procedures who usage I want to track I added the following statement

INSERT INTO TEST_PROGUSERS (PROG, USER, CURDATE, DETAILS) SELECT EXEC.EXEC, SQL.USER, SQL.DATE, STRCAT (DTOA (:$.FDT, 'DD/MM/YY'), ',', DTOA (:$.TDT, 'DD/MM/YY')) FROM EXEC WHERE EXEC.ENAME = '$' AND EXEC.TYPE = 'P';

The 'details' field is supposed to contain the values of the parameters passed to the procedure. 

Now I can see at a glance who has run a given procedure and when, without having to rely on saved reports (which even if they exist are inaccurate as someone could send the output to Excel, thus preventing the report instance being saved).

Tuesday, 13 May 2025

Debugging in the web interface

Before I get started, I have to note that debugging in the web interface is a pain, when compared to debugging with the classic interface.

In the documentation can be found the following: A common step when debugging code that includes linked temporary tables is dumping the contents of the temporary table to a file. This is used to investigate the values the system was working with at a certain point in the code. This usually follows the structure:

SELECT COLUMN1, COLUMN2... FROM LINKED_TABLE
TABS :FILENAME;

A common question when developing on Priority Web is how to access these files in a situation when there is no access to the server machine.

I won't quote the documentation further because I think that it gives a false and incomplete solution. I want to show a solution that I developed that creates debug filest then saves them as attachments to a specific customer (www) for viewing. This solution also allows the creation of several files that is useful when the procedure creating those files is run under the TTS. I'll display the complete subroutine first after which I will explain the various lines.

[1] SELECT SQL.TMPFILE INTO :INFILE FROM DUMMY; [2] SELECT * FROM HTMLCOLORS TABS :INFILE; [3] SELECT STRCAT(SYSPATH('MAIL', 1), '/TEST/$,', DTOA (SQL.DATE, 'DD-MM-YY hh-mm'), '.txt') INTO :OUTFILE FROM DUMMY; [4] EXECUTE COPYFILE :INFILE, :OUTFILE; [5] SELECT SQL.TMPFILE INTO :TEST_FILE FROM DUMMY; [6] LINK GENERALLOAD RCF TO :TEST_FILE; [7] GOTO 901 WHERE :RETVAL <= 0; [8] INSERT INTO GENERALLOAD RCF (LINE, RECORDTYPE, TEXT6) [9] VALUES (1, '1', 'www'); [10] INSERT INTO GENERALLOAD RCF (LINE, RECORDTYPE, TEXT7, TEXT3) [11] VALUES (2, '2', :OUTFILE, 'Debug'); [12] EXECUTE INTERFACE 'TEXT_ADDEXT2CUST', SQL.TMPFILE, '-L', :TEST_FILE; [13] UNLINK AND REMOVE GENERALLOAD RCF; [14] LABEL 901;

The online documentation says to create a temporary file and output the required data to this file. This is what happens in lines 1 and 2. Line 3 creates a string whose value will be ../../system/mail/test' + name of the procedure + date and time.txt. This line differs from the website and it's important to explain why: the website uses the NEWATTACH procedure to create a filename - from my tests, this file will be in an arbitrary subdirectory of ../system/mail, e.g. ../../system/mail/202402/0mjw3vv/name of file.txt. In retrospect, this doesn't matter too much for reasons that I will explain shortly. Line 4 copies the temporary file to the filename that was built in the previous line; this causes a physical file to be created whose name is stored in :OUTFILE. 

Lines 5-13 are concerned with creating a new instance of GENERALLOAD and populating it with the customer www and the file that was created in line 4. As the variable :OUTFILE is used, it doesn't really make any difference if the SYSPATH or NEWATTACH method is used; in the web interface, the user can't see the directory, so it doesn't matter if the file is in a specific directory or in an arbitrary one.

The interface TEXT_ADDEXT2CUST has two forms: CUSTOMERS, where CUSTNAME ('www') is stored in field TEXT6 and CUSTEXTFILE (in the singular!), where the name of the file is stored in TEXT7 and the description in TEXT3. When I was developing the subroutine, a strange error message about the interface appeared; it transpires that I automatically used the son form EXTFILES (in the plural) as the second form in the interface, and not CUSTEXTFILE.

Two final notes:

  1. The attachments will be displayed in reverse order of addition, i.e. the first file will be the last to be created. This is because I couldn't be bothered to use the EXTFILENUM field in the interface. I think that it's better this way as one doesn't have to scroll through a list of files in order to find the newest.
  2. Deleting a line in the attachments form will delete the physical file! Newer versions of Priority display a warning message that it is not necessarily clear. This does allow old and irrelevant files to be removed.