Not really a detailed article, just sharing something that I've created on the weekend out of curiosity when I wanted to look at the contents of MQ messages that were put on a local queue. I wanted to see the MQMD header and this is how I have done, on z/OS.
You don't have to do this if you know the environment, but since I work in so many different clients and systems, cannot memorize it. I just list the basic resources and get the information that I want, in this case I wanted to see in which PSID the queue was stored.
You can do this via online commands, I prefer in batch mode because it is very verbose and allows me to go back and forth. Here is a sample:
https://github.com/bimonti/MQ/blob/main/CSQUTIL.JCL
The next step was to get the message from the MQ logs, the messages that were already processed, not the ones sitting on a queue. On z/OS we use the utility CSQ1LOGP for that. There are so many options on this one, you can use the Bootstrap to find the information, active logs, archived logs, etc.
I wanted any data, not a particular time frame or unit of recovery, so I just went with the active logs. Here is a sample:
https://github.com/bimonti/MQ/blob/main/CSQ1LOGP.JCL
The description of the parameters and how to use it:
https://www.ibm.com/docs/en/ibm-mq/9.4?topic=reference-log-print-utility-csq1logp-zos
Two things worth mentioning here. First is that I've only looked at committed data, I have only the CSQCMT DDname in my job. The second is that I made the SYSPRINT DDname as dummy so it does not echo the messages to the job's sysout. You can change that to any valid SYSOUT class if you would like to see the summary information.
The layout of the data is publicly available in the CSQ1LOPG page, here is the information:
I just created a DFSORT job using that information to print in a report format. The message is variable length at the end of the record, but I just printed the first 384 bytes, that is enough to cover the entire MQMD header and a few bytes of the actual message. If the record is shorter, the VLFILL parameter will add blanks to it.
I did not add column headers yet, but it should be fairly simple to follow along with the record description in the user guide. The fields that are stored in STCK format (Store Clock) are converted to ISO and printed as well. I used a technique that I have discussed before where I have a symbol in the JCL that can be either a blank space or a semicolon, I flip that if I want a report on SDSF or if I plan to download and process as CSV.
//EXPORT EXPORT SYMLIST=*
//*SV SET CSV=' '
//CSV SET CSV=';'
Here is the link to the job:
https://github.com/bimonti/MQ/blob/main/MQLGSORT.JCL
This is a print of the report, with the CSV format, that I ran on the IBM z Xplore platform using their sample MQ instance.