[Bio] / FigWebServices / Emergency.cgi Repository:
ViewVC logotype

Diff of /FigWebServices/Emergency.cgi

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.13, Mon Feb 18 07:04:15 2008 UTC revision 1.14, Wed Feb 27 01:54:08 2008 UTC
# Line 1  Line 1 
1  #!/usr/bin/perl -w  #!/usr/bin/perl -w
2    
3  BEGIN {  use strict;
4      # Print the HTML header.  use Tracer;
5      print "CONTENT-TYPE: text/html\n\n";  use CGI;
6  }  use CGI::Cookie;
7    use DocUtils;
8    use FIG_Config;
9    
10  =head1 Emergency Tracing  =head1 Emergency Tracing
11    
12  This script manages emergency tracing. Emergency tracing is controlled  This script configures emergency tracing and displays the trace file. Emergency tracing
13  by a file in the FIG temporary directory containing trace information.  is used to debug web and command-line applications. A cookie is stored on the user's
14  It enables developers to turn on tracing without the cumbersome  computer that the web applications use to determine what to trace and where to put the
15  requirement for adding parameters to the URL. This method does not do  messages. This script is generally run from the Debug Console in the NMPDR Wiki, where
16  the tracing, it merely sets up data structures that allow tracing to take  you can find further documentation and examples.
 place without explicit authorization from form or command-line parameters.  
17    
18  This script supports the following CGI query parameters.  The following CGI parameters are used.
19    
20  =over 4  =over 4
21    
22  =item Trace  =item action
   
 Trace level and list of trace modules to turn on, space-delimited. The  
 default is no tracing.  
   
 =item Level  
23    
24  Level at which to turn on emergency tracing, generally a number from 0 through 4.  Command to execute. C<Activate> will activate tracing and clear the temporary file (if any).
25    C<Terminate> to turn tracing off, and C<Show> will display the trace messages.
26    
27  =item Packages[]  =item key
28    
29  A list of trace packages to activate. This parameter can be multiply-occurring, or  The tracing key (C<key>). This is usually the user's login name (and defaults to that
30  you can pass in a set of package names separated by spaces.  value).
31    
32  =item TType  =item level
33    
34  Type of tracing to use: C<WARN> to trace to the server error log, C<QUEUE> to  The trace level. The higher the trace level, the more messages will appear. This parameter
35  queue output to the web page, C<FILE> to write to a temporary file, or  is used for the C<Activate> action only.
 C<APPEND> to append to a temporary file.  
36    
37  =item Hours  =item packages[]
38    
39  Number of hours to leave emergency tracing active. Note that for web services,  An array of tracing modules to turn on. Most tracing is configured using the lowest-level
40  tracing will turn off automatically at the end of the web session when the  name of the package containing the trace message, but there are some special names defined as well.
41  cookie is erased.  This parameter is used for the C<Activate> action only.
42    
43  =item Activate  =item destination
44    
45  If specified, emergency tracing is turned on and any existing trace file  Tracing destination. C<FILE> to write to a temporary file, or C<APPEND> to append to a temporary file.
46  will be deleted.  This parameter is used for the C<Activate> action only.
47    
48  =item Terminate  =item hours
49    
50  If specified, emergency tracing is turned off.  The number of hours to leave tracing active (C<hours>). This parameter is used for the C<Activate>
51    action only.
52    
53  =item ShowFile  =item timeSlice
54    
55  If specified, the trace file is displayed in the output.  The number of minutes to display in the trace file, or 0 to display the whole
56    trace file. This parameter is used for the C<Show> action only.
 =item  
57    
58  =back  =back
59    
60  =cut  =cut
61    
62  use strict;  # Denote we have not yet started the output page. We need to know this when recovering
63  use Tracer;  # from errors.
64  use CGI;  my $PageStarted = 0;
65  use File::stat;  # Get the CGI query object.
66  use Time::Local;  my $cgi = CGI->new();
67    # Insure we recover from errors.
   
 my ($cgi, $varHash) = ScriptSetup('noTrace');  
68  eval {  eval {
69      # Only proceed if debug mode is on. We don't want normal users doing this.      # Get the tracing key.
70      if (Tracer::DebugMode) {      my $key = $cgi->param('key') || "";
71          # Get the tracing key. This determines the file names.      if (! $key) {
72          my $tkey = EmergencyKey($cgi);          die "No tracing key specified.";
73          # Get the emergency file name itself.      }
74          my $efileName = Tracer::EmergencyFileName($tkey);      # Get the action to take.
75          # Determine what the user wants us to do.      my $action = $cgi->param('action') || 'Show';
76          if ($cgi->param('Terminate')) {      # Get the emergency file name.
77              # Here we are supposed to turn off emergency tracing.      my $efileName = Tracer::EmergencyFileName($key);
78              unlink $efileName;      # Process the action.
79              $varHash->{results} = $cgi->p("Emergency tracing key $tkey turned off.");      if ($action eq 'Activate') {
80          } elsif ($cgi->param('ShowFile')) {          # Get the package list. Note that part of our package list may come in as
81              # Here the user wants to display the emergency tracing file.          # a comma- or space-delimited string, so we split the individual parameters up.
82              my $traceFileName = Tracer::EmergencyFileTarget($tkey);          my @packages = map { split(/\s*[\s,]\s*/, $_) } $cgi->param('packages');
83              # Create the header for a failure situation.          # Get the other parameters. Note we have defaults for everything.
84              my $problem = $cgi->h3("Tracing Data Not Available");          my $level = $cgi->param('level') || 0;
85              # Check to see if there's a problem with the trace file.          my $destination = $cgi->param('destination') || 'FILE';
86              if (! -e $traceFileName) {          my $hours = $cgi->param('hours') || 4;
87                  $varHash->{results} = $problem .          # Create a cookie so that the tracing key can be retrieved by other scripts.
88                                        $cgi->p("Trace file $traceFileName does not exist.") .          my $cookie = CGI::Cookie->new(-name => 'IP', -value => $key, -path => '/');
89                                        $cgi->p("Either emergency tracing is not turned on or it " .          # Start the output page.
90                                                "not being sent to a file.");          StartPage("Activate Tracing for $key", [$cookie]);
91              } elsif (-z $traceFileName) {          # If there's already a trace file, delete it.
92                  $varHash->{results} = $problem .          my $traceFileName = Tracer::EmergencyFileTarget($key);
                                       $cgi->p("The trace file $traceFileName is empty.");  
             } else {  
                 # Here we know we can read from the file. Start by opening it.  
                 my $handle = Open(undef, $traceFileName);  
                 # Get the first line of the file.  
                 my $line = <$handle>;  
                 # Now we need to determine what part of the file to read.  
                 my $timeSlice = $cgi->param('TimeSlice') || 0;  
                 if ($timeSlice) {  
                     # Here we want to skip to a certain number of minutes in the past.  
                     # Compute that time from the file's last-modified timestamp. Note that  
                     # we add, since the timeSlice variable contains a negative number  
                     # of minutes.  
                     my $fileStats = stat $handle;  
                     my @localFileTime = localtime($fileStats->mtime);  
                     my $startTime = timelocal(@localFileTime) + $timeSlice * 60;  
                     # Loop until we find a recent enough time.  
                     my $done = 0;  
                     while (defined($line) && ! $done) {  
                         # Get the time from the current line. Note that if we have a data  
                         # line, the match will fail and we'll keep going.  
                         if ($line =~ /^\[([^\]]+)\]/) {  
                             my $thenTime = Tracer::ParseTraceDate($1);  
                             if ($thenTime >= $startTime) {  
                                 $done = 1;  
                             }  
                         }  
                         if (! $done) {  
                             $line = <$handle>;  
                         }  
                     }  
                 }  
                 # Now we can begin displaying the file. Start a table.  
                 $varHash->{results} = "<table border=\"2\"><tr><th>Time</th><th>Module</th><th>Message</th></tr>\n";  
                 # Denote we're starting the output.  
                 my $traceMode = 2;  
                 # Read the whole file from the current position. Note that a line  
                 # is already in the buffer from the above effort.  
                 while (defined($line)) {  
                     # Process the current line.  
                     $traceMode = ProcessLine($line, $traceMode);  
                     # Get the next line.  
                     $line = <$handle>;  
                 }  
                 # Close the final line.  
                 $varHash->{results} .= CloseLine($traceMode);  
                 # Close the table.  
                 $varHash->{results} .= $cgi->end_table();  
             }  
         } elsif ($cgi->param('Activate')) {  
             # Here we want to turn on emergency tracing. First, we get the  
             # packages. Note we split any space-delimited package lists.  
             my @packages = map { split(/\s*[\s,]\s*/, $_) } $cgi->param('Packages');  
             # Get the other parameters.  
             my $level = $cgi->param('Level');  
             my $dest = $cgi->param('TType');  
             my $hours = $cgi->param('Hours');  
             # Clear the current trace file (if any).  
             my $traceFileName = Tracer::EmergencyFileTarget($tkey);  
93              if (-f $traceFileName) {              if (-f $traceFileName) {
94                  unlink $traceFileName;                  unlink $traceFileName;
95                print $cgi->p("$traceFileName deleted.") . "\n";
96              }              }
97              # Turn on emergency tracing.              # Turn on emergency tracing.
98              Emergency($tkey, $hours, $dest, $level, @packages);          Emergency($key, $hours, $destination, $level, @packages);
99              # Denote the fact.          # Tell the user about it.
100              $varHash->{results} = $cgi->h3("Emergency Tracing Activated") .          print join("\n",$cgi->p("Destination is " . Tracer::EmergencyTracingDest($key, $destination) . "."),
101                                    $cgi->p("Destination is " . Tracer::EmergencyTracingDest($tkey, $dest) . ".") .                          $cgi->p("Duration is $hours hours (or end of session)."),
102                                    $cgi->p("Duration is $hours hours (or end of session).") .                          $cgi->p("Trace level is $level."),
103                                    $cgi->p("Use <code>export Tracing=$tkey</code> " .                          $cgi->p("Modules activated:"),
104                                            "to activate tracing in command-line mode.") .                          $cgi->ul(map { $cgi->li($_) } @packages),
105                                    $cgi->p("Trace level is $level.") .                          "");
106                                    $cgi->p("Modules activated:") .      } elsif ($action eq 'Terminate') {
107                                    $cgi->ul(map { $cgi->li($_) } @packages);          # Turn off tracing. We do this by deleting the tracing key file.
108            TWiki::Plugins::NmpdrPlugin::StartPage("Tracing Terminated for $key", []);
109            if (-f $efileName) {
110                unlink $efileName;
111                print FormatStatus("Tracing key file deleted.");
112            } else {
113                FormatError("Tracing was already turned off.");
114          }          }
115        } elsif ($action eq 'Show') {
116            # Get the trace file name.
117            my $traceFileName = Tracer::EmergencyFileTarget($key);
118            StartPage("Tracing Data for $key", []);
119            FormatStatus("Tracing data from $traceFileName");
120            # See if tracing is turned on.
121            if (! -f $traceFileName) {
122                FormatStatus("No trace file found for $key.");
123            } elsif (! -s $traceFileName) {
124                FormatStatus("The trace file for $key is empty.");
125            } else {
126                # Here we have a file to read. Get the amount of time to display.
127                my $timeSlice = $cgi->param('timeSlice');
128                # Display the trace file.
129                DocUtils::ShowTraceFile($timeSlice, $traceFileName);
130            }
131        } else {
132            # Here we have an unknown command.
133            StartPage("Tracing Console Error", []);
134            FormatError("Unknown tracing command $action.");
135      }      }
136  };  };
137    
138  if ($@) {  if ($@) {
139      my $errorMessage = $@;      # Here we have a fatal error. Save the message.
140      Trace("Script Error: $errorMessage") if T(0);      my $errorText = $@;
141      $varHash->{results} = $cgi->h3("Script Error: $errorMessage");      # Insure we have a page to which we can write.
142        if (! $PageStarted) {
143            StartPage("Tracing Console Error", []);
144        }
145        # Output the error message.
146        FormatError("CONSOLE ERROR: $errorText");
147    }
148    # If we have an output page in progress, close it.
149    if ($PageStarted) {
150        print CGI::end_html();
151  }  }
 ScriptFinish("Html/Basic_tmpl.html", $varHash);  
152    
153  =head3 CloseLine  1;
154    
155      my $html = CloseLine($traceMode);  =head2 Utility Methods
156    
157  Close off the current output line for the trace file display.  =head3 FormatError
158    
159  =over 4      FormatError($message);
160    
161  =item traceMode  Format an output message as an error. Error messages are shown as block
162    quotes, which makes them stand out very violently.
163    
164  C<1> if we are processing trace lines, C<0> if we are processing text lines,  =over 4
 C<2> if we are between rows of the table.  
165    
166  =item RETURN  =item message
167    
168  Returns the HTML for closing off the current line.  Error message to output.
169    
170  =back  =back
171    
172  =cut  =cut
173    
174  sub CloseLine {  sub FormatError {
175      # Get the parameters.      # Get the parameters.
176      my ($traceMode) = @_;      my ($message) = @_;
177      # Declare the return variable.      # Write the error message.
178      my $retVal = "";      print CGI::blockquote($message) . "\n";
     # Only proceed if we're NOT in start mode. In start mode, the previous line's  
     # already closed.  
     if ($traceMode != 2) {  
         # If we're in line mode, close the pre-formatted section.  
         if (! $traceMode) {  
             $retVal .= "\n</PRE>";  
         }  
         # Close the trace row.  
         $retVal .= "</td></tr>\n";  
     }  
     # Return the result.  
     return $retVal;  
179  }  }
180    
181  =head3 ProcessLine  =head3 FormatStatus
182    
183      my $newTraceMode = ProcessLine($line, $traceMode);      FormatStatus($message);
184    
185  Process and display a line from the trace file.  Format an output message as a status line. Status lines are shown as
186    ordinary paragraphs.
187    
188  =over 4  =over 4
189    
190  =item line  =item message
191    
192    Status message to output.
193    
194  The line to display. This may be either a trace line, with date, module name,  =back
195  and message, or a data line, with just plain data.  
196    =cut
197    
198    sub FormatStatus{
199        # Get the parameters.
200        my ($message) = @_;
201        # Write the status message.
202        print CGI::p($message) . "\n";
203    }
204    
 =item traceMode  
205    
206  The current display mode: C<0> is line mode, meaning we have been writing data  =head3 StartPage
 lines. C<1> is trace mode, meaning we have been writing trace lines. C<2> is start  
 mode, meaning we are between rows. The importance here is that the display mode  
 tells us what we did with the previous line, and determine how we will separate  
 the new line from the old one. A trace line represents a table row, while a data  
 line is part of the previous trace line's message. See also L</CloseLine>.  
207    
208  =item RETURN      StartPage($title, $cookies);
209    
210  Returns C<0> if the incoming line was a data line and C<1> if it was a trace  Start an Html page. This method is used by the console methods to produce
211  line. This value should be used as the I<traceMode> value for the next call.  the HTTP and HTML headers.
212    
213    =over 4
214    
215    =item title
216    
217    Title for the page.
218    
219    =item cookies
220    
221    Reference to a list of cookies to set.
222    
223  =back  =back
224    
225  =cut  =cut
226    
227  sub ProcessLine {  sub StartPage {
228      # Get the parameters.      # Get the parameters.
229      my ($line, $traceMode) = @_;      my ($title, $cookies) = @_;
230      # Parse the new line.      # Write the HTTP header.
231      if ($line =~ /^\[([0-9:\/ ]+)\]\s+<(.+)>:\s+(.+)$/) {      print CGI::header(-cookie => $cookies);
232          # This is a trace line. Get the three pieces.      # Write the HTML header.
233          my ($time, $module, $message) = ($1, $2, $3);      print CGI::start_html(-title => $title,
234          # Now close off any data in progress.                            -style => { src => "$FIG_Config::cgi_url/Html/css/WikiConsole.css" });
235          $varHash->{results} .= CloseLine($traceMode);      # Echo the title as a body heading.
236          # Trace this line.      print CGI::h1($title) . "\n";
237          $varHash->{results} .= "<tr><td>$time</td><td>$module</td><td>" . $cgi->escapeHTML($message);      # Denote we've started the page.
238          # Denote we're in trace mode.      $PageStarted = 1;
         $traceMode = 1;  
     } else {  
         # Here we have a data line. If we're in trace mode, we start  
         # a line block and set the mode. In start mode, we have to  
         # create two blank colums.  
         if ($traceMode) {  
             if ($traceMode == 2) {  
                 $varHash->{results} .= "<tr><td>&nbsp;</td><td>&nbsp;</td><td>";  
             }  
             $varHash->{results} .= "<br /><pre>\n";  
             $traceMode = 0;  
         }  
         # Display the line. Note we include the new-line code at the end,  
         # which the regular expression match does automatically for trace-mode  
         # lines. This is because here we're preformatted.  
         $varHash->{results} .= $cgi->escapeHTML($line);  
     }  
     # Return the new trace mode.  
     return $traceMode;  
239  }  }
240    
241    
242  1;  
243    

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3