How To Make SMF Report
How To Make SMF Report
"One of the greatest SMF parsing programming languages I’ve ever seen."
"The user is extremely happy. I produced some Excel files for her from our
customers’ SMF files to debug a problem and she’s ecstatic she can produce
all kinds of graphs and charts."
"I have an immediate need for a report that will not take me anytime at all
using your tool. Thanks for everything!"
"I’ve been experimenting quite a bit the last couple of days with download-
ing the PC format and loading into Excel and Access. That is very cool. I can
produce snazzy reports very quickly."
"I do like the product because of its ease. An associate asked at the begin-
ning of this week if I had a way to see how many VSAM files and sequential
files we had on our systems. I informed him that with this product I could
quickly generate a report using the SMF type62 records for VSAM cluster
opens and go back however far we keep our SMF records."
"I’m doing more and more ad hoc type reports off of SMF data and SMF
Report Writer is a huge help for me!"
"I really appreciate all of your help, and wish that all of the vendors with
whom I work were half as pleasant and helpful as you have been. It has been
a pleasure."
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
Introduction
This tutorial teaches you how to use Spectrum SMF Writer control statements to request custom reports from your
Introduction
SMF files.
Spectrum SMF Writer's language is non–procedural, which means you describe the result you want, not the
programming steps needed to produce it. And that means you can produce new reports in a matter of minutes,
rather than days or weeks.
You will describe your report with a few simple "control statements". You can create an SMF report with as few
as three control statements. For example:
INPUT: SMF14
INCLUDEIF: SMF14RTY = 14
COLUMNS: SMF14DTE SMF14TME SMF14JBN SMF14PGN SMF14TIOE5 SMF14_JFCBDSNM SMF14_JFCLRECL SMF14EXCP
The three statements above produce a complete report with Spectrum SMF Writer. (See Figure 1 on page 8.)
Note:
This tutorial contains some references to chapters and
pages outside of the tutorial itself. Those references are
to pages in the Spectrum Writer User’s Guide and
Reference Manual (available on our website).
Control
Statements
INPUT: SMF14
INCLUDEIF: SMF14RTY = 14
COLUMNS: SMF14DTE SMF14TME SMF14JBN
File Definition
Statements
FILE: SMF14 LRECL(32767) DDNAME(SMFIN)
FIELD: SMF14LEN DISP(0) LEN(2) TYPE(BU)
FIELD: SMF14SEG DISP(2) LEN(2) TYPE(BU)
FIELD: SMF14FLG DISP(4) LEN(1) TYPE(BU)
FIELD: SMF14RTY DISP(5) LEN(1) TYPE(BU)
SMF File
..............DESA
........6...."DESAOMVS.............O.....
............."DESASTC .............O.....
r i t e r
S M FW
c t ru m
Sp e
Custom
Reports
6 Introduction
Lesson 1. How to Make an SMF Report
in 5 Minutes
This lesson teaches you how to make a simple SMF report in just 5 minutes using only three control statements.
Spectrum SMF Writer Tutorial
The above statement tells Spectrum SMF Writer that you want to produce a report using data from the type 14
SMF records. (Each SMF 14 record contains information about one input data set referenced during the execution
of a job or task.)
1) it copies the statements from member SMF14 in the copy library (which in turn copies another
member named REC14). Those members define the SMF input file and describe all of the fields available
in the SMF 14 record. That lets you refer to any of those fields in the control statements that follow.
2) it also sets this newly defined SMF14 file as the primary (and in this case only) input file for this report.
SMF14 SMF14
SMF14DTE SMF14TME SMF14JBN SMF14PGN SMF14TIOE5 JFCBDSNM JFCLRECL SMF14EXCP
________ ___________ ________ ________ __________ ____________________________________________ ____________ ______________
Remarks:
• this report was produced from just three statements: the INPUT, INCLUDEIF, and COLUMNS statements
• the data used in this report comes from the SMF14 records
• the eight columns of data in the report correspond to the field names in the COLUMNS statement
• the default column headings used are the field names themselves, broken apart at each underscore
• the report has a default title which includes the name of the input file
• the report has a Grand Total line showing totals for the two numeric columns. (Later we will see how to suppress the total
for a particular column when it is meaningless, as it is for the LRECL column here.)
• the number of records listed in the report is shown
But since the SMF file contains dozens of different record types, each containing different kinds of data, it is not
very useful to include all records in a single report. So it is safe to say that most of your reports will use an
INCLUDEIF statement to limit the records used in a given report.
The INCLUDEIF statement tells Spectrum SMF Writer to "include" a record in the report only "if" one or more
conditions are met. In Figure 1 (page 8), we included records in the report if the record type field was equal to 14.
So that report includes every type 14 record from the input file.
Most of your reports will consist of data from only one type of SMF record. And often you will want to limit the
records that appear in your report even further. You do this by specifying more than one condition (or test) in the
INCLUDEIF statement. Consider these statements:
The above statements select just the type 30 with a subtype of 5 for the report. Subtype 5 records are written at job
termination time, so those a good source of job accounting information. We will use the above statements in some
later examples.
The INCLUDEIF statement may appear anywhere after the INPUT statement. Only one INCLUDEIF statement is
allowed per report, but it may contain as many conditions as you like.
By the way, the INCLUDEIF statement may refer to any of the fields defined for the input file (as well as any
COMPUTE field).You are not limited to just those fields that are listed in the COLUMNS statement, for example.
Note: If your INCLUDEIF expression is too big to fit on a single line, end the first line anywhere that a space
is allowed in the expression. Then continue the expression in column 2 or later of the next line (or lines).
Alsays leave column 1 of continuation lines blank.
See Appendix A, "Writing Conditional Expressions" of the User Manual (page 62) for a more complete discussion
of the rules for the conditional expressions allowed on the INCLUDEIF statement.
The COLUMNS statement above tells Spectrum SMF Writer that we want columns in our report that show the date
and time the SMF record was written, the job name, program name, DDNAME, DSNAME, LRECL and count of EXCP’s
for that dataset.
You may specify as many fields as you have room for in the report.
a default title containing the name of the input file, as well as the date, time, day of the week, and page
number
the columns of data that we requested, appearing in the same order as we specified
neat, underlined column headings identifying each column of data
date, time and numeric fields that are properly formatted from the raw SMF data
a Grand Totals line which shows totals for each of the numeric columns
an item count, showing the number of records included in the report
The members beginning with "REC" contain the definitions for the individual fields for a given record. These are
the fields you can choose from for your COLUMNS statement (and other statements that you will be learning about.)
You can browse the copy library PDS to see what is available for you to report on. You can also get a list of all of
the fields available for a file by just adding the SHOWFLDS(YES) parm to your INPUT statement, like this:
The above statement tells Spectrum SMF Writer to print (in the control statement listing) a list of all of the fields
defined for SMF14.
Lastly, our web site is an excellent resource for learning about the SMF fields available for a given record type.
However, Spectrum SMF Writer is restricted (by license agreement and technically) to report exclusively on SMF
input files.
To address your needs, we do offer an unrestricted version of this same program. It is called Spectrum Writer.
Spectrum Writer can report on any file in your shop — and even on DB2 tables (with the available DB2 Option.)
Call us to ask about upgrading your current Spectrum SMF Writer license to a license for our full Spectrum Writer
product. It does everything Spectrum SMF Writer does and more!
Note: we do permit you to use Spectrum SMF Writer to experiment (for non-productive purposes) with
other files to actually see how it would work out for your shop. The software you now have allows you to
report on a very limited number of records from non-SMF files. To try this out, see Chapter 6, "How to
Define Your Input Files" in the full User’s Guide to learn how to easily set up a definition for any file you
have. You can even use your existing COBOL or Assembler record layouts to define a file.
Summary
Here is a summary of what we learned in this lesson:
an INPUT statement is needed to tell Spectrum SMF Writer which SMF record (and which copy library
definitions) to use for the report
an INCLUDEIF statement is used to tell Spectrum SMF Writer which records from the input file to include
in the report
a COLUMNS statement is needed to tell Spectrum SMF Writer what columns of data to print in your report
by using just these three statements you can produce a complete report
The next lesson will teach you how to turn your SMF report into an export file for PC programs.
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
how to specify conditions based on bit fields (page 465). Also see this tutorial’s index for examples of
testing bits.
how to use the STOPWHEN parm on the INPUT statement to limit the records read from the SMF file
during testing (page 542)
how to use the MAXINCLUDE and MAXINPUT options to limit the records read from the SMF file during
testing
the complete syntax for the INPUT, INCLUDEIF and COLUMNS statements, in Chapter 10, "Control
Statement Syntax"
This lesson teaches you how to turn your SMF data into PC export files. It also explains how to produce two or
more different outputs (reports and/or files) during a single pass of the input file. The control statements discussed
are:
the PC parm of the OPTIONS statement
the NEWOUT statement
To create a PC export file instead of a report, just add this OPTION statement near the beginning of your control
statements.
OPTION: PC /* MAKE A PC FILE INSTEAD OF A REPORT */
INPUT: SMF14 /* COPY SMF 14 RECORD DEFINITIONS */
INCLUDEIF: SMF14RTY = 14 /* SELECT JUST TYPE 14 RECORDS */
COLUMNS: SMF14DTE SMF14TME SMF14JBN SMF14PGN SMF14TIOE5 SMF14_JFCBDSNM_SMF14_JFCLRECL SMF14EXCP
Figure 2 shows a portion of the PC file created with the above statements. It also shows the spreadsheet obtained
after importing the PC file into Excel.
Let’s examine what each statement does. The OPTION statement above tells Spectrum SMF Writer that you want
to produce a comma-delimited PC file (instead of a report) in this run. Such PC files can be imported into virtually
any PC spreadsheet, data base or word processing program You can use this option to turn virtually any report into
a PC export file.
The INPUT statement identifies the SMF record that contains the data that you want to put into your PC file.
The INCLUDEIF statement tells which records from the input file to include in your PC export file.
The COLUMNS statement specifies what columns of data you want in the PC spreadsheet. Here you name the
individual fields from the input file that you want to populate the columns of the spreadsheet.
With just these four statements, we've given Spectrum SMF Writer everything it needs to turn your selected SMF
data into a PC file! That's all there is to creating custom PC files with Spectrum SMF Writer. Four simple
statements let you accomplish what would otherwise have taken an entire COBOL program to do!
To produce a second (or third, etc.) output, just add a NEWOUT statement to you request.
NEWOUT:
This statement should go after you have finished describing the first report that you want. Everything after the
NEWOUT statement applies only to the new report (or export file).
NEWOUT:
OPTIONS: PC /* THIS OUTPUT IS A PC FILE, NOT A REPORT */
INCLUDEIF: SMF14RTY = 14 /* SELECT JUST TYPE 14 RECORDS */
COLUMNS: SMF14DTE SMF14TME SMF14JBN SMF14PGN SMF14TIOE5 SMF14_JFCBDSNM_SMF14_JFCLRECL SMF14EXCP
The above control statements would produce the report in Figure 1 (page 8) and the export file in Figure 2
(page 13) in the same run. Spectrum SMF Writer will only make a single pass through the SMF input file.
Notice that we do not specify another INPUT statement after the NEWOUT statement. The same input file is always
used for all of the outputs in a run.
But you are free to change everything else, if you like. In this example, we used the same INCLUDEIF statement for
both outputs. (We selected all type 14 records.) But the INCLUDEIF statements can be completely different, if you
like. (For example, it could select a different type of SMF record.)
Note: When creating additional outputs in a run, your JCL will need a new DD for each additional output.
In this example, you need a new SWOUT002 DD to write the PC export file to. The new DD’s are numbered
sequentially after that (SWOUT003, etc.)
Summary
Here is a summary of what we learned in this lesson:
just add OPTION: PC to turn a report into a PC export file
use a NEWOUT statement to begin describing a different report or PC file (from the same input file)
The next lesson will teach you how to process SMF records that sections which occur more than once in the same
record.
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
how to specify the format to use for dates in the export file (see the FORMAT parm of the OPTION
statement, in Chapter 10, "Control Statement Syntax")
how to specify the quote character to be used in the export file (see the QCHAR parm of the OPTION
statement, in Chapter 10, "Control Statement Syntax")
how to write single-line (legend style) column headings at the beginning of your export file, with the
HGCOLHDG option
read more about using the NEWOUT statement in Chapter 4, "Beyond the Basics."
the complete syntax for the NEWOUT statement, in Chapter 10, "Control Statement Syntax"
This lesson teaches you how to work with SMF’s infamous "triplets." These triplets define sections of the SMF
record that occur more than one time. The control statements and parms discussed are:
the NORMSMF parm of the INPUT statement
the NORMALIZE parm of the INPUT statement
the related NORMWHEN parm of the INPUT statement
As you probably know, SMF records are notorious for the complex way in which they are assembled. Many
commonly used SMF records consist of numerous different sections, each containing an entirely different set of
data. For example, here is a list of just some of the sections found within the SMF 30 record:
Subsystem Section
Identification Section
I/O Activity Section
Completion Section
Processor Section
EXCP Section
Complicating matters further, certain sections may appear in some SMF 30 records but not in others. And, when
a section does appear in a record, it may not be in the same location in all records. And finally, some of these
sections can occur more than one time within a single SMF 30 record. And the number of times that it occurs varies
from record to record.
Did we mention that each occurrence of such a multiple-occurring section can contain nested sections of its own
(which, yes you guessed it, can also occur a variable number of times).
It’s no wonder that SMF records present a real obstacle to most report writer programs. And certainly to
programmers trying to code their own COBOL or assembler programs to parse SMF records.
Happily, this is precisely where Spectrum SMF Writer excels! It has special functionality to handle even the most
complicated SMF records. And it makes this almost transparent to the end user (you).
sMost of the work involved in handling these situations has already been done for you right in the file definitions.
(Feel free to browse the definitions in the copy library to see how we use OFFSET parms and conditional COMPUTE
statements to determine whether a section exists in a given record, and, if so, where it is located.)
That means that no special action is required on your part to report on the data contained in the first (and often
only) occurrence of any section. Just name the fields on your COLUMNS statement just like any other field.
And there are actually many sections that do occur only one time. For example, the Subsystem and Identification
sections in type 30 records always occur exactly once in every SMF 30 record. Also, the I/O Activity, Completion
and Processor sections of SMF 30 records each occurs either once or not at all.
The above statements produce the report shown in Figure 3. That report uses just the SMF 30 records written at
job termination time (the subtype 5 records.) The report has columns for these items taken from various parts of
the SMF 30 record:
log date and time, record type and subtype (all from the standard SMF record header)
job name (from the Identification section, which occurs exactly once)
number of card image records read (from the I/O Activity section, which occurs no more than once)
step completion code (from the Completion Section, which occurs no more than once)
DDNAME, EXCP block count, and largest block size (all taken from the EXCP section, which can occur any
number of times)
The report in Figure 3 shows the contents of those fields taken from the first occurrence of each section (even
though that first section may be located at different offsets in different records.)
Note: if you refer to a field in a section that does not exist in that particular record, the field is treated as
"missing." Missing fields yield blanks or zeros, depending on the data type.
But the report in Figure 3 only shows the DDNAME, EXCP count and maximum blocksize for a single DDNAME for
each job. (Whichever DDNAME the SMF system happened to put in the first occurrence of the EXCP section.)
To report on the DDNAME, the EXCP count and the maximum block size for each DD in the job, you must add an
additional parm to your INPUT statement — the NORMSMF parm:
INPUT: SMF30 NORMSMF(SMF30EOF)
Figure 3. SMF 30 report with data from only the first occurrence of various section
SMF30DTE SMF30TME SMF30RTY SMF30STP SMF30JBN SMF30INP SMF30SCC SMF30DDN SMF30BLK SMF30BSZ
________ ___________ ________ ________ ________ ______________ ________ ________ ______________ ____________
Figure 3. SMF 30 report with data from only the first occurrence of various sections
The NORMSMF parm is almost always used in conjunction with the NORMWHEN parm as explained below (and as
shown in Figure 4 on page 20.) The NORMWHEN parms tells Spectrum SMF Writer when to perform the
normalization described in the following NORMSMF parm(s). (If we had omitted the NORMWHEN parm in Figure 4,
Spectrum SMF Writer would have tried to normalize the EXCP section of every input record, not just the type 30
subtype 5 SMF records. This would lead to errors, since the triplet field that Spectrum SMF Writer uses for the
type 30 record (SMF30EOF) would contain "garbage" for all of the non-type 30 records.)
All of the logical records created from a physical record are identical to that original physical record except for
one thing: each one contains a different value in the SMF30EOF field. Spectrum SMF Writer increments that offset
field’s value in each logical record so that it points to the next occurrence of the EXCP section. Since all of the
fields within the EXCP section are defined relative to the offset contained in the SMF30EOF field, a different set of
EXCP fields is addressed in each logical record.
Let’s examine the processing step by step. The unchanged physical record is first processed once, as-is. That is,
the inclusion tests, if any, are performed on the unchanged physical record. If selected, the data from this record
is used to make a line in the report.
Next, a new logical record is created by just incrementing the value of the triplet’s "offset" field in the original
physical record. As a result, the offset field now contains the offset from the beginning of the record to the second
occurrence of the section. Since all of the fields within the EXCP section are defined relative to the offset contained
in the SMF30EOF field, a different set of EXCP fields is processed in this logical record (the EXCP fields from the
second occurance of ths section.)
This new logical record is then processed as if it were a new record from the physical input file. Inclusion tests are
performed. If selected, the data from the record (now addressing the second occurrence of the section) is used to
make a report line in the report.
Then the offset field is incremented once again to process a new logical record using the third occurrence of the
section. On so on.
This normalization process continues until the number of occurrences specified in the third field of the triplet have
been processed. At that point, the next physical record is read from the input file.
Here is an easy way to visualize normalizations. The net result of processing the NORMSMF parm is just the same
as if each SMF 30 record actually contained only a single EXCP section — but the SMF file contained one SMF
30 record for each DDNAME used in the job. (Incidentally, that is exactly how the similar SMF 14 records actually
are logged by SMF — a separate type 14 record for each DD used in a job.)
Here is an example of using the NORMSMF parm to process all occurrences of the EXCP section of the SMF 30
subtype 5 records.
INPUT: SMF30 /* COPY SMF 30 RECORD DEFS */
NORMWHEN(SMF30RTY=30 AND SMF30STP=5) /* WHEN TO NORMALIZE */
NORMSMF(SMF30EOF) /* OFFSET FIELD IN TRIPLET */
INCLUDEIF: SMF30RTY=30 AND SMF30STP=5 /* JUST INCLUDE TYPE 30 SUBTYPE 5 RECS IN RPT*/
COLUMNS: SMF30DTE SMF30DTE SMF30RTY SMF30STP SMF30JBN /* SHOW THESE FLDS IN REPT */
SMF30INP SMF30SCC(HEX) SMF30DDN SMF30BLK SMF30BSZ
The INPUT statement now has a NORMWHEN and a NORMSMF parm. The other control statements haven’t changed
at all (from the previous report example in Figure 3).
The above control statements produce the report in (Figure 4) That report shows data for all of the EXCP sections
in the type 30 records. (Notice that the data from the other (non-EXCP) sections, which all occur only once in the
physical record, is the same in all of the logical EXCP records created from the physical SMF record.)
Figure 4. SMF 30 report with data from all occurrences of the EXCP section
SMF30DTE SMF30TME SMF30RTY SMF30STP SMF30JBN SMF30INP SMF30SCC SMF30DDN SMF30BLK SMF30BSZ
________ ___________ ________ ________ ________ ______________ ________ ________ ______________ ____________
Figure 4. SMF 30 report with data from all occurrences of the EXCP section
There are non-standard repeating segments in some SMF records. For example, the SMF120 subtype 7 record uses
4-bytes each for the offset, length and number of segments. (See fields SMF120WA1, SMF120WA2, and SMF120WA3.)
Another example: the SMF 70 records define one repeating section by specifying the beginning section number
within a repeating section to start with (rather than an offset from the beginning of the record). It also uses a 4-
byte field to specify how many times the segment occurs. The length of those sections is specified in a non-
contiguous field elsewhere in the record. (See fields SMF70BDS, SMF70BDN and SMF70BCL).
The two non-standard sections described above can be handled with a different parm -- the NORMALIZE parm (as
opposed to NORMSMF). This parm will be discussed in the next section.
A few, very unusual sections must be handled by special built-in exits in Spectrum SMF Writer. One example is
in the SMF 102 record. The sections in that record all have variable length, so there is no triplet that specifies a
fixed segment length to use for them. For the 102 records, Spectrum SMF Writer has a special built-in exit to
normalize these. You will use an IOEXIT parm on the INPUT statement to normalize these sections. (See the example
on page 60 in Appendix B of this document.)
The record definition (in your Spectrum SMF Writer copy library) will always tells you how to normalize a
particular section, whether it is with the standard NORMSMF parm, or a NORMALIZE parm or an IOEXIT parm. Look
in the "RECnnn" member of the copy library, in the comments at the beginning of the section that you want to
normalize.
The NORMALIZE parm has two parameters: the first one is a field in the record that defines the entire first occurrence
of the section you want to process. The second parameter in a NORMALIZE parm is an expression yielding the
number of times the section occurs. (The length of the section is taken from the defined length of the field in the
first parameter.)
Here is an example of an INPUT statement that uses one NORMSMF and one NORMALIZE parm to perform a nested
normalization (described in a later section) on SMF 70 records:
INPUT: SMF70 /NORMALIZE THE LPARS, THEN EACH LPAR'S LOGICAL PROCESSORS*/
NORMWHEN(SMF70RTY=70 AND SMF70STY=1)
NORMSMF(SMF70BCS) /*LPARS - STANDARD TRIPLET */
NORMALIZE(SMF70_PRSMLPD_SECTION, SMF70BDN) /*LOG PROCS* - NON-STANDARD */
Internally, Spectrum SMF Writer handles NORMALIZE parms very differently from NORMSMF parms. If you are
interested in the details, see the main Spectrum Writer User’s Guide and Reference Manual. (Check the index for
“NORMALIZE”).
Since the different sections within a record contain totally different sets of data, in most cases you will just want
to normalize only a single section for any given report. (In the much the same way that we normally include data
from only a single SMF record type in a given report.)
Spectrum SMF Writer, however, does support the normalization of more than one section at a time. And we will
discuss that next.
There is one case where it actually does make sense to normalize multiple sections in the same report. And that is
when one section contains an embedded section. In that case, you may well want to first normalize the outer
section, so your report includes all occurrences of that section. And then for each of those occurrences you would
also want to see all occurrences of the section that is embedded within it.
The SMF 70 record ("RMF Processor Activity") provides just such a situation. So we will use it for an example.
In the fixed portion of the SMF 70 (subtype 1) record there is this standard triplet: SMF80BCS, SMF80BCL, and
SMF80BCN. These fields define an "LPAR Partition Data Section" which occurs once for each configured logical
partition.
Within this LPAR Data Section, there are two additional fields (SMF70BDN and SMF70BDS). These fields, when
used together with an additional triplet (SMF70BVS, SMF70BVS, and SMF70BVS) identify a number of LPAR
Processor Data Sections. These sections contain information about all of the logical processors associated with
that LPAR.
The main idea to pick up here is that if the need arises, you can report on all occurrences of nested recurring
sections. And the part that you do need to understand is very easy: to NORMALIZE nested sections, you simply add
an additional NORMSMF (or NORMALIZE) parm to the INPUT statement:
INPUT: SMF70
NORMWHEN(SMF70RTY=70 AND SMF70STY=1)
NORMSMF(SMF70BCS) /*LPARS - STANDARD TRIPLET */
NORMALIZE(SMF70_PRSMLPD_SECTION, SMF70BDN) /*LOG PROCS* - NON-STANDARD */
Note: we did not need to add an additional NORMWHEN parm. The existing one applies to all NORMSMF and
NORMALIZE parms that follow it.
With this INPUT statement, Spectrum SMF Writer will process each physical SMF 70 (subtype 1) record as a
number of logical records.
You might think of this as processing each element of a two-dimensional array. While the first occurrence of the
outer section is processed, each occurrence of the inner section is normalized to form its own logical record. After
that, the second occurrence of the outer section is processed, and all of the inner sections for it are normalized, and
so on.
Don’t worry if you this seems complex to you. It is complex. And happily, most SMF reports don’t need such
sophisticated logic. But it’s nice to know that Spectrum SMF Writer can handle it when the need does arise. And
all just by adding a line or two to your INPUT statement.
You can see a report example that uses the above INPUT statement in Figure 15 (page 59).
Summary
Here is a summary of what we learned in this lesson:
add a NORMWHEN and a NORMSMF parm to your INPUT statement to process all occurances of standard
triplet
with certain non-standard sections, you will use a NORMWHEN and a NORMLIZE parm instead
you can use multiple NORMSMF/NORMALIZE parms to process nested recurring sections
The next lesson will teach you how to customize the titles in your report.
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
You can learn more about the normalization process in these places:
a fuller explanation of the normalization process is found in Chapter 4, "Beyond the Basics", beginning
on page 237
the complete syntax for the parms related to normalization is found in Chapter 10, "Control Statement
Syntax" (page 542).
This lesson teaches you how to specify your own report titles. The control statement discussed is:
To specify your own report titles, simply use one or more TITLE statements. For each TITLE statement, Spectrum
SMF Writer prints one title line at the top of each page of the report. The title lines print in the same order in which
the TITLE statements occur.
After the word TITLE and the colon, enclosed your desired title text in either single or double quotation marks. For
example:
TITLE: 'SPECTRUM SMF WRITER REPORT - CPU TIMES'
Note: If your title is too big to fit on a single line, type right up to column 72 in the first line and then
continue in column 2 of the next line. Leave column 1 of the continuation line blank.
For example, you will probably want to include the date and page number in your titles. Do this by using the
special built–in fields named #DATE and #PAGENUM. (Don't let the pound sign scare you. All of Spectrum SMF
Writer's built–in field names begin with this character. This is to distinguish them from fields in your own files
that may have similar names.) The contents of the special built-in fields #DATE and #PAGENUM are, of course, the
system date and the current page number:
TITLE: #DATE / 'SPECTRUM SMF WRITER REPORT - CPU TIMES' / 'PAGE' #PAGENUM
When using #DATE and #PAGENUM in your TITLE statement, do not enclose them in quotation marks. Anything
enclosed in quotation marks is printed as is in the title. Anything not within quotation marks must be the name of
a field, whose contents you want in the title.
Built-In
Description
Field
the system date in a true date field (which you can format any
#DATE
way you like. By default it is formatted as MM/DD/YY.)
Built-In
Description
Field
a character field containing the current day of the week (e.g.,
#DAYNAME
"MONDAY ")
the system time formatted as a 8-byte, 12-hour HH:MM AM/PM
#TIME
character field
the system time formatted as a 5-byte, 24-hour HH:MM character
#TIME24
field
the system time in a true time field (which you can format any
#HHMMSS
way you like.)
#JOBNAME the name of the job executing Spectrum SMF Writer
Notice that it contains two slashes (/). These are a powerful formatting device that let you easily align your titles
in the customary way without having to carefully count up the number of columns in your report lines. (And then
having to carefully counting them again each time you make a minor change to the report.)
When slashes are not used, the whole title is centered over the report.
But when slashes are used, they divide the title line into three parts. The first part of the title (#DATE, in the example
above) will be aligned with the left margin of the report. The middle part (the literal text) will be centered over the
report. And the last part ("PAGE" and #PAGENUM) will be aligned with the right margin of the report.
Figure 5 (page 29) shows a report that uses a TITLE statement similar to the one above.
Note: You can also use a single slash in your TITLE statement. That results in a 2-part title, where the first
part is left-justified and the second part is right-justified.
Note: you can also use two slashes but leave one or more of the three title parts "empty". The report in
Figure 15 (page 59) shows an example of doing this.
Summary
Here is a summary of what we learned in this lesson:
use the TITLE statement to specify your own titles for a report
if more than one TITLE statement is used, the title lines print in the same order in which the TITLE
statements appear
use Spectrum SMF Writer's built–in fields to include the date, time, day of the week, and page
number in your titles
put a field name in the TITLE statement to show that field’s current value in the title of each page
use slashes to separate your title into left, center, and right aligned parts
The next lesson will teach you how to customize the formatting of your report.
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
the complete syntax for the TITLE statement, in Chapter 10, "Control Statement Syntax" (page 602).
Now that your report contains the data that you need, it is time to think about its appearance. Just because
Spectrum SMF Writer can produce new reports quickly doesn’t mean that the report has to look "quick and dirty"
at all. This lesson helps you give your report a "professional" look, as if it were made with a custom written report
program.
This lesson teaches you how to specify your own formatting options for a report. It covers:
"display formats" (which determine how dates, times and numbers are formatted)
column headings
column widths
the BIZ (blank if zero) parm
the ACCUM/NOACCUM parms (for totalling or not totalling a column)
Type of Display
Description/Example
Data Format
12/31/10
MM-DD-YY
(this is the default format for dates)
MM-DD-YYYY 12/31/2010
DD-MM-YYYY 31/12/2010
Type of Display
Description/Example
Data Format
1,234,567.98 (leadingzero suppression;
commas for thousands separator; dot before
NUM
decimal digits. This is the default format for
numberic fields.)
1.234.567,98 (European standard -- dots for
DOTSEP thousands separator; comma before decimal
Numeric digits)
01234 or 0123M (no leading zero suppression;
DISPLAY
no commas; sign in zone nibble of last digit)
User specified "picture", similar to COBOL’s
PIC’ZZ9.9’
PIC
DOLLAR $123.45 (with floating dollar sign)
HEX F1F2F3F4 (shows raw data in hex format)
Any
BITS 00010011 (shows each bit in the raw data)
When no display format has been specified by the user (as in most of the earlier examples in this tutorial),
Spectrum SMF Writer uses a default display format. To specify your own format, just put the name of a display
format in parentheses immediately after the field name in your control statement. (Do not leave a space between
the field name and the open parenthesis.) Display formats are allowed in COLUMNS, TITLE and other statements that
produce report output.
For example:
TITLE: ’DAILY SMF ABSTRACT FOR’ #DATE(LONG1)
COLUMNS: SMF30DTE(SHORT3) SMF30TME(HH-MM) EXCP-CHARGE(DOLLAR) SMF30SCC(HEX)
The display formats within parentheses after the field names above specify how the fields will be formatted in the
report.
Figure 5 shows a report that uses display formats.
COLUMNS: SMF30BLK('EXCP|BLOCK|COUNT')
In the above statement, we specified our own column heading for the SMF30BLK field. As you can see in the report
in Figure 5, the SMF30BLK column now has EXCP, BLOCK, and COUNT stacked over it as a 3-line column heading.
Figure 5. Customizing a report by using display formats, column headings, override widths and more
COMPUTE: JOB-ELAPSED-SECONDS =
(#MAKENUM(SMF30DTE) * 86400 + #MAKENUM(SMF30TME))
- (#MAKENUM(SMF30STD) * 86400 + #MAKENUM(SMF30SIT))
Figure 5. Customizing a report by using display formats, column headings, override widths and more
Just specify the number of bytes you want for a particular column in parentheses after the field name. For example:
COLUMNS: SMF14_JFCBDSN(20)
The above statement tells Spectrum SMF Writer to shorten the long 44-byte DSN field to just the first 20 bytes.
The report in Figure 5 (page 29) uses the BIZ parm shown above. The report lines with a zero EXCP count now
have blanks in that column, allowing the non-zero values to stand out.
Note: in the example statement above we also specified override column headings and an override width.
This illustrates the fact that you can specify more than one override for a single field. Their order within the
parentheses is not important. You can separate the overrides with spaces and/or commas.
Note: to avoid having to specify ACCUM and NOACCUM parms in every report you make, consider adding
the appropriate parm to the definitions of commonly used fields in your copy library. Just locate the FIELD
statement you want, and add either an ACCUM or NOACCUM parm to the statement. For example:
You may want to change the default way in which dates and numbers are formatted (rather than specifying it for
every individual field in the report). The FORMAT option lets you do this easily. Put the following statement near
the beginning of your control statements.
This statement makes DD-MM-YY the default format for all dates in the report. And it makes the DOTSEP format the
default for all numeric fields.
You can also change the delimiter that Spectrum SMF Writer uses when it formats dates and time in the report.
For example:
The statement above causes dates to be formatted like this: 31-12-10. And time fields look like this: 12.34.56 . Of
course, you can use the delimiter character of your choice.
OPTION: DDMMYYLIT
This option indicates that all date literals in the control statements will be in DD/MM/YY or DD/MM/YYYY format. It
does not affect how dates are formatted in the report. (The FORMAT option, just discussed, does that.)
Note: the delimiters specified by the DATEDELIM and TIMEDELIM options apply only to formatting data to
display in the report. The delimiters used to write date and time literals (in your control statements) cannot
be changed. Always use slashes for date literals, and colons for time literals, in your control statements.
You can put all of these options on a single OPTION statement, of course. An easy way to specify these options for
all reports is to put them in a new member of your Spectrum SMF Writer copy library (we recommend naming
the member SWOPTION). Then either copy that member in each run with a COPY control statement. Or add a
SWOPTION DD in your execution JCL that points to that member of the copy library. The dataset named in this
DD is copied by default at the beginning of each run.
Summary
Here is a summary of what we learned in this lesson:
use an override display format to change the way data is formatted in a report
use override column headings to change the column headings in a report
specify a column width to change the width of a column in a report
use the BIZ parm to blank out zero values
use the ACCUM or NOACCUM parms to specify which columns to show totals for
each of these overrides should be put in parentheses after the appropriate field name
you can specify multiple overrides for a field, all within the same parentheses
use the FORMAT option to change the default display format for all fields in a report
use a literal text in your PRINT statement to include constant text in all report lines
several options exist to help format reports using international conventions
The next lesson will teach you how to create your own new fields to use in your report.
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
This lesson teaches you how to create your own fields to use in a report. The control statement discussed is:
For example, refer back to the report in Figure 3 (page 18). That report has two numeric columns — the EXCP
block count (SMF30BLK) and the maximum block size (SMF30BSZ). We could compute our own new field called
"maximum EXCP bytes" by multiplying those two fields together:
COMPUTE: MAX-EXCP-BYTES = SMF30BLK * SMF30BSZ
Now that the MAX-EXCP-BYTES field has been created, we can use that field in any way that other fields can be used.
For example, a computed field can be used: as a column in the body of the report; in the report titles; as a sort field;
as a control break field; as part of a conditional expression (in the INCLUDEIF statement); or even as an operand in
a subsequent COMPUTE statement to create another field.
You can perform addition, subtraction, multiplication, and division in the COMPUTE statement. Use the +, –, * and
/ symbols, respectively. You may also use parentheses as needed to indicate the order in which the operations
should be performed.
Note: since dashes are allowed as characters in field names, when performing subtraction, always put a
blank space before and after the minus sign. Otherwise, the minus sign will be treated as part of the field
name. Blanks are optional around the other arithmetic operators.
In addition to these arithmetic operations, there are also a large number of built–in functions that you can use in
your COMPUTE statements. These built–in functions allow you to perform more complex operations on SMF data.
These functions are listed at "Built-In Functions Available for COMPUTE Statements" (page 37).
COMPUTE statements usually come after the INPUT statement, so that you can refer to fields from the input file.
And your COMPUTE statement must appear before any control statement that uses the field being created. Beyond
that, the precise location of a COMPUTE statement is not important. The contents of a COMPUTE field is calculated
once for each new record from the input file.
MAX TOTAL
EXCP CPU CPU
SMF30TME SMF30JBN SMF30BLK SMF30BSZ BYTES SMF30UCS SMF30UCT TIME SECONDS
___________ ________ ________ ________ ______________ _____________ _____________ _____________ _______
For efficiency’s sake, Spectrum SMF Writer performs computations only if or when the value of the field is
actually needed. In that sense, the COMPUTE statement is similar to the FIELD statement. Both statements describe
how to obtain the contents of a given field. (The FIELD statement tells where the raw data is located in the input
record, and what format it is in; the COMPUTE statement tells what formula to use to calculate the value of a field.)
But Spectrum SMF Writer itself decides when and whether it actually needs to go to the effort of obtaining a
field’s value while producing the report.
For example, assume that a COMPUTE field is used in the COLUMNS statement, but is not referred to in the INCLUDEIF
statement. If the INCLUDEIF statement fails for an input record, Spectrum SMF Writer will not need to calculate the
COMPUTE field’s value at all for that record. It only needs to compute the value if the record passes the INCLUDEIF
statement’s conditions (so that the data can be shown in the output line).
For this reason, it is fine to store commonly used COMPUTE statements right in the copy library along with a file
definition. They will not add any (significant) overhead to report runs that do not actually use them.
For example, the SMF 30 record has two CPU time fields named SMF30UCT (total TCB time) and SMF30UCS (total
SRB time). We can use a COMPUTE statement to create a new CPU time field containing the combined SRB and
TCB time. We just add the two time fields together, like this:
COMPUTE: TOTAL–CPU-TIME = SMF30UCT + SMF30UCS
The TOTAL-CPU-TIME field created in this statement is a time field. So by default it is formatted in the report as
HH:MM:SS.DD. If you find that you are dealing with very small time intervals, (like the 00:00:00.24 in Figure 6),
you may prefer to view the data as a numeric number of seconds. Use the #MAKENUM built-in function to change
the value from a time field to a numeric field.
COMPUTE: CPU-SECONDS = #MAKENUM(TOTAL-CPU-TIME)
When times are converted to numeric values, the result is the total number of seconds contained in the time field.
The report in now shows this computed field as a numeric value (0.24).
So it might seem tempting to just compute the elapsed time like this
COMPUTE: JOB-ELAPSED-TIME = SMF30TME - SMF30SIT
However, this simple method has an obvious drawback. It won’t work if the job runs past midnight and ends on
the next day. (The time difference will be negative). The correct way to compute this elapsed time is to also take
into account the dates when the job began and ended. The job initiation date is in SMF30STD. And the SMF log
date is in SMF30DTE. Now armed with these four fields, Spectrum SMF Writer’s powerful built-in functions make
the calculation easy:
COMPUTE: JOB-ELAPSED-SECONDS =
(#MAKENUM(SMF30DTE) * 86400 + #MAKENUM(SMF30TME))
- (#MAKENUM(SMF30STD) * 86400 + #MAKENUM(SMF30SIT))
The statement above creates a field that contains the number of elapsed seconds that a job ran. (It does this by
converting both the start date/time and the end date/time into their total number of seconds since the beginning of
the nineteenth century, and then subtracting the starting value from the ending value.) Figure 7 in the next lesson
(page 41) shows a report that uses this COMPUTE statement.
If you prefer to see the elapsed time in regular HH:MM:SS time format, you can convert this numeric seconds field
to a time field, like this:
COMPUTE: JOB-ELAPSED-TIME = #MAKETIME(JOB-ELAPSED-SECONDS)
The above statement creates a single new field that has a unique value for every job in the SMF file. It concatenates
the jobname with the date and time that the job hit the internal reader. This combination forms a unique identifier
for the job, And this is very useful when you want to sort and break on all of the records for a single job — perhaps
printing a total line for the job. In fact, there is an example of using this field in just that way in Figure 10
(page 48).
In the statement above, we used the #FORMAT built-in field in two places. This is necessary because you can only
concatenate character fields. The #FORMAT function formats the date value in SMF14RSD into a MM/DD/YY character
field. Similarly, we formatted the SMF30RST time field into a HH:MM:SS.DD character field.
We also inserted blanks between these SMF fields to make the result more readable, in case we want to print it in
the report.
Here is one more example of using built-in fields to easily extract data that would take quite a few steps in a
procedural language. We use the #REPLACE and #PARSE functions to extract just the first node of the DSNAME field
from the SMF 14 record.
COMPUTE: FIRST-NODE = #PARSE(#REPLACE(SMF14_JFCBDSNM, ’.’, ’ ’), 1)
Here is a complete list of the built-in functions that are available to use in your COMPUTE statements. These
functions allow you to perform complex logic with minimal coding. To learn the specifics of using a particular
function, see the page number mentioned below in our Spectrum Writer User’s Guide and Reference Manual. That
manual was included with your Spectrum SMF Writer download. And you can download it from our website.
#AND returns the result of ANDing two character strings page 630
#ASCII returns the ASCII equivalent of an EBCDIC string page 631
#COMPRESS concatenates multiple fields and compresses out extra blanks page 631
#DAY returns the day of the week for a given date page 631
#EBCDIC returns the EBCDIC equivalent of an ASCII string page 631
#FORMAT converts a numeric, date or time value to a character value page 632
#LCASE returns the lower–case value of a character string page 632
#LEFT returns the leftmost n characters of a character string page 632
#MONTH returns the month name pertaining to a given date page 633
#OR returns the result of ORing two character strings page 633
#PARSE returns one individual word parsed out of a character string page 633
#RIGHT returns the rightmost n characters of a character string page 634
#SUBSTR returns a substring from a character string page 634
translates one set of characters within a character string to another set
#TRANSLATE page 634
of characters
#UCASE returns the upper–case value of a character string page 634
#XOR returns the result of XORing two character strings page 635
#YEAR returns the 4–byte year pertaining to a given date page 635
#BEGMONTH returns the first day of the month in which a date occurs page 638
#BEGWEEK returns the first day of the week in which a date occurs page 638
#BEGYEAR returns the first day of the year in which a date occurs page 639
#ENDMONTH returns the last day of the month in which a date occurs page 639
#ENDWEEK returns the last day of the week in which a date occurs page 639
#ENDYEAR returns the last day of the year in which a date occurs page 639
#INCDATE increments a date by a number of days, weeks, months or years page 639
#INCDATETIME increments a date/time by a number of seconds, minutes or hours page 639
#MAKEDATE converts a character or numeric value to a date page 640
#YMD
#MDY creates a date from three numeric parms page 640
#DMY
#INCDURATION increments a time duration by a number of seconds, minutes or hours page 640
#INCTIME increments a time of day by a number of seconds, minutes or hours page 641
#MAKETIME converts a character or numeric value to a time page 641
#ERROR returns "true" if the argument field is "in error" page 642
#ISNUM returns "true" if the character argument is numeric page 642
#LEAPYEAR returns "true" if the date argument occurs in a leap year page 642
#MISSING returns "true" if the argument field is "missing" page 642
#OFF returns "false" page 642
#ON returns "true" page 643
#REALDATE returns "true" if the date argument is a valid, calendar date page 643
Summary
Here is a summary of what we learned in this lesson:
the COMPUTE statement is used to create new fields
a simple COMPUTE statement assigns the result of a single computational expression to a new field
The next lesson will introduce a more complex form of the COMPUTE statement.
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
This lesson teaches you how to perform complex logic by using COMPUTE statements with conditional parms. We
will even show how conditional COMPUTE statements help you report on data from different types of SMF records
in a single report.
Tip: remember this construction well. It will come in handy for many different applications. Sometimes
we are asked why Spectrum SMF Writer has no "IF" statement and how to get around that. And often, the
answer to the question is to use this if-type logic within a COMPUTE statement.
When Spectrum SMF Writer needs to compute the value of such a field, it begins by evaluating the conditional
expressions within the WHEN parms. The WHEN parms are processed in order, one by one. As soon as a WHEN
parm is found that is true, Spectrum SMF Writer assigns the value from the corresponding ASSIGN expression to
the compute field. At that point, no further WHEN parms are examined.
If none of the WHEN expressions are true, then the value from the ELSE ASSIGN parm, if present, is assigned to
the result. If no ELSE ASSIGN parm was specified, then a value of blanks or zeros will be assigned to the compute
field (depending on the data type.)
Now let’s look at some examples of how conditional COMPUTE statements can help with report logic.
COMPUTE: COMP-CODE =
WHEN(SMF30SCC = 0) ASSIGN(' ')
WHEN(ABEND-BIT = '0') ASSIGN(#FORMAT(SMF30SCC,P'ZZZZ9'))
WHEN(CC-NIB1 = '0') ASSIGN('S' + #SUBSTR(CC-HEX,2,3))
WHEN(CC-NIB1 = '8') ASSIGN('U' + #FORMAT(CC-DROP-8,P'ZZZ9'))
COMPUTE: JOB-ELAPSED-SECONDS =
(#MAKENUM(SMF30DTE) * 86400 + #MAKENUM(SMF30TME))
- (#MAKENUM(SMF30STD) * 86400 + #MAKENUM(SMF30SIT))
TITLE: 'SMF 30 JOB TERMINATIONS, WITH ELAPSED TIME AND COMPLETION CODE'
COMPUTE: COMP-CODE =
WHEN(SMF30SCC = 0) ASSIGN(' ')
WHEN(ABEND-BIT = '0') ASSIGN(#FORMAT(SMF30SCC,P'ZZZZ9'))
WHEN(CC-NIB1 = '0') ASSIGN('S' + #SUBSTR(CC-HEX,2,3))
WHEN(CC-NIB1 = '8') ASSIGN('U' + #FORMAT(CC-MINUS-8,P'ZZZ9'))
The above code first extracts just the abend bit out of the 2-byte SMF30STI field. Two other COMPUTE statements
extract just the first nibble from the SMF30SCC field. Another calculates the binary value of the SMF30SCC field,
after ignoring the X’8’ user abend indicator (which is in the sign bit.)
The conditional COMPUTE statement for COMP-CODE formats our final result. When SMF30SCC is 0, we just set
COMP-CODE to blanks. Otherwise, if the abend bit is off we set COMP-CODE to a normal completion code value.
Otherwise, if the first nibble of SMF30SCC is 0, we format the remaining three hex digits with an S prefix, as a
system abend code. Otherwise, if the first nibble is ’8’ we format the rest of the SMF30SCC field as a binary user
abend value with a U prefix.
Let’s say that we want a report that shows all changes made to any dataset with "SPFTEMP" in its name. We want
to include all jobs that wrote to the dataset, as well as any jobs that may have deleted it. To do that, we need to
combine the information from SMF 15 records (logged when a DD is opened for output) and SMF 17 records
(logged when a dataset is deleted.)
Since we will be working with fields from two different SMF types, we will need the field definitions for both of
them. The following statements handle that for us:
INPUT: SMF15 /* GET TYPE 15 FILE AND FIELD DEFINITIONS */
COPY: REC17 /* GET TYPE 17 FIELD DEFINITIONS ONLY */
The INPUT statement above does two things. It reads in the file and field definitions for the type 15 records from
the copy library. And it names that file as the input for the report. Since we cannot have multiple INPUT statements
in a run, we use a COPY statement to copy in the additional field definitions for the type 17 records. We copied
member REC 17 rather than SMF17 because we want to add all of the type 17 SMF fields to the existing SMF 15
file definition. (Copying SMF17 would have defined a new, second file containing the SMF 17 fields. That is not
what we want.)
***************************************************************
* MOVE DATA FROM DIFFERENT LOCATIONS TO A SINGLE FIELD *
***************************************************************
COMPUTE: DSN = WHEN(SMF15RTY=15) ASSIGN(SMF15_JFCBDSNM)
ELSE ASSIGN(SMF17DSN)
COMPUTE: MGMT = WHEN(SMF15RTY=15) ASSIGN(SMF15MCN)
ELSE ASSIGN(' ')
COMPUTE: DISP = WHEN(SMF15RTY=15) ASSIGN(SMF15_DISP)
ELSE ASSIGN('DELETE')
SMF MANAGEMENT
LOG DATE LOG TIME TYPE DATASET NAME CLASS DISP
________ ___________ ____ ______________________________ __________ ______
Our INCLUDEIF statement should now include both type 15 and type 17 records in the report. Since the SMF record
type field is located in the same position for all SMF records (in the fixed SMF header), it is safe for us to test the
SMF15RTY field in all records.
We also want to restrict the records in our report to just those which contain the text "SPFTEMP" somewhere within
the dataset name. However, the dataset name in SMF15 records is not in the same place as it is in SMF17 records.
So we can not make this test directly on any one field in the input record. This is where a conditional COMPUTE
statement is useful.
COMPUTE: DSN = WHEN(SMF15RTY=15) ASSIGN(SMF15_JFCBDSNM)
ELSE ASSIGN(SMF17DSN)
The COMPUTE statement assigns SMF15_JFCBDSNM to DSN when the input record is type 15. Otherwise, it
assigns SMF17DSN, from a different part of the record, to DSN.
Now we have a single field where we can look for the text "SPFTEMP". So our final INCLUDEIF statement will be
this:
Now that the input and inclusion criteria have been specified, we just need to specify what columns to put in the
report. Once again, for some items we must make COMPUTE fields to use in the COLUMNS statement (rather than
a field name which may or may not be valid for a given record.) Other fields (such as SMF15DTE and SMF15TME)
are located in the standard SMF header and can be used with any type of SMF record.
The report in Figure 8 (page 43) now has one line for each type 15 or 17 record that refers to a "SPFTEMP" dataset.
Each report line shows relevant data taken from either SMF 15 fields or from SMF 17 fields.
Summary
Here is a summary of what we learned in this lesson:
a conditional COMPUTE statement uses one of multiple different computational expressions, depending
on the conditions that you specify
you can use a conditional COMPUTE statement to construct report lines using data from 2 different
types of SMF records
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
the complete syntax for the COMPUTE statement, in Chapter 10, "Control Statement Syntax" (page 506).
This lesson teaches you how to sort your report into the order you want. It also explains how to add control breaks
to your report. And it shows how to use control breaks to create summary reports. The control statements discussed
are:
To print a report in a different order, just add a SORT statement. The SORT statement can appear anywhere after
the INPUT statement. Only one SORT statement is allowed per report, but it may contain as many "sort fields" as
you like. Spectrum SMF Writer will sort your report on all of the sort fields.
For example, let's request a report from the SMF14 records and sort it on two fields:
SORT: SMF14_JOBID SMF14EXCP(D)
Now the report will be sorted first on SMF14-JOBID. That is a computed field that was discussed on page 36. It has
a unique value for each job in the SMF file. When the file has multiple SMF14 records for the same job, then those
records will be sorted in descending SMF14EXCP order.
Note: you can actually use the SMF14_JOBID in your own reports without even having to write a COMPUTE
statement for it. This field is so useful that we have included the COMPUTE statement for it right in the copy
library.
The SORT statement can name any field in the input file (as well as any COMPUTE field). You are not limited to
just the fields that are listed in the COLUMNS statement.
You may also put a trailing #EQUAL parm after all of the sort fields. That parm causes "tie" records to remain in
their original relative order.
EXCP
SMF SMF COUNT
LOG LOG PROGRAM FOR
JOBNAME AND READER TIMESTAMP DATE TIME NAME DDNAME DSNAME LRECL DDNAME
_____________________________ ________ ___________ ________ ________ _________________________ _______ _________
By default, Spectrum SMF Writer sorts reports into ascending order on each sort field. If you want to sort the
report into descending order for a field, put the DESCENDING parm (or just DESC or D) in parentheses immediately
after the field name.
Often it is desirable to perform special processing whenever one such group of records ends and another group is
about to begin. For example, you might want to print a line of totals for the group (the job, in this case) that just
ended. Or, you might want to print a few blank lines before the next group starts printing, or even skip to a new
page. This processing is called control break processing.
A control break occurs whenever one group of records ends and another group is about to begin. The field that
is being grouped (for example, SMF14-JOBID) is called the control break field. A control break field must also be
a sort field, since it is by being sorted that records are grouped together in the first place.
You may designate any sort field as a control break field. Just name the field in a BREAK statement:
SORT: SMF14-JOBID SMF14EXCP(D)
BREAK: SMF14-JOBID
The above statements make SMF14-JOBID a control break field (as well as a sort field). Now we will get job totals
in the report whenever the lines for one job ends and another job is about to begin.
After the totals, two blank lines will print. Then the report lines for the next job start to print, and so on.
Figure 10 shows a report that uses the above BREAK statement to produce a control break. Notice that at the breaks
(by default) Spectrum SMF Writer prints: the value of the break field, the number of item in the control group,
and totals for each numeric column. It also indicates the level of the break with a number of leading asterisks.
For example, the following statement makes SMF14-JOBID a break field and specifies that 3 blank lines should print
at the control break:
BREAK: SFM14-JOBID SPACE(3)
If you want to skip to a new page whenever the contents of a field changes, use the PAGE spacing parm, like this:
BREAK: SMF14SID SPACE(PAGE)
The SPACE(PAGE) parm specifies that, rather than printing 2 blank lines whenever the SMF14SID field (the System
Identification) changes, the report should skip to a new page.
EXCP
SMF SMF COUNT
LOG LOG PROGRAM FOR
JOBNAME AND READER TIMESTAMP DATE TIME NAME DDNAME DSNAME LRECL DDNAME
_____________________________ ________ ___________ ________ ________ _________________________ _______ _________
Note: you can also specify the NOTOTALS parm on the BREAK statement, if you only want blank lines or a
new page at the break, and do not also want totals:
BREAK: SMF14SID NOTOTALS
Control breaks are used to create the desired total lines. Consider again the report in Figure 10 (page 48). It is a
detail report that lists the EXCP count for every DDNAME accessed by a job in the SMF file. The control break on
SMF14-JOBID causes a total line to print after the detail lines for each job. By just adding the following statement,
we can suppress the detail lines and print only those job totals:
OPTIONS: SUMMARY
Figure 11 shows a summary report that uses the above statement. This report just shows the total EXCP count for
each job.
Note: if we intended to use this report as something more than a one-shot job, we would make some
changes to improve its appearance. We could remove some or all of the character columns, since those
fields are empty in the total lines.
But for this example, we wanted to clearly demonstrate that any report that has a control break can easily
be turned into a summary report — just by adding one option to it.
EXCP
SMF SMF COUNT
LOG LOG PROGRAM FOR
JOBNAME AND READER TIMESTAMP DATE TIME NAME DDNAME DSNAME LRECL DDNAME
_____________________________ ________ ___________ ________ ________ _________________________ _______ _________
In this example, we have, in effect, split the SMF14_JOBID field into two components: the jobname alone
(SMF14JBN), and the reader start date/time in a separate field (SMF14-TIMESTAMP). By sorting on both of these
fields (plus SMF30EXCP as the tie breaker), our report remains in the same order as in the previous example.
But now we can break separately on two occasions. First we can break, as before, when each individual job ends
and show its EXCP total. The break on SMF14_TIMESTAMP does that for us. That break’s total line is followed by
1 blank line.
And now we can have an additional break each time the jobname alone changes. The totals at that break will
include all runs of a job with that name in the SMF file. The jobname break is followed by 3 blank lines.
Notice that the number of asterisks in the default total lines serves as a visual indicator of the level of the break.
When multiple BREAK statements are used, the BREAK statements may appear in any order. Note that the order of
the BREAK statements does not determine which break is nested within the other. That is determined by the order
of the fields in the SORT statement.
COLUMNS: SMF14JBN('JOBNAME')
SMF14_TIMESTAMP('READER TIMESTAMP')
SMF14DTE('SMF|LOG|DATE') SMF14TME('SMF|LOG|TIME')
SMF14PGN('PROGRAM|NAME') SMF14TIOE5('DDNAME')
SMF14_JFCBDSNM('DSNAME' 25)
SMF14_JFCLRECL('LRECL' 7 BIZ NOACCUM)
SMF14EXCP('EXCP|COUNT|FOR|DDNAME' 9)
EXCP
SMF SMF COUNT
LOG LOG PROGRAM FOR
JOBNAME READER TIMESTAMP DATE TIME NAME DDNAME DSNAME LRECL DDNAME
________ ____________________ ________ ___________ ________ ________ _________________________ _______ _________
Summary
Here is a summary of what we learned in this lesson:
use the SORT statement to sort your report
you can sort on multiple sort fields
you can sort in either ascending or descending order
The next lesson will show you how to print statistics at control breaks, and how to write your own custom lines at
the beginning and end of a control group.
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
use additional control break spacing parms, including one that skips to a new sheet of paper (page 178)
compute percentages and ratios that apply to an entire control group (page 202)
create multiple levels of summarization (page 204)
the complete syntax for the SORT and BREAK statements is given in Chapter 10, "Control Statement
Syntax" (page 595) and (page 481)
This lesson introduces additional parms available to customize your control breaks. The control statement
discussed is:
the AVERAGE, MAXIMUM and MINIMUM statistical parms of the BREAK statement
the HEADING and FOOTING parms of the BREAK statement
Parm Description
AVERAGE (AVG) Average value (mean)
NZAVERAGE (NZAVG) Average of only the non-zero values
MAXIMUM (MAX) Maximum value
MINIMUM (MIN) Minimum value
NZMINIMUM (NZMIN) Non-zero minimum value
You can specify as many of these parms as you like in the BREAK statement. The parms may be specified in any
order. (The statistic lines in the report, however, always print in a standard fixed order.) For example:
BREAK: SMF14-JOBID AVERAGE MAXIMUM
The BREAK statement above requests that an average line and a maximum line print (in addition to the totals line)
whenever the contents of the SMF14-JOBID field changes.
You can specify any number of these parms. Each parm results in one line that will be printed at the beginning or
end of the control group. Within these parms, specify a "print expression." Print expressions are combinations of
literal text and field names, of the sort that we have used earlier in the COLUMNS statement and the TITLE statement.
Figure 13. Printing statistics and custom headings and footings at control breaks
---- EXCP COUNTS FOR JOB AUABB109 11/02/09 12:21:09.33 FOLLOW ----
11/02/09 12:21:18.82 UASUARC0 UASOMP00 IMSSYST.IMS1.OMP0 24,572 9,001 221,208,576
11/02/09 12:21:19.08 UASUARC0 STEPLIB IMS910T.TAP0.SUASRESL 73 2,391,480
EXCP COUNT AVERAGE: 4,537 MAX: 9,001
*** TOTAL FOR AUABB109 11/02/09 12:21:09.33 ( 2 ITEMS) 9,074 223,600,056
*** AVERAGE VALUE 4,537 111,800,028
*** MAXIMUM VALUE 9,001 221,208,576
---- EXCP COUNTS FOR JOB DCRC91T 11/01/09 19:09:46.82 FOLLOW ----
11/02/09 12:21:09.39 UASMVRC0 JCLPDS D10.TAPDSW4.PROCLIBT 80 324 1,036,800
EXCP COUNT AVERAGE: 324 MAX: 324
*** TOTAL FOR DCRC91T 11/01/09 19:09:46.82 ( 1 ITEM ) 324 1,036,800
*** AVERAGE VALUE 324 1,036,800
*** MAXIMUM VALUE 324 1,036,800
---- EXCP COUNTS FOR JOB DUMPSMF 11/02/09 12:20:14.79 FOLLOW ----
11/02/09 12:20:52.07 SMFGDG LOG D10.SMF.GDG.LIST 80 59 1,647,280
11/02/09 12:20:52.22 SMFGDG STEPLIB USER.LINKLIB 2 65,520
11/02/09 12:20:15.43 IFASMFDP SYSIN USER.PROCLIB 80 2 12,800
EXCP COUNT AVERAGE: 21 MAX: 59
*** TOTAL FOR DUMPSMF 11/02/09 12:20:14.79 ( 3 ITEMS) 63 1,725,600
*** AVERAGE VALUE 21 575,200
*** MAXIMUM VALUE 59 1,647,280
Figure 13. Printing statistics and custom headings and footings at control breaks
Spectrum SMF Writer Tutorial 55
Lesson 9. Customizing the Control Breaks
One powerful feature of the FOOTING parm is that you can print a statistical value (total, average, maximum, etc.)
of a field, rather than just the value of that field from the last record in the control group. You can do that by
specifying one of the statistical parms in parentheses after the field name:
BREAK: SMF14-JOBID FOOTING(’MAXIMUM EXCP COUNT WAS’ SMF14EXCP(MAX))
The report in Figure 13 (page 55) shows examples of some of these additional features. Notice that by moving
the long SMF14-JOBID field out of the COLUMNS statement and into a break heading line, we opened up much more
room for data in the actual report lines. That is one good way to use break headings.
For a much more detailed discussion of customizing control breaks with these features, see Chapter 4, "Beyond
the Basics."
This sample report uses just the type 70 subtype 1 SMF records (RMF Processor Activity). These records have a
complex layout. Each record contains a variable number of "LPAR sections," one for each logical partition in the
system. Furthermore, there are a variable number of "logical processor sections" for each of those LPAR sections.
However, all of these logical processor sections are grouped together near the end of the SMF record — not
physically within each owning LPAR section.
Nevertheless, Spectrum SMF Writer easily handles these records so you quickly create powerful reports from your
RMF data. We use nested NORMALIZE parms on the INPUT statement to process each logical processor that exists
for each logical partition. (The NORMALIZE parm was discussed earlier in Lesson 3, "Working with SMF Triplets"
(page 16).)
The report is sorted by LPAR name and then by logical processor address.
The report is formatted to reflect the hierarchical layout of the SMF 70 records. We used the page titles to show
information about the physical CPU, since it is applies to all of the LPARs.
Then, for each of the LPARs, we print a header section containing ID information, as well as capacity and MSU
values.
Following that are the report lines for each of the logical processors for that LPAR. On each processor line we
show the percentage of the RMF reporting interval for which that processor was: 1) online, 2) waiting, 3)
effectively dispatched and 4) processor dispatched. Note that the percentage fields used are not actually in the
RMF record itself. They are computed fields. However, they are included in the copy library along with the actual
RMF record definitions. That means that you can use the percent fields just like any other RMF field.
Figure 14. This report features nested normalization and customized break headings
INPUT: SMF70
NORMWHEN(SMF70RTY=70 AND SMF70STY=1 AND SMF70BCN > 0)
NORMSMF(SMF70BCS) /* OUTER-LEVEL*/
NORMALIZE(SMF70_PRSMLPD_SECTION, SMF70BDN) /* NESTED LVL */
BREAK: SORT_PARTITION
HEADING('PARTITION INFO')
HEADING('==============')
HEADING('SYSTEM:' SMF70SNM 'SYSTEM NAME:' SMF70STN)
HEADING('PARTITION NUM:' SMF70LPN(2) 'PARTITION NAME:' SMF70LPM)
HEADING('LPAR CLUSTER:' SMF70SPN)
HEADING('LPAR DEFINED CAPACITY LIMIT:' 0 SMF70MSU(6) 'MSU''S' )
HEADING('STORAGE:' SMF70CSF(7) 'MB' )
HEADING(' ')
HEADING('LOGICAL PROCESSOR INFO (' 0 SMF70BDN(4) 'PROCESSORS)')
HEADING('========================================')
COLUMNS:
SMF70VPA('LOG|PROC|ADDR' HEX)
SMF70BPS('WEIGHT|FACTOR' 6)
SMF70INT_TIME('ACTUAL|RMF|INTERVAL')
2 '|'
SMF70ONT('ONLINE|TIME')
SMF70ONT_PCT('PCT|ONLINE')
2 '|'
SMF70WST('WAIT|TIME')
SMF70WST_PCT('PCT|WAIT')
2 '|'
SMF70EDT('EFFECT.|DISPATCH|TIME')
SMF70EDT_PCT('PCT|EFF|DISP')
2 '|'
SMF70PDT('PROC|DISP|TIME')
SMF70PDT_PCT('PCT|PROC|DISP')
Figure 14. This report features nested normalization and customized break headings
Spectrum SMF Writer Tutorial 57
Summary
Here is a summary of what we learned in this lesson:
use one or more statistical parms to request that statistical lines print at a control break
use HEADING and FOOTING parms in your BREAK statement to completely customize the lines printed
around your control groups
the custom lines that you print at control breaks can contain a statistical value of a field (such as total,
average, maximum, etc.)
To Learn More
The chapters and page numbers below refer to pages in the Spectrum Writer User’s Guide and Reference Manual.
58
Figure 15. This report features nested normalization of SMF sections and customized break headings
PARTITION INFO
==============
SYSTEM: Z3 SYSTEM NAME: JF0
PARTITION NUM: 1 PARTITION NAME: JF0
LPAR CLUSTER: UTCPLXJ8
LPAR DEFINED CAPACITY LIMIT: 0 MSU'S
STORAGE: 15,360 MB
PHYSICAL CPU S/N: 04299E LPARS ONLINE TIME PERCENTAGE REPORT RUN DATE: 03/02/10
FAMILY & MODEL: 2094 742 BY LOGICAL PROCESSOR PAGE 2
CAPACITY: 387 MSU'S 15:00 MINUTE INTERVAL ENDING 11/02/07 AT 12:00
PARTITION INFO
==============
SYSTEM: Z3 SYSTEM NAME: J80
PARTITION NUM: 2 PARTITION NAME: J80
LPAR CLUSTER: UTCPLXJ8
LPAR DEFINED CAPACITY LIMIT: 0 MSU'S
STORAGE: 112,640 MB
Figure 15. This report features nested normalization of SMF sections and customized break headings
Spectrum SMF Writer Tutorial 59
Lesson 10. The DB2 Option
Spectrum SMF Writer has an available DB2 Option. This option allows you to perform "reads" to DB2 tables to
get additional information to include in your SMF reports. This feature is very useful when you are reporting on
the DB2-related SMF records (SMF records 100, 101 and 102). The DB2 Option allows you to look up the names
of the actual DB2 objects (tables, views, etc.) that the SMF record is reporting on. You can then include those user-
friendly table names in your report. Without the DB2 Option, the report can only show the halfword DB2 "Object
ID Number" (which is what the SMF record contains) and is not very meaningful.
Sample Audit Report from SMF 102 Records - Who Accessed a DB2 Resource
This sample report illustrates how the DB2 Option works. The primary input file is (as always) the SMF file. We
select just the type 102 "DB2 Audit" records with IFCID 144 ("ATTEMPTED ACCESS (READ) OF AN
AUDITED OBJECT"). We normalize the 144 data section, in order to report on all occurances of that segment
within each SMF record. The normalization is performed by a built-in I/O exit.
We select only the records for the timeframe and the tables that we are interested in. (We might also have selected
a particular Operator ID, to see all tables accessed by a given user.)
The SMF record itself does not contain the text name of the tables being accessed. It just contains halfword codes
for: Database ID, Page Space ID and Object ID. We used two READ statements to "read" rows from two DB2
system tables and expand those codes into full names. Thus we were able to show the actual table names in our
report (see next page.)
60
Lesson 10. The DB2 Option
102 144 04/11/10 18:37:40.13 TSO ADB TTP011A 291 FLOATACC1 2 3 FLOATAAC1
102 144 04/11/10 18:37:54.06 TSO ADB TTP011A 291 FLOATACC1 2 3 FLOATAAC1
102 144 04/11/10 18:38:09.56 TSO ADB TTP011A 291 FLOATACC1 2 3 FLOATAAC1
102 144 04/11/10 18:38:19.11 TSO ADB TTP011A 292 FLOATTEMP 2 3 FLOATTEMP
102 144 04/11/10 18:38:31.80 TSO ADB TTP011A 292 FLOATTEMP 2 3 FLOATTEMP
102 144 04/11/10 18:48:35.58 DB2CALL SPECT303 TTP011A 292 FLOATTEMP 2 3 FLOATTEMP
102 144 04/11/10 18:49:29.27 DB2CALL SPECT303 TTP011A 291 FLOATACC1 2 3 FLOATAAC1
The complete rules for conditional expressions are discussed in "Conditional Expressions" (page 459) in the full
Reference Manual. It is generally the same as for such languages as BASIC, COBOL, etc. Below is a summary of
the main syntax points:
Your expression can contain any number of conditions, separated with the words AND and OR, optionally preceded
by NOT, nested as needed within parentheses. You can also use the symbols &, | and ¬.
Note: The colon comparison operator (:) is a special feature of Spectrum SMF Writer. It allows you to scan
a field to see if a given text appears anywhere within it. This is a very handy feature for writing condition
expressions with Spectrum SMF Writer. For example:
The above statement will include any record whose jobname is ’ACCT1000’ or where the dataset name
contains the characters ’PROD.ACCT’ somewhere within it.
Character Literals
Character literals must appear within single or double quote marks. To embed the same quote character within the
literal, double it. The following are all valid examples of a character literal:
• ’JONES’
• "JONES"
• ’JONE’’S’
• "JONE’S"
Character literals can also be specified in hexadecimal format by prefixing the literal with an X, like this: X’FFFF’
Numeric Literals
Numeric literals should not be contained within quotes. No punctuation is allowed other than a minus sign and a
decimal point.
Date Literals
Date literals should be in either MM/DD/YY or MM/DD/YYYY format (leading zeros not required).
If you use YY in your date literals, it is understood to represent a year between 1951 and 2050. However, you can
specify your own cutover year by specifying the CENTURY option.
International Customers: you may want to specify the following option near the beginning of your
control statements:
OPTION: DDMMYYLIT
This option indicates that all date literals in the control statements will be in DD/MM/YY or DD/MM/YYYY
format.
Comparing Dates
One very powerful feature of Spectrum SMF Writer often takes some getting used to by programmers. If they have
used other report writers, programmers are used to matching the format of their date literal with the format of the
raw data in the record being tested. For example, if a record contains packed Julian dates, programmers usually
have to look up the desired date in Julian and then write their comparison literal in the same packed Julian date
format.
With Spectrum SMF Writer, this is not necessary. The program automatically handles all required date
conversions for you. So, whether a raw field is stored in the record as a packed Julian date, a character YYYYMMDD
or MMDDYY date, an 8-byte STCK date, or a binary day in century (to name a few of the formats), you always write
your comparison dates in MM/DD/[YY]YY format.
As an example, even though the SMF14DTE field is stored in the SMF record in packed P’CYYDDD’ format, you just
test it like this:
INCLUDEIF: SMF14RTY= 14 AND SMF14DTE >= 6/30/2010 AND <= 7/13/2010
The only exception would be if a field has accidentally been defined (in the copy library) as a plain character or
numeric field (rather than a true date field). In that case, you do need to compare it with a character or numeric
literal of the same format. In that case, you may also want to change the field’s definition (in the copy library).
Just locate the correct FIELD statement and add a TYPE parm that specifies one of the dozens of Date Data Types
listed in Appendix A of the Reference Manual. Then you will be able to test that field using date literals. (And the
field will also be formatted correctly as a date in the report output.)
Time Literals
Time literals should be in 24-hour HH:MM or HH:MM:SS[.DDD...] format.
Comparing Times
Once again, you do not need to be concerned with exactly how a time or interval field is stored in the SMF record.
As long as the field is defined as a true time field, Spectrum SMF Writer automatically handles all required
conversions for you. So, whether a field is stored in the record as packed seconds since midnight, character HHMM,
an 8-byte STCK time, or binary microseconds since midnight (to name a few examples), you always write your
comparison times in HH:MM[:SS] format.
For example, even though the SMF14TME field is stored in the SMF record as hundredths of a second since
midnight, you will test it like this:
INCLUDEIF: SMF14RTY= 14 AND SMF14DTE = 9/1/2010 AND SMF14TME >= 13:00 AND < 14:00
Again, if a time field has accidentally been defined as a regular character or numeric fields then you will need to
compare it with a character or numeric literal of the same format. Or you can locate the correct FIELD statement in
the copy library and add a TYPE parm that specifies one of the dozens of Time Data Types listed in Appendix A
of the Reference Manual. You may also need to add a DEC(n) parm to the FIELD statement, if the time field contains
decimal parts of a second.
Wildcard Comparisons
Spectrum SMF Writer does not have an actual wildcard character in its syntax for performing comparisons.
However, by applying a few tricks, you can usually achieve the same result.
To select all dataset names starting with the characters PROD1.ABC (like PROD1.ABC*, if * was a wildcard character
meaning any text of any length), you could use this code:
Or, say you want to select any DSN containing the characters 'PAY' anywhere within it (equivalent to *PAY*).
Spectrum SMF Writer has a special comparison operator called "contains." It is the colon character. The following
INCLUDEIF statement would select any record that had the characters "PAY" anywhere within the 44-byte
SMF14_JFCBDSNM field.
By being clever, you can even accomplish more complicated wildcard patterns like: PROD?.*PAYROLL* (if ? meant
any single character and * meant any text of any length):
If you need to break a literal onto multiple lines, continue up to column 72 in one line and resume it in column 2
of the next line.
This chapter shows some actual, useful SMF reports made with Spectrum SMF Writer. Each example includes
the control statements we used, along with a small sample of the report output. The examples are presented in
order of SMF record used. Some of these examples are included in the COPYLIB PDS that was included with
your download. Look for members whose name starts with "RUN".
SMF writes one type 5 record each time a background job terminates. This record includes the job's begin and end
date/time, which we can use to compute the session's elapsed time. For the final session of the month, we use the
end of the month as the "end time" for our elapsed time computation. And, for the first session of the month we
use the beginning of the month as the "begin time" for the computation. We sort the report on CICS region to sort
all of the sessions for each region together. We add a BREAK statement on region to get region totals for the
month. These totals that automatically print tell us the total up-hours for each region for the last month.
For each session, we also compute its elapsed time as a percentage of the total hours in the month. While not very
meaningful for an individual session, in the total line we can see what percentage of the month the CICS region
was available — a very useful number to monitor on a month to month basis.
(We showed the detail line in this example, so you can see how it works. But by uncommenting the SUMMARY
option statement, you can eliminate the detailed session lines and see just one total line for each CICS region for
the month. The perfect executive-level report!)
Note that this report makes extensive use of Spectrum SMF Writer's many powerful date and time computational
functions. We use them to: determine the begin and end dates of the previous calendar month; to compute elapsed
time from one date/time to another date/time, and convert that to into hours; and to calculate the exact number of
hours in the previous month. This report can run each month without requiring any manual changes to the control
statements.
COLUMNS:
SMF14_JOBID('JOBNAME READER TIMESTAMP' 26)
SMF14SPN('STEPNAME')
SMF14PGN('PGMNAME')
SMF14TIOE5('DDNAME')
SMF14_JFCBDSNM('DATASET NAME' 16) /* SHORTEN FOR SPACE*/
SMF14EXCP('EXCP/COUNT' 6)
SMF14_CRDT('CREATION/DATE')
SMF14_JFCLRECL('LRECL' 6)
SMF14_JFCBLKSI('BLKSIZE' 7)
SMF14_JFCBVOLS_1('VOLSER' 8)
SMF14MCN('SMS MGMT/CLASS')
SMF14SCN('SMS STOR/CLASS')
SORT: SMF14_JOBID
BALCOMB 08/02/07 07:41:39 BTPRMF52 IKJEFT01 SYSPROC SYS1.TSO.CLIST.N 0 04/08/03 80 27,920 KRJSTC
BALCOMB 08/02/07 07:41:39 BTPRMF52 IKJEFT01 SYSPROC SYS1.TSO.CLIST.N 0 04/08/03 80 27,920 KRJSTC
BALCOMB 08/02/07 07:41:39 BTPRMF52 IKJEFT01 SYSPROC SYS1.TSO.CLIST.N 0 04/08/03 80 27,920 KRJSTC
BALCOMB 08/02/07 07:41:39 BTPRMF52 IKJEFT01 SYSEXEC TSP.SISPEXEC 0 09/18/06 80 27,920 TIMPC0
BALCOMB 08/02/07 07:41:39 BTPRMF52 IKJEFT01 SYSEXEC TSP.SISPEXEC 0 09/18/06 80 27,920 TIMPC0
BALCOMB 08/02/07 07:41:39 BTPRMF52 IKJEFT01 SYSEXEC TSP.SISPEXEC 0 09/18/06 80 27,920 TIMPC0
BT910152 08/02/07 12:01:52 AT1 DFSULLS1 DFUTLP02 IMSSYST.IMS1.OLP 9,001 02/14/07 24,572 24,576 V91024 TESTBASE TESTBASE
BT910152 08/02/07 12:01:52 AT1 DFSULLS1 STEPLIB IMS910T.ZRS0.SDF 73 04/27/05 0 32,760 V91013 PRIOR TESTBASE
BT910648 08/02/07 12:06:48 AT1 DFSULLS1 DFUTLP03 IMSSYST.IMS1.OLP 9,001 02/14/07 24,572 24,576 V91116 TESTBASE TESTBASE
BT910648 08/02/07 12:06:48 AT1 DFSULLS1 STEPLIB IMS910T.ZRS0.SDF 73 04/27/05 0 32,760 V91013 PRIOR TESTBASE
BT911150 08/02/07 12:11:50 AT1 DFSULLS1 DFUTLP04 IMSSYST.IMS1.OLP 9,001 02/14/07 24,572 24,576 V91053 TESTBASE TESTBASE
BT911150 08/02/07 12:11:50 AT1 DFSULLS1 STEPLIB IMS910T.ZRS0.SDF 73 04/27/05 0 32,760 V91013 PRIOR TESTBASE
BT911352 08/02/07 12:13:52 AT1 DFSULLS1 DFUTLP01 IMSSYST.IMS4.OLP 12,001 02/14/07 22,524 22,528 V91095 TESTBASE TESTBASE
BT911352 08/02/07 12:13:52 AT1 DFSULLS1 STEPLIB IMS910T.ZRS0.SDF 73 04/27/05 0 32,760 V91013 PRIOR TESTBASE
BT912758 08/02/07 12:27:58 AT1 DFSULLS1 STEPLIB IMS910T.ZRS0.SDF 73 04/27/05 0 32,760 V91013 PRIOR TESTBASE
BT912758 08/02/07 12:27:58 AT1 DFSULLS1 DFUTLP02 IMSSYST.IMS1.OLP 9,001 02/14/07 24,572 24,576 V91024 TESTBASE TESTBASE
CSQ1BING 08/01/07 19:04:10 CSQ1BING CSQXJST SYS00180 TCPIP.ETC.SERVIC 7 02/05/97 80 3,120 C23SP3
DB29AT 08/01/07 19:09:46 DB29AT DFSMVRC0 JCLPDS D10.TIMDSW4.PROC 320 10/23/02 80 3,200 C23CL1
DB29AT 08/01/07 19:09:46 DB29AT DFSMVRC0 JCLPDS D10.TIMDSW4.PROC 316 10/23/02 80 3,200 C23CL1
DB29AT 08/01/07 19:09:46 DB29AT DFSMVRC0 JCLPDS D10.TIMDSW4.PROC 308 10/23/02 80 3,200 C23CL1
DB29AT 08/01/07 19:09:46 DB29AT DFSMVRC0 JCLPDS D10.TIMDSW4.PROC 332 10/23/02 80 3,200 C23CL1
DB29AT 08/01/07 19:09:46 DB29AT DFSMVRC0 JCLPDS D10.TIMDSW4.PROC 312 10/23/02 80 3,200 C23CL1
DB29AT 08/01/07 19:09:46 DB29AT DFSMVRC0 JCLPDS D10.TIMDSW4.PROC 324 10/23/02 80 3,200 C23CL1
DB29AT 08/01/07 19:09:46 DB29AT DFSMVRC0 JCLPDS D10.TIMDSW4.PROC 328 10/23/02 80 3,200 C23CL1
DB29AT 08/01/07 20:03:53 DB29AT DFSMVRC0 JCLPDS D10.TIMDSW4.PROC 64 10/23/02 80 3,200 C23CL1
...
In this example each report selects the same records — just the type 30 records with a subtype of 5 ("job
termination" records.) (But Spectrum SMF Writer allows you to specify different selection criteria for each report,
if desired.) We then compute the elapsed time by subtracting the Job start date/time from the date/time the log
record is written (at job termination time). We computed the elapsed time both in seconds, and in hours. For a job
run monthly, you would probably want the hours to print in the report. For a days worth of data, you could show
seconds. (Or create an elapased minutes field. Or print the elapsed time in HH:MM:SS format. With Spectrum
SMF Writer's flexibility, you have lots of options.)
In the first report, we simply sort and break on the SMF30WID field from the SMF 30 subtype 5 records.
SMF30WID contains a 4-byte "Work Type Identifier". By breaking on this field, the report shows us the count of
tasks for each category of work (Started Tasks, TSO Sessions, etc.) It also shows the total elapsed time for each
category. (Note that the sample report below used a very small test file of SMF records.)
The second report is very similar to the first one. But in this case, instead of using the SMF30WID field to
categorize tasks, we created our own WORK-TYPE field. We assigned values to it based on the contents of the
Jobname (SMF30JBN) and the SMF30WID fields. Note that Spectrum SMF Writer has a very powerful
comparison operator that other languages do not have — the colon. The colon comparator means "contains." For
example, we assign "CICS REGIONS" to WORK-TYPE if the jobname contains the characters CICS somewhere
within it.
The third report is just like the second report — but with an OPTION: SUMMARY statement added. That makes
it a summary report showing only the total lines. All of the detail lines are suppressed. That is an option you would
probably want if you ran this job on a whole month's worth of SMF data!
**************************************************
* SPECIFY WHICH SMF RECORDS TO INCLUDE IN REPORT
**************************************************
INCLUDEIF: SMF30RTY = 30 AND SMF30STP = 5
**************************************************
* SPECIFY REPORT TITLE
**************************************************
TITLE: 'NUMBER OF TASKS, BY WORD TYPE INDICATOR (SMF30WID)'
**************************************************
* COMPUTE THE NUMBER OF ELAPSED SECOND BY SUBTRACTING
* SMF LOG DATE/TIME FROM JOB START DATE/TIME
**************************************************
COMPUTE: ELAPSED-SECS =
(#MAKENUM(SMF30DTE) * 86400 + #MAKENUM(SMF30TME))
-(#MAKENUM(SMF30STD) * 86400 + #MAKENUM(SMF30SIT))
**************************************************
* SORT AND BREAK ON SMF30WID, WHICH IS
* THE 'WORK TYPE INDICATOR' FIELD, TO GET SUBTOTALS
*************************************************
SORT: SMF30WID
BREAK: SMF30WID SPACE(1)
**************************************************
* NOW DEFINE A NEW REPORT TO MAKE FROM THE
* SAME PASS OF THE SMF FILE
*************************************************
NEWOUTPUT:
**************************************************
* SPECIFY WHICH SMF RECS TO INCLUDE IN THIS REPORT
**************************************************
INCLUDEIF: SMF30RTY = 30 AND SMF30STP = 5
**************************************************
* BREAK THE TASK DOWN INTO CATEGEORIES THAT ARE
* MORE USEFUL FOR THIS SHOP THAN SMF30WID VALUES
**************************************************
COMPUTE: WORK-TYPE =
WHEN(SMF30JBN : 'CICS') ASSIGN('CICS REGIONS')
WHEN(SMF30JBN : 'DB2') ASSIGN('DB2 REGIONS')
WHEN(SMF30WID = 'STC') ASSIGN('STARTED TASKS')
WHEN(SMF30WID = 'TSO') ASSIGN('TSO SESSIONS')
ELSE ASSIGN('BATCH JOBS')
TITLE: 'NUMBER OF TASKS, BY TYPE'
SORT: WORK-TYPE
BREAK: WORK-TYPE SPACE(1)
**************************************************
* NOW DEFINE ANOTHER REPORT TO MAKE FROM THE
* SAME PASS OF THE SMF FILE
*************************************************
NEWOUTPUT:
**************************************************
* SUPPRESS DETAIL LINE AND JUST SHOW TOTALS
**************************************************
OPTION: SUMMARY
**************************************************
* SPECIFY WHICH SMF RECS TO INCLUDE IN THIS REPORT
**************************************************
INCLUDEIF: SMF30RTY = 30 AND SMF30STP = 5
SORT: WORK-TYPE
BREAK: WORK-TYPE SPACE(0)
ELAPSED ELAPSED
SMF30WID SMF30JBN SMF30JNM SMF30DTE SMF30TME SMF30STD SMF30SIT SECS HRS
________ ________ ________ ________ ___________ ________ ___________ ________ _______
BATCH JOBS B5A9514 STC07283 07/25/08 06:00:03.48 07/25/08 05:59:58.40 5.08 0.0014
BATCH JOBS FTPD4 STC07283 07/25/08 06:11:23.89 07/25/08 06:11:23.54 0.35 0.0001
BATCH JOBS B5A9514 STC07283 07/25/08 06:11:26.16 07/25/08 06:11:23.89 2.27 0.0006
BATCH JOBS O1X20715 JOB07291 07/25/08 06:25:49.35 07/25/08 06:25:06.68 42.67 0.0119
BATCH JOBS GSL10010 JOB02576 07/25/08 06:01:33.76 07/25/08 06:01:31.67 2.09 0.0006
BATCH JOBS AMTTRA23 JOB07284 07/25/08 06:02:38.59 07/25/08 05:59:36.87 181.72 0.0505
BATCH JOBS AMTPRM23 JOB07286 07/25/08 06:06:49.94 07/25/08 06:05:43.66 66.28 0.0184
BATCH JOBS AMTCON23 JOB07287 07/25/08 06:07:21.59 07/25/08 06:07:21.16 0.43 0.0001
BATCH JOBS BA1PORT JOB07289 07/25/08 06:09:06.37 07/25/08 06:08:45.17 21.20 0.0059
*** TOTAL FOR BATCH JOBS ( 9 ITEMS) 322.09 0.0895
STARTED TASKS B9AAQ STC07283 07/25/08 06:41:26.16 07/25/08 05:57:39.62 2,626.54 0.7296
STARTED TASKS SMFSLRD STC07285 07/25/08 06:00:14.57 07/25/08 06:00:14.46 0.11 0.0000
*** TOTAL FOR STARTED TASKS ( 2 ITEMS) 2,626.65 0.7296
TSO SESSIONS U016101 TSU07288 07/25/08 06:09:15.99 07/25/08 06:07:54.82 81.17 0.0225
TSO SESSIONS B5A9514 TSU07280 07/25/08 06:09:18.17 07/25/08 05:56:56.36 741.81 0.2061
*** TOTAL FOR TSO SESSIONS ( 2 ITEMS) 822.98 0.2286
Since the main purpose here is just to illustrate how to normalize an input file, this example simply lists some
fields from the EXCP sections of a few records. Specifically, we list the SMF30DEV (device class), SMF30DDN
(DDNAME) and SMF30BLK (block count) fields from the EXCP section. The other report fields all come from
the constant portion of the SMF 30 record.
By the way, there are many different kinds of variable sections in the SMF type 30 record (not just EXCP
sections). For example, there are I/O activity sections, processor accounting sections, performance sections,
storage sections and others. You can normalize any of these sections using this same technique with Spectrum
Writer. You can even normalize more than one section of the record in the same run.
SMF30DTE SMF30TME SMF30SID SMF30JBN SMF30PGM SMF30STM SMF30JNM SMF30DEV SMF30DDN SMF30BLK
...
The SMF record itself just contains a 2-byte binary value for step completion code (SMF30SCC). Depending on
the form of the value in SMF30SCC, we format it as a system abend code, user abend code, user return code or a
normal (zero) completion code.
A useful modification to this job would be to select only records with a non-zero completion code. That could be
the basis of a daily exception report.
**************************************************
* SPECIFY WHICH SMF RECORDS TO INCLUDE IN REPORT
**************************************************
INCLUDEIF: SMF30RTY = 30 AND SMF30STP = 4
**************************************************
* CREATE A FORMATTED COMP CODE TO SHOW IN REPORT
* SMF30SCC CAN BE: 0NNN -- SYSTEM ABEND CODE
* 8NNN -- USER ABEND CODE
* 0000 -- NORMAL TERM, OR FLUSHED
* NNNN -- USER COMPLETION CODE
**************************************************
COMPUTE: CC-HEX = #FORMAT(SMF30SCC,HEX) /* GET 4-BYTE CHAR */
COMPUTE: CC-NIB1 = #SUBSTR(CC-HEX,1,1) /* GET 1-BYTE 1ST NIBBLE*/
COMPUTE: CC-NIB2 = #SUBSTR(CC-HEX,2,1) /* GET 1-BYTE 2ND NIBBLE*/
**************************************************
* SPECIFY REPORT TITLE
**************************************************
TITLE: 'STEP COMPLETION CODES FROM SMF 30 RECORDS, SUBTYPE 4'
**************************************************
* SPECIFY WHICH SMF FIELDS TO SHOW IB RPT COLUMNS
* WE ALSO OVERIDE SOME COLUMN WIDTHS AND HEADINGS
**************************************************
COLUMNS: SMF30DTE
SMF30TME(HH-MM)
SMF30RTY(4,'SMF|REC|TYPE')
SMF30STP(4,'SMF|SUB|TYPE')
SMF30JBN('JOBNAME')
SMF30STN('STEP|NUM',4)
SMF30STM('STEPNAME')
SMF30SCC(HEX,'HEX|COMP/CODE')
COMP-CODE('FORMATTED|COMP|CODE')
We assigned each job to a quarter-hour time slot. We also computed some useful data items to include in the
report.
We sorted the records by time slot, and printed only the total information for each time slot. The SUMMARY
option suppessed the detailed information for each job. (You may want to include the detail information as you
are developing your report, and then add the SUMMARY option when it is fully debugged.)
We used the COLUMNS statement just to get the automatic column headings. The data that actually prints in the
report is specified in the two BREAK statements. One BREAK statement for the time slot control break. The other
BREAK statement is for the grand total "break."
Note that the sample report below uses a small test SMF file. A production file would show slots for all (active)
times of the day.
**************************************************
* SPECIFY THE INPUT FILE (AND LAYOUT) FOR THIS RUN
**************************************************
INPUT: SMF30
**************************************************
* SPECIFY WHICH SMF RECORDS TO INCLUDE IN REPORT
* WE WANT SMF 30 JOB COMPLETION RECORDS FOR 1 DAY
**************************************************
INCLUDEIF: SMF30RTY = 30 AND SMF30STP = 5
AND SMF30WID = 'JES2'
AND SMF30TME > SMF30PPS /* SAME DAY */
AND SMF30PPS > 00:00 /* DID START*/
**************************************************
* SPECIFY REPORT TITLE
**************************************************
TITLE: 'JES2 JOB STATISTICS'
TITLE: 'FOR EACH QUARTER HOUR OF THE DAY'
**************************************************
* COMPUTE SOME SPECIAL VALUES FOR THE REPORT
**************************************************
COMPUTE: BEG_TIME =
WHEN(SMF30RST <> 00:00) ASSIGN(SMF30RST) /*RDR */
ELSE ASSIGN(SMF30SIT) /*INIT*/
COMPUTE: TIME =
WHEN(BEG_TIME < 00:15:00) ASSIGN('00:00')
WHEN(BEG_TIME < 00:30:00) ASSIGN('00:15')
WHEN(BEG_TIME < 00:45:00) ASSIGN('00:30')
WHEN(BEG_TIME < 01:00:00) ASSIGN('00:45')
WHEN(BEG_TIME < 01:15:00) ASSIGN('01:00')
WHEN(BEG_TIME < 01:30:00) ASSIGN('01:15')
**************************************************
* SPECIFY WHICH SMF FIELDS TO SHOW IN RPT COLUMNS
* WE ALSO OVERIDE SOME COLUMN WIDTHS AND HEADINGS
**************************************************
COLUMNS:
TIME('JOB|BEGIN|TIME')
JOB_COUNT(5)
CPU_SECS('AVG|CPU|TIME|(SECS)' 9)
CPU_SECS('MAX|CPU|TIME|(SECS)' 9)
ELAPSED_TIME('AVG|ELAPSED|TIME|(SECS)' 9)
ELAPSED_TIME('MAX|ELAPSED|TIME|(SECS)' 9)
JOB_QUEUE_TIME('AVG|SECS|IN JOB|QUEUE' 7)
STORAGE_USED('AVG|STORAGE|PER JOB|(K''S)' 7)
TAPE_MOUNTS('AVG NUM|TAPE|MOUNTS' 7)
PAGE_SWAPS('AVG NUM|PAGE|SWAPS' 7)
**************************************************
* SUMMARIZE BY TIME SLOT
**************************************************
SORT: TIME
BREAK: TIME
NOTOTALS
FOOTING(
TIME
JOB_COUNT(TOTAL 5)
CPU_SECS(AVG 9)
CPU_SECS(MAX 9)
ELAPSED_TIME(AVG 9)
ELAPSED_TIME(MAX 9)
JOB_QUEUE_TIME(AVG 7)
STORAGE_USED(AVG 7)
TAPE_MOUNTS(AVG 7)
PAGE_SWAPS(AVG 7)
)
BREAK: #GRAND
NOTOTALS
FOOTING(
'*ALL*'
JOB_COUNT(TOTAL 5)
CPU_SECS(AVG 9)
CPU_SECS(MAX 9)
ELAPSED_TIME(AVG 9)
ELAPSED_TIME(MAX 9)
JOB_QUEUE_TIME(AVG 7)
STORAGE_USED(AVG 7)
TAPE_MOUNTS(AVG 7)
PAGE_SWAPS(AVG 7)
)
For demo purposes, we have multiplied the EXCP count and the CPU seconds by arbitrary per-unit costs. Now
the chargeback "costs" can be shown directly in this SMF data extraction report.
One important task is choosing the info in the SMF 30 record that will assign each job to its appropriate "cost
center" for charge back purposes. Possibilities include the job card accounting field, or part of the jobname itself.
For this demo report, we used the first four bytes of the jobname as the cost-center identifier.
We grouped the jobs according to this jobname prefix. We sort and break on this job prefix to get total EXCP and
CPU for each of these "cost centers". And also the total chargeback "dollars" for each cost center.
Once the report is fully developed and looks good at the individual job level, we would simply uncomment the
SUMMARY statement (at the top) to suppress all the detail lines and turn it into an executive summary report.
Then the report will just print the totals for each cost center.
This gives an idea of the sort of chargeback possibilities that exist with Spectrum SMF Writer. This low-cost
program can give you an amazing amount of useful information with only minimal coding effort. It can quickly
pay for itself in the amount of programming effort saved.
**************************************************
* SPECIFY THE INPUT FILE (AND LAYOUT) FOR THIS RUN
**************************************************
INPUT: SMF30
**************************************************
* SPECIFY WHICH SMF RECORDS TO INCLUDE IN REPORT
* SUBTYPE 5 MEANS JOB TERMINATION RECORDS REPORT
**************************************************
INCLUDEIF: SMF30RTY = 30 AND SMF30STP = 5
*
**************************************************
* EXTRACT 1ST 8 BYTES OF JOBCARD ACCOUNT FIELD *
**************************************************
COMP: ACCT(8) = #LEFT(SMF30ACT,#MIN(8,SMF30ACL))
*
**************************************************
* WE WILL TOTAL CHARGES BY LEADING PART OF JOBNAME
**************************************************
COMP: JOB_PREFIX = #LEFT(SMF30JBN,4)
*
COMP: SRB_CPU = #MAKENUM(SMF30CPS) /* CHG TIME TO SECS */
**************************************************
* COMPUTE ELAPSED TIME IN SYSTEM *
**************************************************
COMP: ELAP_SYS = #MAKETIME(
((#MAKENUM(SMF30DTE) * 86400) + #MAKENUM(SMF30TME))
- ((#MAKENUM(SMF30RSD) * 86400) + #MAKENUM(SMF30RST)) )
**************************************************
* ASSIGN A MADE-UP COST FOR DEMO PURPOSES *
**************************************************
COMP: FAKE_IO_RATE = .01 /* PENNY PER EXCP */
COMP: FAKE_IO_CHG = SMF30TEX * FAKE_IO_RATE
*
COMP: SMF30CPT_SECS =#MAKENUM(SMF30CPT)
COMP: FAKE_CPU_RATE = 5.25 /* $5.25 PER CPU SECOND */
COMP: FAKE_CPU_CHG(2) = #MAKENUM(SMF30CPT) * FAKE_CPU_RATE
*
**************************************************
* SPECIFY WHICH SMF FIELDS TO SHOW IN RPT COLUMNS.
* WE ALSO OVERIDE SOME COLUMN WIDTHS AND HEADINGS*
**************************************************
COLUMNS:
SMF30JBN('JOBNAME')
JOB_PREFIX
ACCT('JOB|CARD|ACCOUNT')
'|'
SMF30TEX('TOTAL|EXCPS' 11)
FAKE_IO_RATE('I/O|RATE|(FAKE)' 6 NOACCUM)
FAKE_IO_CHG('I/O|CHARGE|(FAKE)' 11 DOLLAR)
'|'
SMF30CPT_SECS('CPU|TIME|(SECS)' 8)
FAKE_CPU_RATE('CPU|RATE|(FAKE)' 6 NOACCUM)
FAKE_CPU_CHG('CPU|CHARGE|(FAKE)' 11 DOLLAR)
'|'
SRB_CPU('SRB|TIME|(SECS)' 6)
ELAP_SYS('ELAPSED|TIME IN|SYSTEM' ACCUM)
ELAP_EX('ELAPSED|EXECUTION|TIME' ACCUM)
**************************************************
* SPECIFY REPORT TITLE
**************************************************
TITLE: 'CHARGE BACK RELATED JOB INFO FROM SMF 30-5 RECS'
TITLE: 'FOR' SMF30DTE
**************************************************
* SORT AND BREAK ON JOB PREFIX, WITH SUBTOTALS. *
* (ACCT IS ANOTHER CHOICE FOR HERE) *
**************************************************
SORT: JOB_PREFIX
BREAK: JOB_PREFIX TOTALS('** TOTALS' JOB_PREFIX)
AT122309 AT12 | 7,644 0.01 $76.44 | 0.31 5.25 $1.63 | 0.23 00:00:05.28 00:00:04.73
AT122109 AT12 | 18,002 0.01 $180.02 | 0.60 5.25 $3.15 | 0.46 00:00:09.80 00:00:09.01
** TOTALS AT12 25,646 $256.46 0.91 $4.78 0.69 00:00:15.08 00:00:13.74
DUMPSMF DUMP | 38,489 0.01 $384.89 | 1.07 5.25 $5.62 | 0.39 00:00:37.44 00:00:00.29
** TOTALS DUMP 38,489 $384.89 1.07 $5.62 0.39 00:00:37.44 00:00:00.29
LOGWRTR LOGW | 18 0.01 $0.18 | 0.26 5.25 $1.37 | 0.00 00:00:00.92 00:00:00.37
** TOTALS LOGW 18 $0.18 0.26 $1.37 0.00 00:00:00.92 00:00:00.37
U0200021 U020 ACT123 | 153 0.01 $1.53 | 0.06 5.25 $0.32 | 0.00 00:00:00.15 00:00:00.11
U0200095 U020 ACT123 | 14,598 0.01 $145.98 | 1.74 5.25 $9.14 | 0.01 00:00:33.80 00:00:33.80
U0240052 U024 ACT123 | 9,969 0.01 $99.69 | 1.32 5.25 $6.93 | 0.01 00:00:20.62 00:00:20.62
U0240082 U024 ACT123 | 9,975 0.01 $99.75 | 1.34 5.25 $7.04 | 0.04 00:00:29.82 00:00:29.82
U0240021 U024 ACT123 | 9,957 0.01 $99.57 | 1.27 5.25 $6.67 | 0.01 00:00:21.39 00:00:21.39
** TOTALS U024 935,117 $9,351.17 119.44 $627.30 0.98 00:43:12.78 00:43:11.88
WSWS1 WSWS | 140 0.01 $1.40 | 0.03 5.25 $0.16 | 0.01 00:00:00.31 00:00:00.31
WSWS2 WSWS | 36 0.01 $0.36 | 0.04 5.25 $0.21 | 0.00 00:00:00.19 00:00:00.19
WSWS9 WSWS | 138 0.01 $1.38 | 0.03 5.25 $0.16 | 0.00 00:00:00.23 00:00:00.23
** TOTALS WSWS 314 $3.14 0.10 $0.53 0.01 00:00:00.73 00:00:00.73
********* SET DSN TEXT BELOW. ALSO SET COMPDSN TO SAME LENGTH ****
COMP: TESTDSN = 'TTAP01B' /* LOOK FOR THESE DSN PREFIXES */
COMP: COMPDSN(7) = SMF42DSNAM /* TRUNCATE DSN TO TESTDSN'S SIZE */
COLUMNS:
SMF42JDJNM(8 'JOBNAME')
SMF42JDRSD(8 'READER|DATE')
SMF42JDRST(11 'READER|TIME')
SMF42JDWSC(8)
SMF42JDWLD(8)
SMF42DSNAM(20)
SMF42DSIOR(7 'IO|RATE')
SMF42DSION(8 "NUM|IO'S")
SMF42DSVOL(8 'VOLUME')
SMF42DSSC(8 'STORAGE|CLASS')
SMF42DSBSZ(6 'BLOCK|SIZE')
...
INCLUDEIF: SMF64RTY = 64
COLUMNS:
SMF64_JOBID('JOBNAME AND READER TIME')
SMF64VSN('VOLUME')
SMF64CUU('DEVICE' HEX)
SMF64FCC('BEG|CCCHH' HEX)
SMF64TCC('END|CCCHH' HEX)
SMF64NEX('NUM|CEXTENTS' 7)
SMF64NLR('NUM|CRECS' 9)
SMF64NDE('NUM|CDELETES' 9)
SMF64NCS('NUM|CCI|CSPLITS' 5)
SMF64NAS('NUM|CCA|CSPLITS' 5)
SMF64NEP('NUM|CEXCPS' 8)
NUM NUM
BEG END NUM NUM NUM CI CA NUM
JOBNAME AND READER TIME VOLUME DEVICE CCHH CCHH EXTENTS RECS DELETES SPLIT SPLIT EXCPS
_____________________________ ______ ______ ________ ________ _______ _________ _________ _____ _____ ________
DLISET82 05/23/08 22:13:47.86 DB4D03 5D03 26C50000 26CE000E 15 1,115,761 25,946 1,273 0 303,715
DLISET82 05/23/08 22:13:47.86 DB4DSP 5F06 00920002 00920004 12 296,178 1 162 17 64,141
*** TOTAL FOR DLISET82 05/23/08 22:13:47.86 ( 2 ITEMS) 27 1,411,939 25,947 1,435 17 367,856
In this report, we take advantage of several of Spectrum's special formatting options. The BIZ ("blank if zero")
option suppresses 0 values, which can clutter up a report. Also, since the SMF744SASQ field encompasses a wide
range of values, we used a "scaled" type of picture to format it. Spectrum automatically displays a value with the
appropriate K, M, G, ... suffix as necessary. This technique lets you display more data (in smaller columns) when
it is not essential to know the exact value of a field.
We also used another technique to squeeze more data columns into the report. Since the identical Sysplex and
System names appear for hundreds of consecutive lines, we moved those 2 fields from the detail report lines up
into the page titles. We page-break on those fields to insure that the data on each page comes from a single
Sysplex-System.
COLUMNS:
SMF744SNAM('CONNECTED|STRUCTURE')
SMF74IST('INTERVAL|START|TIME')
SMF74INT_TIME(TP'ZZ:Z9.999' 'INTERVAL|LENGTH')
SMF744SSIZ(8 'STRUCT|SIZE' BIZ)
SMF744SARC_VAL('TOTAL|ASYNCH|OPERS' 8 BIZ)
SMF744SASQ('SUM|SQRS|SERVIC|TIME|ASYNCH' 6 P'Z,ZZ9@' BIZ)
SMF744SATM('SUM|SERVIC|TIME|ASYNCH' 10 BIZ)
SMF744SSTA_VAL('ASYNCH|REQS|NO RESRC' 8 BIZ)
SMF744SSRC_VAL('CNT|TIMES|SYNCH|REQS' 8 BIZ)
SMF744SSSQ('SUM-SQRS|SERVIC|TIME|SYNCH' 10 BIZ)
SMF744SSTM('SUM|SERVIC|TIME|SYNCH' 10 BIZ)
SUM
SQRS SUM CNT SUM-SQRS SUM
INTERVAL TOTAL SERVIC SERVIC ASYNCH TIMES SERVIC SERVIC
CONNECTED START INTERVAL STRUCT ASYNCH TIME TIME REQS SYNCH TIME TIME
STRUCTURE TIME LENGTH SIZE OPERS ASYNCH ASYNCH NO RESRC REQS SYNCH SYNCH
________________ ________ _________ ________ ________ ______ __________ ________ ________ __________ __________
...
We print a report showing each RACF processing event, with a description of what the event was, and the
outcome. Note that the actual SMF record just contains codes for the event and its status. The Spectrum SMF
Writer definitions include code to expand those numeric values into descriptive texts. (You can see this code in
member REC80 of your Spectrum SMF copy library.)
These events are grouped by unique JOB and printed in JOB/timestamp order.
INC: SMF80RTY = 80
SORT: SMF80_JOBID
TITLE: #DATE ' '#TIME /'RACF EVENT LOG BY JOB' / 'PAGE' #PAGE
SMF80
EVENT SMF80 EVENT
DESC EVENT CODE EVENT QUAL
SMF80DTE SMF80TME JOBNAME FLAGS CODE QUAL NAME DESC USER GROUP TERMINAL
________ ___________ ________ _____ _____ _____ _________________________ ________________ ________ ________ ________
07/24/06 11:37:33.62 NRP0A 2800 02 00 RESOURCE ACCESS Successful acces NRP0A SYS1
07/24/06 11:36:57.47 NRP0A 2800 02 00 RESOURCE ACCESS Successful acces NRP0A SYS1
07/24/06 11:40:28.69 STRT2 A800 01 01 JOB INITIATION / TSO LOGO Password not val U078044 TESTYP6 7F000001
07/24/06 11:40:28.83 STRT2 A800 01 01 JOB INITIATION / TSO LOGO Password not val U078044 TESTYP6 7F000001
07/24/06 11:55:27.14 STRT2 A800 01 01 JOB INITIATION / TSO LOGO Password not val U078044 TESTYP6 7F000001
07/24/06 11:55:27.27 STRT2 A800 01 01 JOB INITIATION / TSO LOGO Password not val U078044 TESTYP6 7F000001
07/24/06 11:30:10.60 USR0032 A800 1D 01 CHECK ACCESS TO DIRECTORY Not authorized USR0032 MONFLOT 090C14D7
07/24/06 11:30:10.60 USR0032 A800 1D 01 CHECK ACCESS TO DIRECTORY Not authorized USR0032 MONFLOT 090C14D7
07/24/06 11:36:19.20 USR0048 A800 1E 01 CHECK ACCESS TO FILE Not authorized USR0048 MONFLOT 090C112B
07/24/06 11:30:39.32 USR0097 A800 1E 01 CHECK ACCESS TO FILE Not authorized USR0097 MONFLOT C0A8198A
07/24/06 11:47:18.81 XX4DMGS A800 01 01 JOB INITIATION / TSO LOGO Password not val XXTIDM4 XXTADMGP
07/24/06 11:55:21.94 XX6ADM A800 1C 01 DIRECTORY SEARCH Not authorized XX6ADM XX6CFG 09418620
We print a report showing the TCB and SRB time for each monitored product during each recording interval. The
information is sorted and report by Sysplex name, then by System name and finally by Product name, with
subtotals for each product. We have report both the TCB and SRB times in two ways: as the number of seconds,
as they appear in the record. And again after converting the seconds into standard hour, minute and second
notation. Spectrum SMF Writer makes this easy with its powerful built-in time handling functions.
COLUMNS:
SMF89SYN('MVS|SYSTEM|NAME')
SMF89UST('INTERVAL|START|TIME')
SMF89UET('INTERVAL|END|TIME')
SMF89UPN('PRODUCT|NAME')
SMF89UCT('TCB|TIME|SECONDS' 12)
TCB_TIME('TCB|TIME')
SMF89USR('SRB|TIME|SECONDS' 12)
SRB_TIME('SRB|TIME')
INPUT: SMF94
COMPUTE: SMF94ADV0-10 =
WHEN(SMF942OF <> 0) ASSIGN(SMF94ADV05 + SMF94ADV10)
COMPUTE: SMF94ADV10-20 =
WHEN(SMF942OF <> 0) ASSIGN(SMF94ADV15 + SMF94ADV20)
COMPUTE: SMF94ADV20-30 =
WHEN(SMF942OF <> 0) ASSIGN(SMF94ADV25 + SMF94ADV30)
COMPUTE: SMF94ADV30-40 =
WHEN(SMF942OF <> 0) ASSIGN(SMF94ADV35 + SMF94ADV40)
COMPUTE: SMF94ADV40-50 =
WHEN(SMF942OF <> 0) ASSIGN(SMF94ADV45 + SMF94ADV50)
COMPUTE: SMF94ADV50-100 =
WHEN(SMF942OF <> 0) ASSIGN(SMF94ADV55 + SMF94ADV60
+ SMF94ADV65 + SMF94ADV70
+ SMF94ADV75 + SMF94ADV80
+ SMF94ADV85 + SMF94ADV90
+ SMF94ADV95 + SMF94ADV00)
DEST RECS RECS NOT BUFFER NOT ACTIVE REC NOT WRITER
SMF DATE SMF TIME REC IFCID NAME WRITTEN WRITTEN ERRORS ERRORS ACCEPTED ERRORS
________ ___________ ___ _____ ____ ______________ ______________ ____________ ____________ ____________ ____________
...
We further select on the value in the DB2 PLAN field to get just the trace records for the plan we are interested in.
We then print a report showing various data fields from the SMF 101 records for that plan. We leave the report in
SMF log time order.
TITLE: /'DB2 ACCOUNTING INFO FOR DB2PLAN: MAJSERVR' / #DATE ' ' #TIME
We normalize those 110 records in order to process each performance segment present on each record. We print
some identifying information from each segment. (Most users would also add a column for one or more of the
performance measures present on the record.)
We sorted the records by transaction, printing two blank lines at the breaks.
COLUMNS:
SMF110DTE('SMF DATE')
SMF110TME('SMF TIME' TP'99:99:99')
SMF110RTY(3 'REC|TYP')
SMF110STY(3 'SUB|TYP')
SMF110S1_MNCL(4 'CLASS|OF|DATA')
SMF110S1_TRAN('TRAN')
SMF110S1_USERID
SMF110S1_START('START|TIME' TP'99:99:99')
SMF110S1_STOP
SMF110S1_PGMNAME
SMF110S1_SRVCLSNM(8 'SERVICE|CLASS')
CLAS
REC SUB OF SMF110S1 START SMF110S1 SMF110S1 SERVICE
SMF DATE SMF TIME TYP TYP DATA TRAN USERID TIME STOP PGMNAME CLASS
________ ________ ___ ___ ____ ____ ________ ________ _______________ ________ ________
From these SMF records, we print the CICS transaction name and the CICS "program" name under which it
executed. We print the transaction's start and stop time. (Notice that Spectrum SMF Writer takes the raw 8-byte
STCK times and automatically reformats them for you as hour, minutes and seconds - right down to a millionth
of a second.)
We also compute the elapsed time by subtracting the stop time from the start time. (It's actually a bit more
complicated than that. We also took into account the start and stop dates, in case the transaction spans midnight.)
We also print the value found in the SMF records for CPU time, dispatch time and suspend time. These values are
not filled in for all records.
Finally we sort the report by transaction name, CICS name and date/time. We break and space 1 line between
different transactions. (In this example, we specified the break and break spacing directly in the SORT statement.
We did not use a BREAK statement at all.)
COLUMNS:
SMF110DTE('SMF|LOG|DATE')
SMF110TME('SMF|LOG|TIME' TP'99:99:99')
SMF110S1_MNJBN('CICS|JOBNAME')
SMF110S1_TRAN('TRAN')
SMF110S1_START
SMF110S1_STOP
SMF110S1_RESPONSE_TIME(8, 'ELAPSED|TIME')
SMF110S1_USRDISPT('DISPATCH|TIME')
SMF110S1_USRCPUT('CPU|TIME')
SMF110S1_SUSPTIME('SUSPEND|TIME')
SMF SMF
LOG LOG CICS SMF110S1 SMF110S1 ELAPSED DISPATCH CPU SUSPEND
DATE TIME TRAN JOBNAME START STOP TIME TIME TIME TIME
________ ________ ____ ________ _______________ _______________ __________ _______________ _______________ _____________
12/30/09 00:34:27 CEMT CICSVIBK 23:19:26.698238 23:34:26.901300 15:00.203 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:22:54 CISE CICSVATM 23:22:54.054290 23:52:54.197499 30:00.143 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:50:53 CISE CICSVCTG 00:05:52.764595 00:35:52.645543 29:59.881 00:00:00.000000 00:00:00.000000 00:29:59.8809
12/29/09 23:53:29 CISM CICLUTIN 23:08:28.457983 23:23:28.657409 15:00.199 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/29/09 23:45:38 CISM CICSVWLK 22:45:37.704110 23:15:37.584835 29:59.881 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 01:20:53 CISR CICSVCTG 00:35:52.645252 00:50:52.851959 15:00.207 00:00:00.000000 00:00:00.000000 00:15:00.2067
12/30/09 00:21:06 CKTI CICSEAI 23:06:06.372819 23:36:06.254236 29:59.881 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/29/09 23:52:54 COIE CICSVATM 22:52:54.177421 23:22:54.054167 29:59.877 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 01:30:38 COIE CICSVWLK 00:45:37.488736 01:00:37.691469 15:00.202 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/29/09 23:52:52 COI0 CICSVTIN 23:20:32.758513 23:50:32.901407 30:00.142 00:00:00.000000 00:00:00.000000 00:30:00.1428
12/30/09 00:52:39 COI0 CICSVTIN 00:20:32.782153 00:50:32.667259 29:59.885 00:00:00.000000 00:00:00.000000 00:29:59.8851
12/30/09 00:30:16 COI0 CICSVWRS 23:59:08.538353 00:29:08.419178 29:59.881 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 01:15:17 COI0 CICSVWRS 00:59:08.299732 01:14:08.502507 15:00.203 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:52:54 CSKL CICSVATM 23:52:54.197580 00:22:54.077883 29:59.880 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 01:00:38 CSNC CICSVWLK 00:15:37.607961 00:45:37.488564 29:59.881 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:27:32 CSNE CICSVBKT 23:38:16.277222 00:08:16.158398 29:59.881 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:51:06 CSSY CICSEAI 00:06:06.134042 00:21:06.336672 15:00.203 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/29/09 23:57:38 CSSY CICSVCRD 23:25:46.020150 23:55:45.901009 29:59.881 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:27:39 CSSY CICSVCRD 23:55:45.901009 00:25:46.043884 30:00.143 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:23:00 CSSY CICSVTIN 23:50:32.901126 00:20:32.782049 29:59.881 00:00:00.000000 00:00:00.000000 00:29:59.8809
12/30/09 01:07:43 CSSY CICSVTIN 00:50:32.667043 01:05:32.867509 15:00.201 00:00:00.000000 00:00:00.000000 00:15:00.2004
12/30/09 00:00:07 CSSY CICSVWRS 23:29:08.395441 23:59:08.538121 30:00.143 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:45:37 CSSY CICSVWLK 23:45:37.726665 00:15:37.607789 29:59.881 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 01:23:29 CSTP CICLUTIN 00:23:28.680285 00:53:28.561157 29:59.881 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 01:00:45 CSTP CICSVCRD 00:25:46.043924 00:55:45.928358 29:59.884 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 01:30:45 CSTP CICSVCRD 00:55:45.928358 01:25:46.067593 30:00.140 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/29/09 23:46:30 NA10 CICSVWRS 23:45:09.415186 23:45:09.417277 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/29/09 23:57:55 NA10 CICSVWRS 23:56:42.786625 23:56:42.788684 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:09:00 NA10 CICSVWRS 00:07:46.010429 00:07:46.012820 0.003 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:11:33 NA10 CICSVWRS 00:10:16.743547 00:10:16.745772 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:14:06 NA10 CICSVWRS 00:12:47.475928 00:12:47.478273 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:16:40 NA10 CICSVWRS 00:15:18.208815 00:15:18.211266 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:28:05 NA10 CICSVWRS 00:26:51.579611 00:26:51.581779 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:36:36 NA10 CICSVWRS 00:35:24.072558 00:35:24.074685 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:39:09 NA10 CICSVWRS 00:37:54.803954 00:37:54.806177 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:41:43 NA10 CICSVWRS 00:40:25.537018 00:40:25.539253 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/30/09 00:44:16 NA10 CICSVWRS 00:42:56.269533 00:42:56.271769 0.002 00:00:00.000000 00:00:00.000000 00:00:00.0000
12/29/09 23:45:50 NA20 CICSVTIN 23:38:47.471498 23:38:47.476270 0.005 00:00:00.001843 00:00:00.001778 00:00:00.0029
12/29/09 23:50:33 NA20 CICSVTIN 23:46:19.671154 23:46:19.675617 0.005 00:00:00.001718 00:00:00.001708 00:00:00.0027
12/30/09 00:00:24 NA20 CICSVTIN 23:53:21.721659 23:53:21.726867 0.005 00:00:00.001815 00:00:00.001812 00:00:00.0033
12/30/09 00:07:56 NA20 CICSVTIN 00:00:53.919979 00:00:53.924962 0.005 00:00:00.001821 00:00:00.001815 00:00:00.0031
12/30/09 00:15:28 NA20 CICSVTIN 00:08:26.118493 00:08:26.123417 0.005 00:00:00.001948 00:00:00.001831 00:00:00.0029
12/30/09 00:20:33 NA20 CICSVTIN 00:15:58.316783 00:15:58.324343 0.007 00:00:00.001817 00:00:00.001803 00:00:00.0057
12/30/09 00:30:33 NA20 CICSVTIN 00:23:30.519874 00:23:30.524807 0.005 00:00:00.001896 00:00:00.001815 00:00:00.0030
12/30/09 00:38:05 NA20 CICSVTIN 00:31:02.713904 00:31:02.718752 0.005 00:00:00.001805 00:00:00.001768 00:00:00.0030
12/30/09 00:45:37 NA20 CICSVTIN 00:38:34.912368 00:38:34.917524 0.006 00:00:00.001834 00:00:00.001804 00:00:00.0033
12/30/09 00:50:33 NA20 CICSVTIN 00:46:07.113059 00:46:07.117908 0.005 00:00:00.001818 00:00:00.001817 00:00:00.0030
12/30/09 01:00:11 NA20 CICSVTIN 00:53:09.164768 00:53:09.169786 0.005 00:00:00.001802 00:00:00.001798 00:00:00.0032
12/30/09 01:05:33 NA20 CICSVTIN 01:00:41.360650 01:00:41.366474 0.005 00:00:00.001834 00:00:00.001799 00:00:00.0039
12/30/09 01:15:16 NA20 CICSVTIN 01:08:13.559012 01:08:13.563552 0.005 00:00:00.001847 00:00:00.001838 00:00:00.0026
12/30/09 01:22:48 NA20 CICSVTIN 01:15:45.758016 01:15:45.762949 0.005 00:00:00.001797 00:00:00.001794 00:00:00.0031
12/30/09 01:30:20 NA20 CICSVTIN 01:23:17.955831 01:23:17.961375 0.005 00:00:00.001818 00:00:00.001804 00:00:00.0037
...
The first report shows the contents of all Counter Set segments. It also shows the actual counter value for the first
counter of the first counter set.
The second report shows the contents of all of the actual counters themselves. You can use the two reports
together, along with a key to the "counter maps" for your level of z/OS, to assign meanings to the counter values.
INCLUDEIF: SMF113RTY=113
COLUMNS:
SMF113_2_CTS('START|COLLECT|TIME' TP'Z9:99:99')
SMF113_2_CTM('END|COLLECT|TIME' TP'Z9:99:99')
SMF113DTE('END|COLLECT|DATE')
SMF113_2_CPU('PROC|NUM' 4)
SMF113_2_CST('CTR|SET|TYPE' 4)
SMF113_2_CSN('NUM|CNTRS' 5)
SMF113_2_CSP('COUNTER MAP')
SMF113_2_CR('1ST|COUNTER|IN SMF REC' 18)
...
The statistics include number of buffer pools, number of stealable buffers, lowest number of stealable buffers
during the period, actual number of buffer steals, number of get page old and get page new requests, count of
DASD read and write ops, pages written to DASD, etc.
COLUMNS:
SMF115SID('Z/OS|SUB|SYSTEM')
SMF115TME('PERIOD|ENDING' TPIC'Z9:99:99')
QPSTPOOL('BUFFER|POOL|NUMBER' 6)
QPSTNBUF('# OF|BUFFERS|IN POOL' 8)
QPSTCBSL('LOWEST|# OF|STEALABLE|BUFFERS' 9)
QPSTCBS('# OF|STEALABLE|BUFFERS' 9)
QPSTSTL('# OF|BUFFER|STEALS' 9)
QPSTGETP('# OF|GET PAGE|(OLD)|REQUESTS' 11)
QPSTGETN('# OF|GET PAGE|(NEW)|REQUESTS' 11)
QPSTRIO('# OF|DASD|READ|OPS' 6)
QPSTSTW('# OF|SET WRITE|INTENT|REQUESTS' 9)
QPSTTPW('# OF|PAGES|WRITTEN|TO DASD' 9)
QPSTWIO('# OF|DASD|WRITE|OPS' 6)
LOWEST # OF # OF # OF # OF # OF # OF
Z/OS BUFFER # OF # OF # OF # OF GET PAGE GET PAGE DASD SET WRITE PAGES DASD
SUB PERIOD POOL BUFFERS STEALABLE STEALABLE BUFFER (OLD) (NEW) READ INTENT WRITTEN WRITE
SYSTEM ENDING NUMBER IN POOL BUFFERS BUFFERS STEALS REQUESTS REQUESTS OPS REQUESTS TO DASD OPS
______ ________ ______ ________ _________ _________ _________ ___________ ___________ ___________ ___________ _________ ______
ZSA 11:00:07 0 50,000 49,618 49,943 0 833,658 26,025 0 736,158 386 112
ZSA 11:00:07 1 20,000 17,424 18,457 0 1,318,813 507,094 0 1,016,252 2,518 689
ZSA 11:00:07 2 50,000 49,990 49,993 0 2,962 528 0 2,962 14 14
ZSA 11:00:07 3 20,000 19,830 19,885 0 198,242 5,373 0 56,514 144 41
ZSA 11:00:07 4 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 5 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 6 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 7 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 8 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 9 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 10 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 11 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 12 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 13 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 14 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:07 15 0 0 0 0 0 0 0 0 0 0
ZSA 11:00:36 0 50,000 49,972 49,972 0 38 0 0 28 0 0
ZSA 11:00:36 1 20,000 19,999 19,999 0 0 0 0 0 0 0
ZSA 11:00:36 2 50,000 49,995 49,995 0 5 1 0 5 0 0
ZSA 11:00:36 3 20,000 19,992 19,992 0 20 4 0 20 0 0
...
COLUMNS: SMF119AP_TTRNAME('RESOURCE')
SMF119AP_TTSDATE('DATE|STARTED')
SMF119AP_TTSTIME('TIME|STARTED')
SMF119AP_TTEDATE('DATE|ENDED')
SMF119AP_TTETIME('TIME|ENDED')
MY_DURATION('CONNECTION|DURATION|HH:MM:SS.SS' ACCUM
TP'ZZ:ZZ:Z9.99')
SMF119AP_TTINBYTES('INBOUND|BYTES')
SMF119AP_TTOUTBYTES('OUTBOUND|BYTES')
SMF119AP_TTTERMCODE(HEX 'TERM|CODE')
SMF119AP_TTTERMCODE_DESC('TERM CODE DESC')
SORT: SMF119TI_STACK
SMF119AP_TTRNAME
SMF119AP_TTSDATE
SMF119AP_TTSTIME
BREAK: SMF119AP_TTRNAME
CONNECTION
DATE TIME DATE TIME DURATION INBOUND OUTBOUND TERM
RESOURCE STARTED STARTED ENDED ENDED HH:MM:SS.SS BYTES BYTES CODE TERM CODE DESC
________ ________ ___________ ________ ___________ ___________ ______________ ______________ ____ _______________________
FTPTA5 03/21/09 14:04:06.81 03/21/09 14:04:07.46 0.65 257,537 3,052 61 CLIENT SENT RESET
FTPTA5 03/21/09 14:05:35.59 03/21/09 14:05:45.67 10.08 27,043 329 52 APPL ISSUED CLOSE
FTPTA5 03/21/09 14:12:13.81 03/21/09 14:12:14.51 0.70 257,537 3,052 61 CLIENT SENT RESET
FTPTA5 03/21/09 14:12:27.35 03/21/09 14:12:37.42 10.07 27,043 329 52 APPL ISSUED CLOSE
FTPTA5 03/21/09 15:30:34.96 03/21/09 15:30:35.64 0.68 257,537 3,052 61 CLIENT SENT RESET
FTPTA5 03/21/09 15:35:13.92 03/21/09 15:35:24.00 10.08 27,043 329 52 APPL ISSUED CLOSE
*** TOTAL FOR FTPTA5 ( 6 ITEMS) 32.26 853,740 10,143
...
OpenSSH SFTP Transfer Report from SMF 119-96 and 119-97 Records
In the first report, we read the SMF file and select just the type 119 subtype 96 "OpenSSH Server Transfer
Completion" records. We expand the operation codes from the SMF record into text descriptions, And we
reformat the four 1-byte binary IP values into the familiar character IP4 format. (You can see the IP formatting
code in member REC11996 of your Spectrum SMF copy library.)
The second report is similar. It uses the SMF 119 subtype 97 records ("OpenSSH Client Transfer Completion").
This shows the client transfer completion information.
Note that we specified lower case headings in thess reports (purely for style.)
INPUT: SMF11996
INCLUDEIF:
SMF119S96_RTY = 119 /* RECORD TYPE */
AND SMF119S96_STY = 96 /* RECORD SUB-TYPE */
COMPUTE: FSOPER(8) =
WHEN(SMF119S96_SSH_FSOPER = 1) ASSIGN('RMDIR ')
WHEN(SMF119S96_SSH_FSOPER = 2) ASSIGN('RM ')
WHEN(SMF119S96_SSH_FSOPER = 3) ASSIGN('RENAME')
WHEN(SMF119S96_SSH_FSOPER = 4) ASSIGN('GET ')
WHEN(SMF119S96_SSH_FSOPER = 5) ASSIGN('PUT ')
WHEN(SMF119S96_SSH_FSOPER = 6) ASSIGN('CHMOD ')
WHEN(SMF119S96_SSH_FSOPER = 7) ASSIGN('CHOWN ')
WHEN(SMF119S96_SSH_FSOPER = 8) ASSIGN('MKDIR ')
WHEN(SMF119S96_SSH_FSOPER = 9) ASSIGN('SYMLINK')
ELSE ASSIGN(#FORMAT(SMF119S96_SSH_FSOPER))
SORT:
SMF119S96_SSH_FSSDATE
SMF119S96_SSH_FSSTIME
SMF119S96_SID
COLUMNS:
SMF119S96_SSH_FSSDATE('Startdate')
SMF119S96_SSH_FSSTIME('Starttime')
SMF119S97_SSH_TI_ASNAME('Asname')
SMF119S96_SSH_TI_USERID('Userid')
FSOPER('Oper' 4)
SMF119S96_SSH_FSCMD('Cmd')
SMF119S96_SSH_FSSTAT('Stat')
SMF119S96_SSH_FSLIP('Lpcate IP')
SMF119S96_SSH_FSRIP('Remote IP')
SMF119S96_SSH_FSHOSTNAME('Host' 4)
SMF119S96_SSH_FSPATH1('Path1' 45)
Startdate Starttime Asname Userid Oper Cmd Stat Locate IP Remote IP Host Path1
_________ ___________ ________ ________ ____ ____ ____ _____________ _____________ ____ _______________________________________
01/03/11 07:00:19.21 TPADMIN6 TPADMIN get GET OK 55.66.77.88 11.22.33.44 sys2 /SYS2/tmp/payment_detail.SYS2
01/03/11 07:00:19.61 TPADMIN7 TPADMIN get GET OK 55.66.77.88 11.22.33.44 sys2 /SYS2/var/hkeeping/payment_history.SYS2
...
INCLUDEIF:
SMF119S97_RTY = 119 /* RECORD TYPE */
AND SMF119S97_STY = 97 /* RECORD SUB-TYPE */
SORT:
SMF119S97_SSH_FCSDATE
SMF119S97_SSH_FCSTIME
SMF119S97_SID
COLUMNS:
SMF119S97_SID('System')
SMF119S97_SSH_TI_ASNAME('Asname')
SMF119S97_SSH_TI_USERID('Userid')
*
SMF119S96_SSH_FSCMD('CMD')
SMF119S97_SSH_FCTTYPE('Type')
SMF119S97_SSH_FCMODE('Mode')
*
SMF119S97_SSH_FCSDATE('Begdate')
SMF119S97_SSH_FCSTIME('Begtime')
SMF119S97_SSH_FCDUR('Duration')
SMF119S97_SSH_FCBYTES('Bytes')
SMF119S97_SSH_FCSTAT('Stat')
SMF119S97_SSH_FCLIP('Local IP')
SMF119S97_SSH_FCLPORT('Lclport' 12 P'ZZZZZZ9')
SMF119S97_SSH_FCRIP('Remote IP')
SMF119S97_SSH_FCRPORT('Rmtport' 12 P'ZZZZZZ9')
*
SMF119S97_SSH_FCUSERID('Userid' 20)
SMF119S97_SSH_FCPATH('Path' 40)
System Asname Userid Cmd Type Mode Begdate Begtime Duration Bytes Stat Local IP Lclport Remote IP Rmtport Userid Path
______ ________ ________ ____ ____ ____ ________ ___________ ___________ _____ ____ ____________ _______ _______________ _______ ________ __________________________________________________
SYS1 VXATP70I PGASHC PUT A S 28/02/11 03:00:44.19 00:00:00.00 144 OK 11.22.33.2 36823 123.234.567.999 22 zutil2 /data/browse/tmp/LogFile-20110228-030042-83952264
SYS1 I4ATP70I PGAI4A PUT A S 28/02/11 03:14:30.93 00:00:00.01 144 OK 11.22.33.2 37744 123.234.567.999 22 zutil2 /data/browse/tmp/LogFile-20110228-031429-83953426
SYS2 VXATP70I PGASHC PUT A S 01/03/11 03:04:34.61 00:00:00.00 144 OK 11.22.33.6 32453 123.234.567.999 22 zutil2 /data/browse/tmp/LogFile-20110301-030432-67241185
SYS1 I4ATP70I PGAI4A PUT A S 01/03/11 03:05:54.57 00:00:00.00 144 OK 11.22.33.2 7441 123.234.567.999 22 zutil2 /data/browse/tmp/LogFile-20110301-030553-67175216
SYS2 VXATP70I PGASHC PUT A S 02/03/11 03:02:27.21 00:00:00.00 144 OK 11.22.33.6 45256 123.234.567.999 22 zutil2 /data/browse/tmp/LogFile-20110302-030224-84019194
SYS2 I4ATP70I PGAI4A PUT A S 02/03/11 03:21:33.48 00:00:00.00 144 OK 11.22.33.6 46235 123.234.567.999 22 zutil2 /data/browse/tmp/LogFile-20110302-032132-67240410
SYS2 VXATP70I PGASHC PUT A S 03/03/11 03:01:58.84 00:00:00.00 144 OK 11.22.33.6 58076 123.234.567.999 22 zutil2 /data/browse/tmp/LogFile-20110303-030155-50466520
SYS2 I4ATP70I PGAI4A PUT A S 03/03/11 03:13:10.92 00:00:00.00 144 OK 11.22.33.6 58652 123.234.567.999 22 zutil2 /data/browse/tmp/LogFile-20110303-031309-84017320
...
...
COMPUTE: MY_DATA_TYPE =
WHEN(SMF119FT_FSTYPE = 'A') ASSIGN('ASCII')
WHEN(SMF119FT_FSTYPE = 'E') ASSIGN('EBCDIC')
WHEN(SMF119FT_FSTYPE = 'I') ASSIGN('IMAGE')
WHEN(SMF119FT_FSTYPE = 'B') ASSIGN('DBL-BYTE')
WHEN(SMF119FT_FSTYPE = 'U') ASSIGN('UCS-2')
TITLE: 'Z/OS FTP FILE TRANSFER LOG - FROM SMF 119 (70) RECORDS'
TITLE: 'SYSTEM:' SMF119TI_SYSNAME
'SYSPLEX:' SMF119TI_SYSPLEXNAME
TITLE: 'SORTED BY TRANSFER START TIME'
COLUMNS: SMF119TI_STACK('STACK')
SMF119FT_FSCMD('CMND')
SMF119FT_FSDRIP_IPV4('REMOTE|IP')
SMF119FT_FSDLIP_IPV4('LOCAL|IP')
SMF119FT_FSSUSER('CLIENT|USERID')
MY_DATA_TYPE('DATA|TYPE')
SMF119FT_FSSTIME('TRANSFER|START|TIME')
SMF119FT_FSDUR(7 'TRANSFER|DURATION|(SECS)')
SMF119FT_FSBYTES('NUM|BYTES' 7 P'ZZ9.9 @B')
SMF119FT_FSFILENAME1_DISP(30 'DSNAME')
SORT: SMF119FT_FSSTIME
TRANSFER TRANSFER
REMOTE LOCAL CLIENT DATA START DURATION NUM
STACK CMND IP IP USERID TYPE TIME (SECS) BYTES DSNAME
________ ____ _______________ _______________ ________ ________ ___________ _______ _______ ______________________________
STXA81A STOR 100.59.162.15 100.62.110.26 C931169 ASCII 13:04:07.40 0.06 0.3 MB @TO.WH.P0.BATCHABS.NONE.D09082
STXA81A STOR 100.59.162.15 100.62.110.26 C931169 ASCII 13:05:38.64 0.06 0.3 MB @TO.WH.P0.BATCHABS.NONE.D09082
STXA81A STOR 100.59.162.15 100.62.110.26 C931169 ASCII 13:07:26.74 0.11 0.3 MB @TO.WH.P0.BATCHABS.NONE.D09082
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:24.81 0.00 30.0 KB PRD1.PO.M0143181.JAIS.#000002.
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:25.12 0.00 13.3 KB PRD1.PO.M0143181.JAIS.#000002.
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:28.89 0.01 71.3 KB PRD1.PO.M0143181.JAIS.#000002.
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:30.26 0.00 26.2 KB PRD1.PO.M0143181.JAIS.#000002.
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:31.01 0.01 36.8 KB PRD1.PO.M0143181.JAIS.#000002.
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:31.63 0.00 4.1 KB PRD1.PO.M0143181.JAIS.#000002.
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:31.99 0.00 6.2 KB PRD1.PO.M0143181.JAIS.#000002.
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:32.61 0.00 6.5 KB LMA.PRD1.PO.M0143181.JAIS.#000
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:08:33.66 0.00 1.5 KB LMA.PRD1.PO.M0143181.JAIS.#000
STXA81A STOR 100.59.162.15 100.62.110.26 C931169 ASCII 13:09:29.15 0.07 0.3 MB @TO.WH.P0.BATCHABS.NONE.D09082
STXA81A STOR 100.59.162.15 100.62.110.26 C931169 ASCII 13:10:27.04 0.05 0.3 MB @TO.WH.P0.BATCHABS.NONE.D09082
STXA81A STOR 100.59.162.15 100.62.110.26 C931169 ASCII 13:11:16.71 0.06 0.3 MB @TO.WH.P0.BATCHABS.CSS512.D090
STXA81A STOR 199.8.12.25 100.62.110.26 MCMX981 ASCII 13:11:28.90 0.01 0.1 MB PRD1.PO.S3230860.JAIS.#000003.
...
5 AWT4 AXZ4S1 Default AXZ4 AXZ44 Tonam::Inf invoke:java.lang.String,j 1 0.014 0.014 0.013665 0.013665 0.013665
5 AWT4 AXZ4S1 Default AXZ4 AXZ44 Tonam::Inf invoke:java.lang.String,j 1 0.020 0.020 0.006287 0.006287 0.006287
5 AWT4 AXZ4S1 Default AXZ4 AXZ44 Tonam::Inf login:java.lang.String,ja 1 0.006 0.006 0.004206 0.004206 0.004206
5 AWT4 AXZ4S1 Default AXZ4 AXZ44 Tonam::Inf invoke:java.lang.String,j 1 0.004 0.004 0.003605 0.003605 0.003605
5 AWT4 AXZ4S1 Default AXZ4 AXZ44 Tonam::Inf invoke:java.lang.String,j 1 0.007 0.007 0.004831 0.004831 0.004831
5 AWT4 AXZ4S1 Default AXZ4 AXZ44 Tonam::Inf invoke:java.lang.String,j 2 0.005 0.010 0.005650 0.001264 0.010036
COMPUTE: ACT_DUR =
#MAKETIME(#MAKENUM(SMF120WAG) - #MAKENUM(SMF120WAF))
7 00:00:01.50 AWX4 ATX4S1C 04:59:56.643606 04:59:56.676287 0.032681 ATX4 ATX44 /en_US/common/locale 0.000034
7 00:00:01.50 AWX4 ATX4S1C 04:59:56.643606 04:59:56.676287 0.032681 ATX4 ATX44 /en_US/common/recent 0.000030
7 00:00:01.50 AWX4 ATX4S1C 04:59:56.643606 04:59:56.676287 0.032681 ATX4 ATX44 /en_US/common/footer 0.000027
7 00:00:01.50 AWX4 ATX4S1C 04:59:56.643606 04:59:56.676287 0.032681 ATX4 ATX44 /en_US/common/header 0.000170
7 00:00:01.50 AWX4 ATX4S1C 04:59:56.643606 04:59:56.676287 0.032681 ATX4 ATX44 /en_US/cp/TPAInvesti 0.028294
7 00:00:01.50 AWX4 ATX4S1C 04:59:56.643606 04:59:56.676287 0.032681 ATX4 ATX44 ActionServlet 0.029511
7 00:00:06.50 AWX4 ATX4S1C 05:00:03.649787 05:00:04.446123 0.796336 ATX4 ATX44 1 /acessLogon.jsp 0.214795
7 00:00:11.51 AWX4 ATX4S1C 05:00:07.361743 05:00:07.370785 0.009042 ATX4 ATX44 /userhome.jsp 0.005556
7 00:00:16.51 AWX4 ATX4S1C 05:00:11.728713 05:00:11.759218 0.030505 ATX4 ATX44 /en_US/common/locale 0.000034
7 00:00:16.51 AWX4 ATX4S1C 05:00:11.728713 05:00:11.759218 0.030505 ATX4 ATX44 /en_US/common/recent 0.000032
7 00:00:16.51 AWX4 ATX4S1C 05:00:11.728713 05:00:11.759218 0.030505 ATX4 ATX44 /en_US/cp/TPAInvesti 0.025579
7 00:00:16.51 AWX4 ATX4S1C 05:00:11.728713 05:00:11.759218 0.030505 ATX4 ATX44 /en_US/common/footer 0.000028
7 00:00:16.51 AWX4 ATX4S1C 05:00:11.728713 05:00:11.759218 0.030505 ATX4 ATX44 /en_US/common/header 0.000176
7 00:00:16.51 AWX4 ATX4S1C 05:00:11.728713 05:00:11.759218 0.030505 ATX4 ATX44 ActionServlet 0.026826
7 00:00:16.51 AWX4 ATX4S1C 05:00:14.025154 05:00:14.033578 0.008424 ATX4 ATX44 /en_US/common/locale 0.000033
7 00:00:16.51 AWX4 ATX4S1C 05:00:14.025154 05:00:14.033578 0.008424 ATX4 ATX44 /en_US/common/recent 0.000031
7 00:00:16.51 AWX4 ATX4S1C 05:00:14.025154 05:00:14.033578 0.008424 ATX4 ATX44 /en_US/common/footer 0.000028
7 00:00:16.51 AWX4 ATX4S1C 05:00:14.025154 05:00:14.033578 0.008424 ATX4 ATX44 /en_US/common/header 0.000172
...
*** GRAND TOTAL ( 20 ITEMS)
140 1.235038 1
The difficulty with this report is that the program name is not included in the SMF 16 record. To get the program
name in our report, we must find an SMF 30 step termination record for the same job step that produced the SMF
16 DFSORT statistics record. The SMF 30 record will include the name of the program.
That is a bit of a challenge 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.
The first step selects two types of records. All SMF 16 records with the "program" bit on. And all SMF 30 subtype
4 (step termination records). 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" on this JOBID field. That sorts the SMF 16 and SMF 30 records for the same
job together. Our secondary sort is on SMF record type (descending). That ensures that for jobs with both a 16 and
a 30 record, the 30 record will come first. Now, instead of printing a report in this step, we actually output these
sorted SMF records intact. We write these selected and sorted SMF records out to a temporary dataset.
Now we run the second Spectrum SMF Writer step. It reads the sorted SMF 16 and 30 records from our temporary
dataset. We are only going to select the SMF 16 records for our report. (We know that any SMF 16 record in this
file has the "program" bit on, since we tested for that in the first step.) For each SMF 16 record, we will write one
line to our report.
However, we still need to obtain the name of the program that invoked the sort. That program name will be in the
matching SMF 30 record that was read just before the corresponding SMF 16 record. So we need a way to save
that program name from the SMF 30 records as they are read (and then excluded from the report). We save the
program name in a field named SAVE_PGMNAME so that it remains available when we read the matching SMF
16 record that follows. We can then use this saved program name along with all of the SMF 16 record's fields to
print our report line.
The special RETAIN parm of the COMPUTE statement is what enables us to save this program name from the
SMF 30 record as it passes by.
As each SMF record is read, a vaslue is assigned to the SAVE_PGMNAME compute field. When the record is
type 30, we assign the value of that SMF 30 record's program name field (SMF30PGM). (However, we do not
include this SMF 30 record in the report.) When the record is not 30 (meaning that it must be type 16), we do not
assign a new value to the 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 this SMF 16 record in our report. And now we also have the retained program name (from the
previous type 30 record) available to include in the report line, along with all of the fields from the SMF 16 record.
*====================================================================
* DEFINE ONE FILE WHICH HAS THE FIELDS FROM BOTH COPYBOOKS.
*====================================================================
FILE: SMFIN LRECL(32767) DDNAME(SMFIN) KEEPRDW
COPY: REC30
COPY: REC16
INPUT: SMFIN
FIELD: RECORD COL(1) LEN(32000)
*
*====================================================================
* MAKE A UNIQUE JOBID FIELD, USING JOBNAME, READER TIMESTAMP, STEPNUM
*====================================================================
COMPUTE: JOBID = /* MAKE UNIQUE, CHAR-FORMAT JOBID */
WHEN(SMF30RTY = 30)
ASSIGN(SMF30JBN
+ #FORMAT(SMF30RSD, YYYY-MM-DD)
+ #FORMAT(SMF30RST, HH-MM-SS)
+ #FORMAT(SMF30STN, PIC'999') )
WHEN(SMF16RTY = 16)
ASSIGN(SMF16_ICEJOBNM
+ #FORMAT(SMF16_ICERDS, YYYY-MM-DD)
+ #FORMAT(SMF16_ICERST, HH-MM-SS)
+ #FORMAT(SMF16_ICESTN, PIC'999') )
*====================================================================
* EXTRACT JUST THE "PROGRAM" BIT FROM A FLAG FIELD
*====================================================================
COMPUTE: PGMBIT = #SUBSTR(#FORMAT(SMF16_ICEFLBYT,BITS),6,1)
*
*====================================================================
* INCLUDE ALL 30-4 RECORDS, AND 16 RECORD WITH THE PROGRAM BIT ON
*====================================================================
INCLUDEIF: (SMF30RTY=30 AND SMF30STP = 4) /* SMF 30 STEP TERM RECS */
OR (SMF16RTY=16 AND PGMBIT='1') /* SMF 16 W/ PGM BIT */
*
*====================================================================
* OUTPUT IS JUST THE WHOLE RECORD (AS MUCH OF IT AS WE NEED)
*====================================================================
COLUMNS: RECORD /* COPY THE WHOLE 30 OR 16 RECORD */
*
*====================================================================
* SORT SO THAT THE 16 AND 30 RECS FOR THE SAME JOB/STEP ARE TOGETHER.
* WE WANT THE 30 RECORD TO COME BEFORE ITS MATCHING 16 RECORD.
*====================================================================
SORT: JOBID SMF30RTY(DESC)
*
(continued)
INPUT: SMFIN
COMPUTE: SAVE_PGMNAME =
WHEN(SMF30RTY=30 AND SMF30STP=4) ASSIGN(SMF30PGM)
ELSE RETAIN /* IF NOT 30 RECORD, RETAIN OLD VALUE */
*
*=================================================================
* WE INCLUDE ONLY SMF 16 RECS IN THE REPORT. BUT WE HAVE SAVED
* THE JOBID AND PGMNAME FROM ITS MATCHING 30 REC (IF IT APPEARED
* JUST BEFORE THIS 16 RECORD, LIKE IT SHOULD.)
*=================================================================
INCLUDEIF: SMF16RTY=16 /* WE KNOW THE PROGRAM BIT IS ON */
AND JOBID = SAVE_JOBID30 /*INCL 16 IF FOUND MATCHING 30*/
*
*=================================================================
* NOW WE CAN PRINT THE REPORT USING ALL FIELDS IN SMF 16, PLUS THE
* PGMNAME THAT WE SAVED FROM THE PREVIOUS (MATCHING) 30 REC.
*=================================================================
COMPUTE: E15BIT = #SUBSTR(#FORMAT(SMF16_ICEIOTYP,BITS),1,1)
COMPUTE: E32BIT = #SUBSTR(#FORMAT(SMF16_ICEIOTYP,BITS),2,1)
COMPUTE: E35BIT = #SUBSTR(#FORMAT(SMF16_ICEIOTYP,BITS),3,1)
COMPUTE: PGMBIT = #SUBSTR(#FORMAT(SMF16_ICEFLBYT,BITS),6,1)
*
COLUMNS: SMF16SID('SYSTEM|ID')
SMF16RTY('SMF|REC|TYPE' 4)
SMF16_ICERDS('READER|START|DATE')
SMF16_ICERST('READER|START|TIME')
SMF16_ICEIOTYP(BITS)
E15BIT
E32BIT
E35BIT
SMF16_ICEFLBYT(BITS)
PGMBIT
SMF16_ICEJOBNM('JOBNAME')
SAVE_PGMNAME('INVOKING|PROGRAM')
continued
************************************************************************
* REPORT TITLES *
*(SLASHES SEPARATE THE LEFT (EMPTY HERE), CENTER AND RIGHT TITLE PARTS)*
************************************************************************
TITLE: / 'DFSORT INFORMATION FOR SORTS INVOKED BY A PROGRAM'
/ 'RUN DATE:' #DATE
Index
Symbols B
#DATE built-in field 24 Batch
#DAYNAME built-in field 25 job 5
#HHMMSS built-in field 25 Big
#JOBNAME built-in field 25 making a column bigger 30
#PAGENUM built-in field 24, 25 Bits
use in TITLE statement 24 bit fields 11, 42
#PARSE built-in function 36 displaying data as bits 28
#REPLACE built-in function 36 BIZ parm
#TIME built-in field 25 in COLUMNS statement 30, 84
#TIME24 built-in field 25 Blank lines
#TODAY built-in field 24 printing after the total line 47
@ symbol Blanks
meaning in PICTURE 84, 100 required around minus sign 33
showing zeros as blanks 30, 84
BREAK statement 47
control break spacing 47
A order of 51
Abends page breaks 47, 84
reporting on 40, 73 printing averages at control breaks 54
ACCUM parm printing control group footings 54
in COLUMNS statement 30 printing control group headings 54
in FIELD statement 30 printing statistical lines at control breaks 54
Alignment where to put 51
of titles (left, center and right) 25 Buffer
Alphabetizing buffer pool report 95
the report 45 Built-in fields
Ampersand available in TITLE and FOOTNOTE statements 24
meaning in PICTURE 84, 100 Built-in functions
AND available in COMPUTE statement 37
in conditional expressions 62
Ascending
order, in SORT statement 47
Assembler C
record layouts 10 Centering
ASSIGN parm titles 25
in COMPUTE statement 40 Character fields
Audit built-in functions 37
DB2 audit report 60 creating your own 36
AVERAGE (AVG) parm Character operations 36
in BREAK statement 54 Chargeback
in COLUMNS statement 30 sample report 79
Averages CICS
how to print 54 monitoring records 92
which columns receive 30 performance report 91
regions 68
Literals
I in report body 11
I/O in titles 24
reducing I/O time 14 rules for writing 62
If logic 40 Local IP
IFC FTP transfer report 100
destination report 89 Logical
INCLUDEIF statement 7 input records 18
for multiple reports 14 Logical operations 62
which fields allowed in 9 LPAR section
INPUT statement 7, 16 in SMF 70 record 22, 56
stop reading early 11
International
formatting conventions 31
IOEXIT parm M
in INPUT statement 21 Math
IP operations 33
formatting 98 Maximum
Item count records read from input file 11
in total lines 10 value in control group, printing 54
which columns receive 30
MAXIMUM (MAX) parm
in BREAK statement 54
J in COLUMNS statement 30
J2EE Microsoft Excel
report 101 example 12, 13
Java Midnight
CPU time report 101 elapsed times that cross 35
java bean 101 Minimum
JCL value in control group, printing 54
DD for output 14 which columns receive 30
SWOPTION DD 31 MINIMUM (MIN) parm
to run Spectrum SMf Writer 103 in BREAK statement 54
Jobname 25 in COLUMNS statement 30
Julian dates 63 Minus sign (-)
Justification blanks required around 33
of titles (left, center and right) 25 Missing data 17
Months
abbrevations 27
spelling out name 27
L MQ
Websphere MQ queue report 96
Left alignment
Multiple
of titles 25
control breaks 51
Length
input files 60
variable, sections with 21
jobsteps to produce report 103
Limiting
nested triplets 22
records read from input file 11
NORMSMF or NORMALIZE parms 22
Lines
report lines per record 11
multiple report lines per record 11
reports per run 14, 68
Listing
SMF record types in same report 42, 103
of fields in a file 10
U
Uptime
report 65
User-defined fields 33
V
Variable
length sections in SMF records 21
VSAM
file activity report 83
W
WebContainer
servlet report 102
Websphere MQ
J2EE report 101
queue report 96
Week
day of 25
WHEN parm
in COMPUTE statement 40
Width
of column, changing 30
of report 11