<h1>Logprocessor</h1>

<h3>Purpose</h3>
With logpro you can write command files to rigorously analyze log files. For example you may have a complex simulation with many steps, compilation, simulation, analysis, clean up etc. You want to know in an automated way if the simulation ran. Manually reading the log file(s) once or twice searching for errors, warnings and messages is fine but by the third or forth time you want to automate it. Logpro can help.

<h3>[Download]</h3>

<h3>Usage</h3>

Running logpro. EXAMPLE: Run the program "runsim" passing the output through logpro using the cmdfile.logpro log analysis command file. The annotated log file is written to "run.html" and run-logro.log.

<verbatim>
% runsim | logpro cmdfile.logpro run.html > run-logpro.log
</verbatim>

Or put the log into a file and postprocess:

<verbatim>
% runsim > runsim.log
% logpro cmdfile.logpro run.html < runsim.log > run-logpro.log
</verbatim>

In a Makefile:
<verbatim>
simlog.html : cpu.v
       verilog cpu.v | logpro cpu.logpro simlog.html
</verbatim>

The benefit in using logpro calls in a Makefile is that the exit code can be trusted to reflect the pass/fail status correctly. See the (which operates on and produces in the source repository)

<h3>Exit Codes</h3>
<table border=1>
<tr><td>Expect Type</td><td>Exit
<tr><td>All ok</td>  <td>0</td><td>No "errors" or "warnings" found and all "requireds"
<tr><td>ERROR</td>   <td>1</td><td>One or more expect errors matched or a required or waive check did NOT get
<tr><td>WARNING</td> <td>2</td><td>One or more warn rules
<tr><td>CHECK</td>   <td>3</td><td>A check rule
<tr><td>WAIVE</td>   <td>4</td><td>A waive rule
<tr><td>ABORT</td>  <td>5</td><td>An abort rule matched</td><tr>
<tr><td>SKIP</td>      <td>6</td><td>A skip rule
<tr><td>Reserved for future use</td> <td> &gt; 7
</table>

<h3>[Installation]</h3>

<h3>Command file details</h3>
Your command file is written in scheme but don't let that scare you. Only a handful of single line rules are needed to write a rock solid log analyzer. Here is an [example command file] and the [logpro output] from running against this [example log file]

More examples can be seen in the example.logpro file in the source directory and [examples]

<h3>Syntax</h3>

Triggers:
<verbatim>
( trigger "trigger name" #/trigger pattern/ )
</verbatim>
  #  The "trigger name" can be any string
  #  The trigger pattern is a perl compatible regular expression
  #  Triggers are required once defined. Not hitting the trigger is an error. Use trigger:non-required for triggers that may or may not be hit

Sections:
<verbatim>
( section "section name" "start trigger" "end trigger" )
</verbatim>
  #  The "section name" is a string.
  #  The "start trigger" and "end trigger" are strings that match the name of a trigger

Expect rules:
<verbatim>
( expect:required [in|not-in] "section name" [> or < or =] integer  #/regular expression/ )
</verbatim>
  #  Types of expect include: expect:required, expect:ignore, expect:warn, expect:error and expect:waive

<h3>Sections</h3>
You can break your log file into sections to make applying the rules very specific. For example you may want to only apply a set of rules in the compile section of the log file related to compiler failures.

Example: Create a section called "Init" that only applies between a line containing the string "This is a header" and a blank line. The lines match on regular expressions delimited by #/ and /.

<verbatim>
(trigger "Init"     #/This is a header/)
(trigger "InitEnd"
(section "Init" "Init" "InitEnd")
</verbatim>

By default Logpro provides a section "LogFileBody" that covers the entire log file. This example illustrates how you can create sections that start at the beginning or end of a log file. To match the beginning we use a regex that matches anything. To match the end simply use a trigger name that has no specification.

<verbatim>
(trigger "Body"     ;; anything starts the body
(section "Body"     "Body" "EndBody")  ;; EndBody trigger is not defined
</verbatim>

Some sections may occur multiple times in a file. Use trigger-with-limit for those. Use a large number if you don't know how many times the trigger may be hit.

<verbatim>
(trigger-with-limit "Blah5"    100 #/^begin Blah5/)
(trigger-with-limit "Blah5End" 100 #/^end Blah5/)
(section "Blah5" "Blah5" "Blah5End")
</verbatim>

<h3>Required Expects</h3>

There will be some lines in your log file that, if missing, indicate a problem. Create required expects for those:

<verbatim>
;; If we don't get a header then we know something went badly wrong
(expect:required in "Init"  = 1 "Header"      #/This is a header/)
</verbatim>

<h3>Catch and ignore errors</h3>

The rules are applied in the order they are specified in the command file. Once a rule is hit in the log file no other rules are tested. You can use this to create a catch all and then add exceptions. In this example ERROR 244 is false and should not be flagged as an error. The expect:ignore rule will match and so the expect:error rule never gets triggered.

<verbatim>
(expect:ignore   in "Body" = 1 "FALSE ERROR" #/ERROR 244/)
(expect:error    in "Body"  = 0 "ERROR BLAH"  ;; disallow errors
</verbatim>

<h3>Expire rules</h3>

Any rule can have a date set beyond which it will no longer be applied. This is intended to be used on ignore rules that are only intended to be temporarily applied. The date format is

<verbatim>
(expect:ignore in "Body" < 99 "These are real but I want to ignore them for now" #/ERROR 1234/ expires:
</verbatim>

This kind of rule is often best written as "< N" where N is more than you are ever likely to get of these that you want to ignore.

<h3>Values</h3>

Extract values from your logfile and apply simple rules for pass/fail checks.

Syntax is:

<verbatim>
(expect:value   in section  value  tol  comment_string regex [hook: hookname])
</verbatim>

Example, extract a number following a string "Measured voltage output: " and compare it with 1.9 +/- 0.1. Call the hook "freq"

<verbatim>
(expect:value    in "LogFileBody" 1.9 0.1 "Output voltage" #/Measured voltage hook: "freq")
</verbatim>

Example, extract two numbers from a string, the second number must be greater than 1.9:

<verbatim>
(expect:value    in "LogFileBody" 1.9 >   "Time voltage" #/out: matchnum: 2)
</verbatim>

More values handling techniques [More Values Techniques|here]

<h3>Hooks</h3>

Create a hook to handle the information gathered on a frequency measurement:

<verbatim>
(hook:add "freq"    "echo \"Value hook activated: expected=#{expected}, measured=#{measured}, tolerance=#{tolerance}, message=#{message}\"")
</verbatim>