Go to Home Page
Questions?
Call 1-800-572-5517
 
  Go to Home Page  
  See all products
  See price schedules
  See manuals, tutorials, articles
  Download a free 30-day trial
  See user testimonials
  About Pacific Systems Group
 
 
SMF Tools
  See SMF Record Layouts
  See Sample SMF Reports
  Learn How to Export SMF Data
  Download Free SMF Reporting Software (30 days)
 
One of the greatest SMF record parsing programming languages I've ever seen. Chief, Large Systems Services Branch, NIH
  Choose Spectrum Writer to add 4GL to your product
  Report Writer Speedup Tips Article
Spectrum SMF Writer - Low-Cost 4GL Report Writer for SMF Files.

Sample Dataset Access Report with RACF User Information Combining SMF 14, 15, 17 and 30 Records

It's easy to report on SMF data!
 

SMF Spectrum Writer
We have a low-cost 4GL report writer especially for SMF files. It's called Spectrum SMF Writer.

Spectrum SMF Writer handles the difficult SMF record parsing for you automatically. You just specify which fields you want to see.

Spectrum SMF Writer also converts the arcane date and time fields and reformats them into an attractive report.

Plus Spectrum SMF Writer even exports SMF data as comma delimited files to use on your PC.
 
Try It FREE Now!


The sample SMF report below was created with Spectrum SMF Writer, the low-cost 4GL SMF report writer.

In this report, we want to show who accessed a dataset. We include read access (from SMF 14 records), write/created access (from SMF 15) and deletes (from SMF 17). We combine these for our report. And we also find a matching SMF 30 record for the jobs involved. From the SMF 30 record, we can show the RACF group, userid and terminal that accessed the datast.

This is a bit challenging even for Spectrum SMF Writer. It is mostly intended to process one record at a time. Using data from two different records at the same takes a little extra effort. However, this example shows how you can accomplish this by using two Spectrum SMF Writer steps. (You could do it in a single step if you didn't want the RACF information.)

The first step selects 4 types of records. All SMF 14, 15, 17 and 30-4 records will be included. For each record, we build a Job ID field. This field will be unique for each job in the SMF file. We then sort our "report" output on this JOBID field. That sorts all the various SMF records for the same job together. Our secondary sort is on SMF record type (descending). That ensures that for jobs with both a 14/15/17 and a 30 record, the 30 record will come first. Now, instead of printing a report in this step, we simply write these sorted SMF records out intact. We write these selected and sorted SMF records to a temporary dataset.

Now we run the second Spectrum SMF Writer step. It reads the sorted SMF 14, 15, 17 and 30 records from our temporary dataset. We are only going to select the SMF 14, 15 and 17 records for our report. These are the records that indicate some sort of dataset access. For each of these SMF records, we will write one line to our report.

However, we still need to obtain the RACF information associated with the job that access the datasets. The RACF information will be in the matching SMF 30 record that was read just before all of the SMF 14/15/17 records from the same job. So we need a way to save those RACF fields from the SMF 30 records as they are read (and then excluded from the report). We save the RACF group a computed field named SAVE_RACF_GROUP so that it remains available when we read further to the matching SMF 14/15/17 records that follows. We can then use this saved RACF group name along with all of the fields from the then-current SMF 14/15/17 records to print our report line.

The special RETAIN parm of the COMPUTE statement is what enables us to save this RACF information from the SMF 30 record as it passes by.

As each SMF record is read, a vaslue is assigned to the SAVE_RACF_GROUP compute field. When the record is type 30, we assign the value of that SMF 30 record's RACF group name field (SMF30GRP). (However, we do not include this SMF 30 record in the report.) When the record is not 30 (meaning that it must be type 14/15/17), we do not assign a new value to this compute field. Instead, we "retain" the value that it was assigned for the previous 30 record (as long as the jobid's match.) Then we include the SMF 14/15/17 record in our report. And now we also have the retained RACf group name (from the previous type 30 record) available to include in the report line, along with all of the fields from the SMF 14/15/17 record. We used the same technique to save the RACF Userid and Terminal fields. We also saved the JOBID from the SMF 30 record so that we could later verify that it matched the 14/15/17 records that follow it. To print our final report in this second step, we have to use compute fields to move data from the current 14 or 15 or 17 record to a common "dataset" name field, for example. We then listed our computed dataset name in the COLUMNS statement. We couldn't name the SMF record's field directly, since it is found at different locations in the 14/15 and 17 records. Note that long-running jobs that were still executing when the SMF file was dumped, do not have RACF information. That information was not available since the SMF 30 record had not yet been written.

All of this with just a few lines of code!
Why not install a Spectrum SMF Writer trial right now and start making your own SMF reports!

These Spectrum SMF Writer Statements:

//*=================================================================
//* THIS STEP WRITES JUST 14, 15, 17 AND 30-4 RECORDS, IN SORTED ORDER
//*=================================================================
//STEP1 EXEC PGM=SPECTSMF,REGION=4M
//STEPLIB  DD DSN=PACSYS01.SPECTSMF.LOADLIB,DISP=SHR               
//SWCOPY   DD DSN=PACSYS01.SPECTSMF.COPYLIB,DISP=SHR COPY LIBRARY  
//SWLIST   DD SYSOUT=*,OUTLIM=50000 CONTROL LISTING
//SWOUTPUT DD DSN=&&TEMPSMF,DISP=(,PASS),UNIT=SYSDA,
//            SPACE=(CYL,(10,10),RLSE),
//            DCB=(RECFM=VB,LRECL=32752,BLKSIZE=32760)
//SWOUT002 DD SYSOUT=* 2ND LOG REPORT, IF USED
//SYSOUT   DD SYSOUT=* SORT CONTROL LISTING
//SMFIN    DD DSN=PACSYS01.MYSMF.DATA,DISP=SHR
//SYSIN    DD * CONTROL STATEMENTS
OPTION:  MAINFRAME               /* OUTPUT IS A MAINFRAME FILE */

*====================================================================
* DEFINE ONE FILE WHICH HAS THE FIELDS FROM ALL 4 COPYBOOKS
*====================================================================
FILE:       SMFIN LRECL(32767) DDNAME(SMFIN) KEEPRDW
COPY:       REC14
COPY:       REC15
COPY:       REC17
COPY:       REC30

INPUT:      SMFIN
FIELD:      RECORD COL(1) LEN(32000)

*====================================================================
* PULL JOBNAME FROM VARIOUS LOCATIONS INTO A COMMON COMPUTE FIELD
* DO SAME FOR START_TIME AND STEPNAME
*====================================================================
COMPUTE:    JOBNAME  =
            WHEN(SMF14RTY = 14) ASSIGN(SMF14JBN)
            WHEN(SMF15RTY = 15) ASSIGN(SMF15JBN)
            WHEN(SMF17RTY = 17) ASSIGN(SMF17JBN)
            WHEN(SMF30RTY = 30) ASSIGN(SMF30JBN)

COMPUTE:    START_TIME =
            WHEN(SMF14RTY = 14) ASSIGN(
                        #FORMAT(SMF14RSD, YYYY-MM-DD)
                + ' ' + #FORMAT(SMF14RST, HH-MM-SS)  )

            WHEN(SMF15RTY = 15) ASSIGN(
                        #FORMAT(SMF15RSD, YYYY-MM-DD)
                + ' ' + #FORMAT(SMF15RST, HH-MM-SS) )

            WHEN(SMF17RTY = 17) ASSIGN(
                        #FORMAT(SMF17RSD, YYYY-MM-DD)
                + ' ' + #FORMAT(SMF17RST, HH-MM-SS) )

            WHEN(SMF30RTY = 30) ASSIGN(
                        #FORMAT(SMF30RSD, YYYY-MM-DD)
                + ' ' + #FORMAT(SMF30RST, HH-MM-SS) )

COMPUTE:    STEPNAME  =
            WHEN(SMF14RTY = 14) ASSIGN(SMF14SPN)
            WHEN(SMF15RTY = 15) ASSIGN(SMF15SPN)
            ELSE                ASSIGN(' ')


*====================================================================
* MAKE A UNIQUE JOBID FLD, USING JOBNAME, READER TIMESTAMP
*====================================================================
COMPUTE:    JOBID   =  JOBNAME + START_TIME

*====================================================================
* INCLUDE ALL 14, 15, 17 AND 30-5 RECORDS
*====================================================================
INCLUDEIF:  (SMF30RTY=30 AND SMF30STP = 5)   /* SMF 30 JOB TERM RECS */
             OR (SMF14RTY=14 OR 15 OR 17)    /* SMF 14,15,17 RECS */

*====================================================================
* OUTPUT IS JUST THE WHOLE RECORD (AS MUCH OF IT AS WE NEED)
*====================================================================
COLUMNS:    RECORD      /* COPY THE WHOLE 14/15/17/30 RECORD */
*
*====================================================================
* SORT SO THAT ALL RECS FOR THE SAME JOB ARE TOGETHER.
* (AND FOR 14 AND 15 RECORDS, THE SAME JOBSTEP.)
* WE WANT THE 30 RECORD TO COME BEFORE ALL MATCHING 14, 15, 17 RECS
* FOR MULTIPLE 14/15 RECS FROM THE SAME JOB, WE ALSO SORT ON STEPNAME
*====================================================================
SORT:       JOBID SMF30RTY(DESC) STEPNAME

*====================================================================
* OPTIONAL 2ND LOG REPORT. USE DURING DEBUG. NEEDS SWOUT002 DD
*====================================================================
NEWOUT:
INCLUDEIF:  (SMF30RTY=30 AND SMF30STP = 5)   /* SMF 30 JOB TERM RECS */
             OR (SMF14RTY=14 OR 15 OR 17)    /* SMF 14,15,17 RECS */

COLUMNS:
 JOBID SMF30RTY(4) STEPNAME

SORT:       JOBID SMF30RTY(DESC) STEPNAME

//*=================================================================
//* READ FILE OF SORTED, 14,15, 17 AND 30 RECORDS. PRINT REPORT
//*=================================================================
//STEP2 EXEC PGM=SPECTSMF,REGION=4M
//STEPLIB  DD DSN=PACSYS01.SPECTSMF.LOADLIB,DISP=SHR               
//SWCOPY   DD DSN=PACSYS01.SPECTSMF.COPYLIB,DISP=SHR COPY LIBRARY  
//SWLIST   DD SYSOUT=* CONTROL LISTING
//SWOUTPUT DD SYSOUT=* REPORT
//SYSOUT   DD SYSOUT=* SORT CONTROL LISTING
//SMFIN    DD DSN=&&TEMPSMF,DISP=(SHR,PASS)
//SYSIN    DD * CONTROL STATEMENTS
OPTION:     NOGRANDTOTALS

*====================================================================
* DEFINE ONE FILE WHICH HAS THE FIELDS FROM ALL 4 COPYBOOKS
*====================================================================
FILE:       SMFIN LRECL(32767) DDNAME(SMFIN) KEEPRDW
COPY:       REC14
COPY:       REC15
COPY:       REC17
COPY:       REC30

INPUT:      SMFIN

*====================================================================
* PULL JOBNAME FROM VARIOUS LOCATIONS INTO A COMMON COMPUTE FIELD
* DO SAME FOR START_TIME AND STEPNAME
*====================================================================
COMPUTE:    JOBNAME  =
            WHEN(SMF14RTY = 14) ASSIGN(SMF14JBN)
            WHEN(SMF15RTY = 15) ASSIGN(SMF15JBN)
            WHEN(SMF17RTY = 17) ASSIGN(SMF17JBN)
            WHEN(SMF30RTY = 30) ASSIGN(SMF30JBN)

COMPUTE:    START_TIME =
            WHEN(SMF14RTY = 14) ASSIGN(
                        #FORMAT(SMF14RSD, YYYY-MM-DD)
                + ' ' + #FORMAT(SMF14RST, HH-MM-SS)  )

            WHEN(SMF15RTY = 15) ASSIGN(
                        #FORMAT(SMF15RSD, YYYY-MM-DD)
                + ' ' + #FORMAT(SMF15RST, HH-MM-SS) )

            WHEN(SMF17RTY = 17) ASSIGN(
                        #FORMAT(SMF17RSD, YYYY-MM-DD)
                + ' ' + #FORMAT(SMF17RST, HH-MM-SS) )

            WHEN(SMF30RTY = 30) ASSIGN(
                        #FORMAT(SMF30RSD, YYYY-MM-DD)
                + ' ' + #FORMAT(SMF30RST, HH-MM-SS) )

COMPUTE:    STEPNAME  =
            WHEN(SMF14RTY = 14) ASSIGN(SMF14SPN)
            WHEN(SMF15RTY = 15) ASSIGN(SMF15SPN)

*====================================================================
* MAKE A UNIQUE JOBID FLD, USING JOBNAME, READER TIMESTAMP
*====================================================================
COMPUTE:    JOBID   =  JOBNAME + START_TIME

*=================================================================
* THESE COMPUTE STMTS SAVE THE USERID FROM SMF 30 RECS AS THEY
* ARE READ. BUT WE DON'T INCLUDE THE 30 REC IN THE REPORT.
*=================================================================
COMPUTE: SAVE_JOBID_30 =
          WHEN(SMF30RTY=30) ASSIGN(JOBID)
          ELSE RETAIN

COMPUTE: SAVE_RACF_GROUP =
          WHEN(SMF30RTY=30) ASSIGN(SMF30GRP)
          ELSE RETAIN

COMPUTE: SAVE_RACF_USERID =
          WHEN(SMF30RTY=30) ASSIGN(SMF30RUD)
          ELSE RETAIN
*
COMPUTE: SAVE_RACF_TERMINAL =
          WHEN(SMF30RTY=30) ASSIGN(SMF30TID)
          ELSE RETAIN
*
*=================================================================
* WE INCLUDE ONLY SMF 14, 15 AND 17 IN THE REPORT. BUT WE WILL
* ALSO HAVE THE SAVED THE RACF INFO ITS MATCHING 30 REC (IF IT
* APPEARED AHEAD OF THIS 14/15/17 RECORD, LIKE IT SHOULD HAVE.)
*=================================================================
INCLUDEIF:  SMF14RTY=14 OR 15 OR 17
*
*=================================================================
* NOW MOVE DATA FROM VARIOUS LOCATIONS IN SMF 14, 15, 17 RECORD TO
* A SINGLE COMPUTE FIELD THAT WE CAN PRINT IN THE FINAL REPORT.
*=================================================================
COMPUTE: DSNAME   = WHEN(SMF14RTY = 14) ASSIGN(SMF14_JFCBDSNM)
                    WHEN(SMF15RTY = 15) ASSIGN(SMF15_JFCBDSNM)
                    WHEN(SMF15RTY = 17) ASSIGN(SMF17DSN)

COMPUTE: PGMNAME  = WHEN(SMF14RTY = 14) ASSIGN(SMF14PGN)
                    WHEN(SMF15RTY = 15) ASSIGN(SMF15PGN)

COMPUTE: ACTION   = WHEN(SMF14RTY = 14) ASSIGN('READ')
                    WHEN(SMF15RTY = 15) ASSIGN('WRITE')
                    WHEN(SMF17RTY = 17) ASSIGN('DELETE')

*=================================================================
* IF WE FOUND AN EARLIER 30 RECORD FOR THIS 14/15/17 RECORD, WE
* USE ITS RACF INFO IN THE REPORT. (IF SAVED 30 INFO IS FOR SOME
* EARLIER, DIFFERENT JOB, WE PRINT BLANKS FOR RACF INFO.)
*=================================================================
COMPUTE: RACF_GROUP    =
             WHEN(JOBID = SAVE_JOBID_30) ASSIGN(SAVE_RACF_GROUP)

COMPUTE: RACF_USERID   =
             WHEN(JOBID = SAVE_JOBID_30) ASSIGN(SAVE_RACF_USERID)

COMPUTE: RACF_TERMINAL =
             WHEN(JOBID = SAVE_JOBID_30) ASSIGN(SAVE_RACF_TERMINAL)

*=================================================================
* NOW WE NAME THE FIELDS FOR OUR FINAL REPORT, WITH COLUMN HDGS
*=================================================================
COLUMNS:
            DSNAME('DATASET NAME')
            ACTION
            RACF_GROUP
            RACF_USERID
            RACF_TERMINAL
            JOBNAME
            START_TIME('READER START TIMESTAMP')
            STEPNAME
            PGMNAME('PROGRAM|NAME')


*====================================================================
* SORT THE REPORT ON DSNAME, WITH 1 BLANK LINE BETWEEN DSNAMES
* WITHIN DSNAME, SORT BY READER DATE/TIME
*====================================================================
SORT: DSNAME(NOTOTALS 1) START_TIME JOBNAME

************************************************************************
* REPORT TITLES                                                        *
*(SLASHES SEPARATE THE LEFT (EMPTY HERE), CENTER AND RIGHT TITLE PARTS)*
************************************************************************
TITLE: 'RUN DATE:' #DATE
       / 'DATASET ACCESS LOG WITH RACF USER INFORMATION'
       / 'PAGE' #PAGENUM

TITLE: 'FROM SMF RECORDS 14, 15, 17 AND 30'

 

Produce This SMF Report:


1RUN DATE: 02/18/13                       DATASET ACCESS LOG WITH RACF USER INFORMATION                                 PAGE    1
                                                FROM SMF RECORDS 14, 15, 17 AND 30
0                                                      RACF     RACF     RACF                                            PROGRAM
                 DATASET NAME                 ACTION  GROUP    USERID  TERMINAL JOBNAME  READER START TIMESTAMP STEPNAME   NAME
+____________________________________________ ______ ________ ________ ________ ________ ______________________ ________ ________

 BLD.CICSVR.SDWWLOAD                          READ   SYS1     LORAIN0  TNJ80005 LORAIN0  2007/11/02 10:16:04.47 DB2PLEX2 IKJEFT01

 CEE.SCEERUN                                  READ                              LLA      2007/11/01 19:03:23.83 LLA      CSVLLCRE
 CEE.SCEERUN                                  READ                              LLA      2007/11/01 19:03:23.83 LLA      CSVLLCRE

 CEE.SCEERUN2                                 READ                              LLA      2007/11/01 19:03:23.83 LLA      CSVLLCRE
 CEE.SCEERUN2                                 READ                              LLA      2007/11/01 19:03:23.83 LLA      CSVLLCRE
 CEE.SCEERUN2                                 READ                              LLA      2007/11/01 19:03:23.83 LLA      CSVLLCRE
 CEE.SCEERUN2                                 READ                              LLA      2007/11/01 19:03:23.83 LLA      CSVLLCRE

 DB2.QMF810.TEST.SDSQLOAD                     READ   SYS1     LORAIN0  TNJ80005 LORAIN0  2007/11/02 10:16:04.47 DB2PLEX2 IKJEFT01

 DB2LOG.DBX1.ARCLG1.D07306.T1218254.A0014476  WRITE                             DBX1MSTR 2007/11/01 19:03:38.45 DBX1MSTR DSNYASCP

 DB2LOG.DBX1.ARCLG1.D07306.T1218254.B0014476  WRITE                             DBX1MSTR 2007/11/01 19:03:38.45 DBX1MSTR DSNYASCP

 DB2LOG.DBX1.ARCLG2.D07306.T1218254.A0014476  WRITE                             DBX1MSTR 2007/11/01 19:03:38.45 DBX1MSTR DSNYASCP

 DB2LOG.DBX1.ARCLG2.D07306.T1218254.B0014476  WRITE                             DBX1MSTR 2007/11/01 19:03:38.45 DBX1MSTR DSNYASCP

 D10.HANDSON.WLMPM.PANELS                     READ   SYS1     LORAIN0  TNJ80005 LORAIN0  2007/11/02 10:16:04.47 DB2PLEX2 IKJEFT01

 IMSSYST.IMS1.OLP0                            WRITE                             IMS1     2007/11/01 19:09:43.61 IMS1     DFSMVRC0
 IMSSYST.IMS1.OLP0                            READ   SYS1     IBMUSER  

 IMSSYST.IMS1.OLP1                            WRITE                             IMS1     2007/11/01 19:09:43.61 IMS1     DFSMVRC0
 IMSSYST.IMS1.OLP1                            READ   SYS1     IBMUSER  

 IMSSYST.IMS1.OLP2                            WRITE                             IMS1     2007/11/01 19:09:43.61 IMS1     DFSMVRC0
 IMSSYST.IMS1.OLP2                            READ   SYS1     IBMUSER  

 IMSSYST.IMS1.OLP4                            WRITE                             IMS1     2007/11/01 19:09:43.61 IMS1     DFSMVRC0
 IMSSYST.IMS1.OLP4                            READ   SYS1     IBMUSER  

 IMSSYST.IMS1.OLP5                            WRITE                             IMS1     2007/11/01 19:09:43.61 IMS1     DFSMVRC0
 IMSSYST.IMS1.OLP5                            READ   SYS1     IBMUSER  

 IMSVST.DSW4.TPNSLOG.G0002V00                 WRITE                             TPNSG4T  2007/11/02 07:44:15.26 G4T      ITPENTER
 IMSVST.DSW4.TPNSLOG.G0002V00                 WRITE                             TPNSG4T  2007/11/02 07:44:15.26 G4T      ITPENTER
 ISP.SISPMENU                                 READ   SYS1     LORAIN0  TNJ80005 LORAIN0  2007/11/02 10:16:04.47 DB2PLEX2 IKJEFT01

 ISP.SISPSENU                                 READ   SYS1     LORAIN0  TNJ80005 LORAIN0  2007/11/02 10:16:04.47 DB2PLEX2 IKJEFT01

 ISP.SISPTENU                                 READ   SYS1     LORAIN0  TNJ80005 LORAIN0  2007/11/02 10:16:04.47 DB2PLEX2 IKJEFT01

 LORAIN0.ISPF.PROFILE                         READ   SYS1     LORAIN0  TNJ80005 LORAIN0  2007/11/02 10:16:04.47 DB2PLEX2 IKJEFT01

 LORAIN0.SPFLOG1.LIST                         WRITE  SYS1     LORAIN0  TNJ80005 LORAIN0  2007/11/02 10:16:04.47 DB2PLEX2 IKJEFT01

 PET.PLEX2.BRODCAST                           WRITE                             MSTJCLP2 2007/11/01 19:00:30.50          IEEMB860
 PET.PLEX2.BRODCAST                           WRITE                             MSTJCLP2 2007/11/01 19:00:30.50          IEEMB860


 USER.LINKLIB                                 READ   SMFGRP   SMFGUY   
 USER.LINKLIB                                 READ   SMFGRP   SMFGUY   

 USER.PROCLIB                                 READ   SMFGRP   SMFGUY   
 USER.PROCLIB                                 READ   SMFGRP   SMFGUY   

 WITADM1.ISPF.PROFILE                         WRITE                             WITADM1  2007/11/02 10:55:36.66 DB2PLEX2 IKJEFT01

 WITADM1.SPFTEMP1.CNTL                        DELETE                            WITADM1  2007/11/02 10:55:36.66
 WITADM1.SPFTEMP1.CNTL                        WRITE                             WITADM1  2007/11/02 10:55:36.66 DB2PLEX2 IKJEFT01
 WITADM1.SPFTEMP1.CNTL                        READ                              WITADM1  2007/11/02 10:55:36.66 DB2PLEX2 IKJEFT01

 WITADM1.SPFTEMP2.CNTL                        READ                              WITADM1  2007/11/02 10:55:36.66 DB2PLEX2 IKJEFT01
 WITADM1.SPFTEMP2.CNTL                        WRITE                             WITADM1  2007/11/02 10:55:36.66 DB2PLEX2 IKJEFT01

See Other Sample SMF Reports
Copyright 2017.
Pacific Systems Group.
All rights reserved.


Spectrum Writer 4GL - the economical alternative to SAS, Easytrieve, DYL-280...

Home | Products | Prices | Documentation | 30-Day Trials | Customer Reviews | Company | FAQ | Sample Reports | SMF Records
Send Your Comments or Questions