Previous Section Table of Contents Next Section

Creating a Log File Scanner

graphics/arrow.gif The Log File Scanner

Listing 12.6 shows the complete log file scanner.

Listing 12.6. ScanLog.vbs. Scans for "500" errors in an IIS log file.

' Scan a log file from a webserver for

' occurrences of " - 500" which indicates an

' internal server error

' get the log file

Dim varLogFile

varLogFile = InputBox ("Enter the complete " & _

 "path and filename " & _

 "of log file to scan.")



' create filesystemobject

Dim oFSO

Set oFSO = WScript.CreateObject("Scripting.FileSystemObject")



' open file into a TextStream object

Dim oTS

Set oTS = oFSO.OpenTextFile (varLogFile)



Dim oTSOut

Set oTSOut = oFSO.CreateTextFile ("c:\errors.htm")





' begin reading each line in the textstream

dim varLine, varFoundNone

varFoundNone = true

Do Until oTS.AtEndOfStream

 varLine = oTS.ReadLine



 ' contains a 500 error?

 If instr(1, varLine, " - 500 ") <> 0 Then

  WScript.Echo varLine

  oTSOut.WriteLine "<b>" & varline & "</b>"

  varFoundNone = False

 End If

Loop



' close the textstream

oTS.Close

oTSOut.Close



' found any?

If varFoundNone = True Then

 WScript.Echo "Didn't find any errors."

Else

 WScript.Echo "Found Error. You need to fix them."

End If

Before you can start using this script, you simply need to figure out where IIS stores its log files. Normally, it's in %systemroot%\LogFiles with a subfolder (such as W3Svc) for each virtual Web server that you've created.

graphics/arrow.gif The Log File Scanner-Explained

The script starts simply enough, by using an input box to ask for the complete path and filename of the log file to scan. This actually is a limitation of the script in its current form; in the next section, I'll enhance it to scan through every log file in a given folder, further automating the error-checking process.


' Scan a log file from a webserver for

' occurrences of " - 500" which indicates an

' internal server error



' get the log file

Dim varLogFile

varLogFile = InputBox ("Enter the complete path and filename " & _

 "of log file to scan.")

Next, the script creates an FSO to work with.


' create filesystemobject

Dim oFSO

Set oFSO = WScript.CreateObject("Scripting.FileSystemObject")

Because the script has to read a text file, it needs to create a TextStream object. As you've already seen, the way to do this is to simply declare a variable, and then use one of the FSO methods that returns a TextStream. In this case, because the script just needs to read an existing file, it's using the OpenTextFile method.


' open file into a TextStream object

Dim oTS

Set oTS = oFSO.OpenTextFile (varLogFile)

The script is going to need to log any errors it finds, so it creates a second TextStream object. This one represents a new file, and the TextStream is obtained from the FSO's CreateTextFile method.


Dim oTSOut

Set oTSOut = oFSO.CreateTextFile ("c:\errors.htm")

Now the script needs to loop through the contents of the log file, which is opened for reading. I've created a variable, varFoundNone, and set it to the Boolean value of False. I'm using that variable to figure out if I've found any errors so that I can give an appropriate message at the end of the script. To loop through the log file, the script utilizes the AtEndOfStream property of the TextStream object. This property is automatically set to True when the script reaches the end of the file.


' begin reading each line in the textstream

dim varLine, varFoundNone

varFoundNone = true

Do Until oTS.AtEndOfStream

Next, the script reads a line of text from the file. The ReadLine method actually pulls an entire string of text and stores it in varLine. At the same time, ReadLine moves a pointer in the file to the next line, which is where the next ReadLine operation begins. This internal pointer is used to set the AtEndOfStream property to True when the end of the file is reached.

After reading the line of text, the script needs to see if it contains an ASP application error. Remember, each line of an IIS log file represents one logged message. If that line contains " - 500", it's an application error. To check, the script uses the InStr() function, telling the function to start looking for " - 500" at the first character of the line. InStr()returns a number indicating the character position where " - 500" was found. I don't really care about that; what's important is that InStr()returns a zero if it doesn't find " - 500" within the string.


varLine = oTS.ReadLine



' contains a 500 error?

If instr(1, varLine, " - 500 ") <> 0 Then

If there's no error in the line, the script skips down to the Loop and goes back to read the next line from the file. However, if InStr() finds the string, the script outputs the line of text using the WScript.Echo command. It also writes the line of text to the output file, prefixing it with <b> and suffixing it with </b> which are the HTML tags for boldfacing.


  WScript.Echo varLine

  oTSOut.WriteLine "<b>" & varline & "</b>"

  varFoundNone = False

 End If

Loop

Also notice that my tracking variable gets set to False when an error is found. At the end of the script, this lets me know that I did, in fact, find an error.

NOTE

The WScript.Echo command behaves differently depending on how you run the script. If you used WScript.exe (or just double-clicked on the VBS file, which does the same thing), the script displays a message box for each error line found in the log file. However, if you use Cscript.exe to execute the script from a command line, the errors will be written as command-line messages, and you won't be prompted to click OK for each one.


After the script reaches the end of the file, it can start wrapping up. The first step is to close both of the TextStreams that are open.


' close the textstream

oTS.Close

oTSOut.Close

Finally, the script needs to display an appropriate ending message. This is especially important because otherwise there's no clear indication that the script finished running, especially if no errors were found.


' found any?

If varFoundNone = True Then

 WScript.Echo "Didn't find any errors."

Else

 WScript.Echo "Found Error. You need to fix them."

End If

TIP

Why did I choose to add the HTML tags in the output file? Just for fun, mainly. In theory, I could have written the file to a Web server, allowing my company's Web application developers to easily access the file to review their application's errors. You can omit the <b> and </b> tags, and just e-mail the completed text file.


As I've already mentioned, the script is lacking in one significant way, which I'll fix in the next section.

graphics/arrow.gif The Enhanced Log File Scanner

As you know, IIS stores multiple log files in its log file folder. The odds that you're going to find the time to scan each new log file every day are slim, so it'd be nice if this script just asked for a folder and then scanned automatically through each log file it found there. Listing 12.7 does exactly that. The changes from the original log file scanner are shown in boldface.

Listing 12.7. ScanLog2.vbs. Scans for "500" errors in an IIS log file.

' Scan a log file from a webserver for

' occurrences of " - 500" which indicates an

' internal server error



' get the log file

Dim varLogPath

varLogPath = InputBox ("Enter the " & _

 "complete path and logs folder.")



' create filesystemobject

Dim oFSO

Set oFSO = WScript.CreateObject("Scripting.FileSystemObject")



Dim oTSOut

Set oTSOut = oFSO.CreateTextFile ("c:\errors.htm")



' Loop through each file in the folder

Dim oFile, varFoundNone

varFoundNone = true

For Each oFile In oFSO.GetFolder("varLogPath").Files



 'Is this a log file?

 If Lcase(Right(oFile.Name,3)) = "log" Then



  'Open the log file

  Dim oTS

  oTS = oFSO.OpenTextFile(oFSO.BuildPath(oFile.Path, _

   oFile.Name))

  ' begin reading each line in the textstream

  dim varLine

  Do Until oTS.AtEndOfStream

   varLine = oTS.ReadLine



   ' contains a 500 error?

   If instr(1, varLine, " - 500 ") <> 0 Then

    WScript.Echo varLine

    oTSOut.WriteLine "<b>" & varline & "</b>"

    varFoundNone = False

   End If

  Loop



  ' close the input textstream

  oTS.Close



 End If



Next



' close the output textstream

oTSOut.Close



' found any?

If varFoundNone = True Then

 WScript.Echo "Didn't find any errors."

Else

 WScript.Echo "Found Error. You need to fix them."

End If

This new script will run as-is on just about any system, provided you've given it the path to a folder that contains log files.

graphics/arrow.gif The Enhanced Log File Scanner-Explained

This enhanced script starts much like the previous one, but asks only for a folder name. The beauty of the way the FSO treats folder names is that it doesn't matter whether the user includes a trailing backslash; the script works fine either way.


' Scan a log file from a webserver for

' occurrences of " - 500" which indicates an

' internal server error

' get the log file

Dim varLogPath

varLogPath = InputBox ("Enter the complete path and logs folder.")

Another minor change is that only the output TextStream is opened at this point. Because the script is working with multiple files, it needs to open each one, one at a time, as it encounters them.


' create filesystemobject

Dim oFSO

Set oFSO = WScript.CreateObject("Scripting.FileSystemObject")



Dim oTSOut

Set oTSOut = oFSO.CreateTextFile ("c:\errors.htm")

Finally, the first big change. I've declared a variable to represent a file object, and I'm using a For Each…Next construct to loop through a collection of objects. Here's how it works: The FSO's GetFolder method returns a Folder object; specifically, it's returning the folder specified by the user from the earlier InputBox() function. The Folder object has a property called Files, which is a collection of File objects. The construct loops through each file in the collection. Each time through the loop, variable oFile will be set to a different file.


' Loop through each file in the folder

Dim oFile, varFoundNone

varFoundNone = true

For Each oFile In oFSO.GetFolder("varLogPath").Files

I cannot be assured that every file in the specified folder will be a log file, so I've used an If…Then construct. If the rightmost three characters of the filename are "log", I'll allow the script to work with the file and scan for errors. Otherwise, I'll skip the file. Notice the use of the Lcase() function to force the filename into lowercase characters. This ensures that files with a log or LOG filename extension will be scanned.


'Is this a log file?

If Lcase(Right(oFile.Name,3)) = "log" Then

Now I'm ready to open the log file-the current one, that is-into a TextStream. I'm still using the OpenTextFile method, along with the Path property of the File object. The Path property provides a complete path, including the filename, for the file.


'Open the log file

Dim oTS

oTS = oFSO.OpenTextFile(oFile.Path)

Most of the rest of the script is the same: Read each line of the file, scan for the error text, and output a message if an error is found.


dim varLine



' begin reading each line in the textstream

  Do Until oTS.AtEndOfStream

   varLine = oTS.ReadLine



   ' contains a 500 error?

   If instr(1, varLine, " - 500 ") <> 0 Then

    WScript.Echo varLine

    oTSOut.WriteLine "<b>" & varline & "</b>"

    varFoundNone = False

   End If

  Loop

Notice that I've had to rearrange the file closing statements. In this case, I'm finished reading the current input file, so I can close it before looping back up-via the Next statement-to open the next file in the folder.


  ' close the input textstream

  oTS.Close



 End If



Next

Finally, I can close the output text file and finish up as I did before.


' close the output textstream

oTSOut.Close



' found any?

If varFoundNone = True Then

 WScript.Echo "Didn't find any errors."

Else

 WScript.Echo "Found Error. You need to fix them."

End If

The new script is a much more efficient administrative tool, because it can be run whenever you like and always scans through every log file you have.

TIP

You could enhance this script to scan for other types of errors, such as the common errors that occur when a user tries to access a file that doesn't exist, or when users try to access a file that they're not authorized for.


    Previous Section Table of Contents Next Section