Link to home
Start Free TrialLog in
Avatar of mike_at_somedude_dot_com
mike_at_somedude_dot_com

asked on

IIS 6 - View Each Site's Bandwidth Usage

I need to find a program that will allow me to view the bandwidth useage for each site setup in IIS individually.

Here is the reason I need this... we have a dedicated server and are allowed so much bandwidth per month... One customer went over their alotted bandwidth and made our bill go up. We want to find a way to see how much bandwidth each site is using so that we can bill them accordingly. I don't care if it analyzes log files or uses some other method to find the bandwidth used, just as long as it can accurately display the total badwidth used for each site.

The log files are all in different directories (i.e. C:\site1\logs, C:\site2\logs, C:\site3\logs, etc.) We are not moving the log files into a common directory so please don't even suggest it something that would require this course of action.

A free solution would be best. I don't want something that is going to cost me 200 bucks and I don't even really know if it's what I want or not.
Avatar of humeniuk
humeniuk
Flag of Canada image

The most comprehensive solution would be a Windows/IIS control panel with those and other features.  For example, take a look at Ensim Pro for Windows - www.ensim.com/products/pro/windows.html  or Plesk 7.5 for Windows - www.sw-soft.com/en/products/plesk75win/.  However, prices start at $199 for a 20 domain license and you may not be interested in any of the features beyond the bandwidth measurements.

A cheaper and simpler solution would be a log file analysis tool that can break down bandwidth use by website.  A good example of that is LogFileManager 3 - www.logfilemanager.com.
BTW - there is a free trial for LogFileManager, but it costs $39.95 to register and keep.
Avatar of Chris Dent

It's pretty easy to script something that picks up the total for a log file. I wrote some to do that for my own servers in Perl, but VBScript is just as capable of doing it.

Really it just depends on how you perform logging. Daily log files like ex050420.log? And I assume you log bytes-sc / bytes-cs?

Different directories are no problem, even preferable since it gives a nice easy way to figure out what is being read in.

Beyond that... how often / what period do you want to pull bandwidth for and how do you want it reported?

And is this the kind of solution you'd like to persue?

Just for the sake of a sample, this section of perl script is at the core of my own script. It does the bit that matters, counts the usage from a single file (file name is passed into the sub):

sub Logs_Parse

# This function processes a single log file pulling out the sc-bytes field.
# Because not much in the way of data-validation is done this will pull up a lot of warnings with debugging on (use
# warnings and use diagnostics).
# All lines beginning with # are ignored except the #Fields line which is used to determine the position of sc-bytes

{
      my $funcLogFile = shift(@_);
      my $funcFieldCount = 0;
      my $funcFieldPosition = 0;
      my $funcFileTotal = 0;
      my $funcByteCurrent = 0;
      my $funcFieldFound = "FALSE";

      eval {
            open (LOGFILE, "<$funcLogFile") or die "Error opening File - $funcLogFile";
      };
      if ($@)
      {
            print "$@\n";
      }
      else
      {
            while (my $funcLine = <LOGFILE>)
            {
                  chomp($funcLine);
                  my @funcLineArray = split(/ /, $funcLine);
                  if ($funcLineArray[0] =~ m/\#/)
                  {
                        if ($funcLineArray[0] eq '#Fields:')
                        {
                              foreach my $funcField (@funcLineArray)
                              {
                                    if ($funcField eq "sc-bytes")
                                    {            
                                          # Because the main file doesn't have an extra field in front called #Fields:...
                                                
                                          $funcFieldPosition = $funcFieldCount - 1;
                                          $funcFieldFound = "TRUE";
                                    }
                                    $funcFieldCount = ++$funcFieldCount;
                              }
                        }
                  }      
                  if ($funcFieldFound eq "TRUE")
                  {
                        $funcByteCurrent = $funcLineArray[$funcFieldPosition];
                        $funcFileTotal = $funcFileTotal + $funcByteCurrent;
                  }
            }
            print "$funcFileTotal\n";
            close LOGFILE;
            return $funcFileTotal;
      }
}

In my case this all adds up to create a monthly total. The rest of the code wraps around figuring out how to get the file names in the first place, how to do it for lots of different log directories and how to report it.
Avatar of mike_at_somedude_dot_com
mike_at_somedude_dot_com

ASKER

humeniuk: I don't want a control panel on the server. We make sites in coldfusion and then host them on our servers after we are done. Our users do not know how to program or anything, therefore we don't need FTP or any sort of control panel or anything, it's just plain old hosting. The log file tool you suggested looks like it requires all log files to be in the same directory, as I stated before, this is not possible.

Chris-Dent: I don't know anything about perl and we don't allow scripts to be run from the server other than coldfusion. It is a dedicated server and we can connect remotely so I was hoping for some sort of program or something that we could install and it would only be accesible to people remotely connected.

Can the server run vbscript or ASP at all? That normally doesn't require any installation.
Yeah ASP is enabled

The bandwidth monitoring script can be run as part of an ASP page (I have a vbscript log file parser as well as the perl version), or run as a scheduled task on the server.

It just depends on how you want to report bandwidth (on demand / scheduled / monthly / weekly etc etc) and what the filenames of the log files are.

Let me know that and I'll dump you some code to try, you can see if you like it and go from there.

Chris
The filenames are the default IIS names (exyymmdd.log). Monthly would probably be the best reporting period.

Okay this is a basic version (works but doesn't produce pretty output). It's quite long, but it produces the total of last months logs (total for March). The logs it picks and totals can quite easily be altered. The main point is to get it producing a figure in the first place.

One thing you will need to alter, it requires the relative path from the website root to the logs for strLogFolder. It's commented, but let me know if you have any problems.

<html>
      <head>
            <title>
                  <%
                        Dim strDomainName
                        strDomainName = Request.ServerVariables("HTTP_HOST")
                        
                        Response.Write("Bandwidth Report - " & strDomainName)
                  %>
            </title>
      </head>
      <body>
            <%
            
            ' A very basic HTML wrapper for this
      
            Set objFileSystem = CreateObject("Scripting.FileSystemObject")
            strServerPath = Request.ServerVariables("APPL_PHYSICAL_PATH")
            
            ' For this version to work you need to give the relative path from the www root to the log files.
            ' The user running this script must have access rights to the logs or it won't work.
            
            strLogFolder = strServerPath & "<Log File Path from www Root>"
            
            ' e.g.
            ' strLogFolder = strServerPath & "\LogFiles"


            Function FileTotal(strLogName)
            
            ' A function that returns the number of bytes from a particular log file
            
                  intFieldCount = 0
                  intFieldPosition = 0
                  intFileTotal = 0
                  intByteCurrent = 0
                  booFieldFound = "FALSE"
            
                  ' Clear out any previous errors and initialize error handling
            
                  Err.Clear
                  On Error Resume Next
                  Set objFile = objFileSystem.GetFile(strLogName)
                  Set objTextStream = objFile.OpenAsTextStream(1,0)
                  If (Err <> 0) Then
                                    
                  Else
                        Do
                              booIgnore = "FALSE"
                              strLine = objTextStream.ReadLine()
                              arrLine = split(strLine, " ")
                                                                                                      
                              ' Get the field positions
                                                                                                      
                              If (arrLine(0) = "#Fields:") Then
                                    For Each strElement in arrLine
                                          If (strElement = "sc-bytes") Then
                                                intFieldPosition = intFieldCount - 1
                                                booFieldFound = "TRUE"
                                          End If
                                          intFieldCount = intFieldCount + 1
                                    Next
                              End If
                              
                              If (booFieldFound = "TRUE") Then
                                    intByteCurrent = arrLine(intFieldPosition)
                                    intFileTotal = intFileTotal + intByteCurrent
                              End If
                        Loop while not objTextStream.AtEndOfStream
                        objFile.Close
                  End If
                  FileTotal = intFileTotal
            End Function
            
            Function FileName(strMonth, strYear)
            
            ' Creates the partial log filename from the Month and Year
            
                  If (strMonth < 10) Then
                        strMonth = "0" & strMonth
                  End If
                  strYear = Right(strYear, 2)
                  strPartialName = "ex" & strYear & strMonth
                  FileName = strPartialName
            End Function
            
            
            '
            ' Main Section
            '
                                                                                                
            ' Connect to the log folder to get the full path
                                                                                    
            Set objFolder = objFileSystem.GetFolder(strLogFolder)
            
            ' Attempt to Connect to the W3SVC folder
            
            For Each objSubFolder in objFolder.SubFolders
                  If ((InStr(objSubFolder.Name, "W3SVC")) <> 0) Then
                        strLogFolder = objSubFolder.Path
                        booConnected = "TRUE"
                  End If
            Next
            
            Set objFolder = Nothing
            
            ' Start out by running it for last month...
            
            strMonth = DatePart("m",Date())
            strYear = DatePart("yyyy",Date())
            
            ' Set it up to process logs from last month
            
            If (strMonth = 1) Then
                  strYear = strYear - 1
                  strMonth = 12
            Else
                  strMonth = strMonth - 1
            End If
            
            strPartialName = FileName(strMonth, strYear)
            
            Set objFolder = objFileSystem.GetFolder(strLogFolder)
            
            int LogsTotal = 0
            
            For Each objFile in objFolder.Files
                  If (InStr(objFile.Name, strPartialName) <> 0) Then
                        strLogFile = objFile.Path
                        intTotal = FileTotal(strLogFile)
                        intLogsTotal = intLogsTotal + intTotal
                  End If
            Next
                  
            Response.Write("Total Bytes Used in Logs: " & intLogsTotal)
            
            %>
      </body>
</html>
Does this only work for one folder? In my initial question, I stated that the log files are in a bunch of different folders (i.e. wwwroot/client1/logs, wwwroot/client2/logs, etc.). There are at least 50-60 clients so it would be very inconvenient to have to change the variable, run the script, change the variable, run the script, and so on for each client.

It's a sample only, it runs for one particular site, but that can be any particular site.

I can easily change to just process for directories rather than sites.

Are they all like:

c:\site1.com\logs
c:\site2.com\logs

Or does the location of logs vary between sites?

Give me a few minutes and I'll post another version.
Well this is how it works. We have all of the sites on a second drive, seperate from the boot drive. Each site is in a folder inside the sites folder so we have it like this...

D:\sites\acs\
D:\sites\adr\
etc.

Each folder has a folder named logs in it:

D:\sites\acs\logs\
D:\sites\adr\logs\
etc.

Inside of each of the log folders is one single folder, named by windows, which includes the actual logs... Here is an example:

D:\sites\acs\logs\W3SVC93579\
D:\sites\adr\logs\W3SVC53976\
etc.

The actual log files are inside these folder so a sample path to a log would be:

D:\sites\acs\logs\W3SVC93579\ex050421.log

Perfect thanks... won't be a sec.

One thing to beware of for this... if it has to do a lot of processing it might exceed the script timeout on the server. If you can run it as a scheduled task on the server it can be modified to dump the output to a text file. Let me know if you'd like to do that.

As before it still only processes the log files for last month.

<html>
<head>
      <title>
            <%
                  Dim strDomainName
                  strDomainName = Request.ServerVariables("HTTP_HOST")
                   
                  Response.Write("Bandwidth Report")
            %>
      </title>
</head>

<body>
<%
         
' A very basic HTML wrapper for this
     
Set objFileSystem = CreateObject("Scripting.FileSystemObject")

strSiteFolder = "d:\sites"

' For this version to work you need to give the relative path from the www root to the log files.
' The user running this script must have access rights to the logs or it won't work.

strLogPath = "\logs"
         
' e.g.
' strLogPath = "\logs"
' This will combine to create d:\sites\<site folder>\logs

'
' Functions
'

Function FileTotal(strLogName)
         
' A function that returns the number of bytes from a particular log file
     
      intFieldCount = 0
      intFieldPosition = 0
      intFileTotal = 0
      intByteCurrent = 0
      booFieldFound = "FALSE"
         
      ' Clear out any previous errors and initialize error handling
         
      Err.Clear
      On Error Resume Next
      Set objFile = objFileSystem.GetFile(strLogName)
      Set objTextStream = objFile.OpenAsTextStream(1,0)
      If (Err = 0) Then
            Do
                  booIgnore = "FALSE"
                  strLine = objTextStream.ReadLine()
                  arrLine = split(strLine, " ")
                                                                                     
                  ' Get the field positions
                                                                                     
                  If (arrLine(0) = "#Fields:") Then
                        For Each strElement in arrLine
                              If (strElement = "sc-bytes") Then
                                    intFieldPosition = intFieldCount - 1
                                    booFieldFound = "TRUE"
                              End If
                              intFieldCount = intFieldCount + 1
                        Next
                  End If
                         
                  If (booFieldFound = "TRUE") Then
                        intByteCurrent = arrLine(intFieldPosition)
                        intFileTotal = intFileTotal + intByteCurrent
                  End If
            Loop while not objTextStream.AtEndOfStream

            objFile.Close
      End If
      FileTotal = intFileTotal
End Function
         
Function FileName(strMonth, strYear)
         
' Creates the partial log filename from the Month and Year
         
      If (strMonth < 10) Then
            strMonth = "0" & strMonth
      End If
      strYear = Right(strYear, 2)
      strPartialName = "ex" & strYear & strMonth
      FileName = strPartialName
End Function
         
         
'
' Main Section
'

' Start out by running it for last month...
         
strMonth = DatePart("m",Date())
strYear = DatePart("yyyy",Date())
         
' Set it up to process logs from last month
         
If (strMonth = 1) Then
      strYear = strYear - 1
      strMonth = 12
Else
      strMonth = strMonth - 1
End If
         
strPartialName = FileName(strMonth, strYear)
                                                                               
' Connect to the log folder to get the full path
       
Set objSiteFolder = objFileSystem.GetFolder(strSiteFolder)

For Each objSite in objSiteFolder.SubFolders

      ' Make sure the logs folder exists first

      strLogFolder = objSite.Path & strLogPath
      If (objFileSystem.FolderExists(strLogFolder)) Then
            Set objFolder = objFileSystem.GetFolder(strLogFolder)

            ' Attempt to Connect to the W3SVC folder
         
            For Each objSubFolder in objFolder.SubFolders
                  If ((InStr(objSubFolder.Name, "W3SVC")) <> 0) Then
                        strLogFolder = objSubFolder.Path
                        booConnected = "TRUE"
                  End If
            Next
         
            Set objFolder = Nothing

            Set objFolder = objFileSystem.GetFolder(strLogFolder)
         
            int LogsTotal = 0
         
            For Each objFile in objFolder.Files
                  If (InStr(objFile.Name, strPartialName) <> 0) Then
                        strLogFile = objFile.Path
                        intTotal = FileTotal(strLogFile)
                        intLogsTotal = intLogsTotal + intTotal
                  End If
            Next
               
            Response.Write("Total Bytes Used in Logs for " & objSite.Name & ": " & intLogsTotal & "<br />")
      End If
Next
         
%>

</body>
</html>
Not working, it just says 0 for the first 15 or so sites, and then throws a timeout error.

Total Bytes Used in Logs for acs: 0
Total Bytes Used in Logs for adr: 0
Total Bytes Used in Logs for AdvancedAudio: 0
Total Bytes Used in Logs for annabellegutman: 0
Total Bytes Used in Logs for atomiccomputerservices: 0
Total Bytes Used in Logs for Belayer: 0
Total Bytes Used in Logs for BigTallShort: 0
Total Bytes Used in Logs for buggerhugger: 0
Total Bytes Used in Logs for buyaudiogear: 0
Total Bytes Used in Logs for CentralChristian2: 0
Total Bytes Used in Logs for CentralChristianBeta: 0
Total Bytes Used in Logs for checkoutaisle: 0
Total Bytes Used in Logs for CreativeAudioServices: 0
Total Bytes Used in Logs for DewaldHealthCare: 0
Total Bytes Used in Logs for dobsonranchinn: 0
Total Bytes Used in Logs for elpradogalleries: 0
Total Bytes Used in Logs for escomconsulting: 0
Total Bytes Used in Logs for GetAwayStakes: 0

Active Server Pages error 'ASP 0113'

Script timed out

/loganalysis/index.asp

The maximum amount of time for a script to execute was exceeded. You can change this limit by specifying a new value for the property Server.ScriptTimeout or by changing the value in the IIS administration tools.


Could you add:

<% Server.ScriptTimeout = 900 %>

To the beginning, that gives it 15 minutes to run, shouldn't take that long.

Also need to add a few bits to the code to see where it's breaking if that's okay...

Can you change the end section to match this:

          Set objFolder = objFileSystem.GetFolder(strLogFolder)
         
          int LogsTotal = 0
         
          Response.Write(objSite.Name & ": " & strLogFolder & " - " & objFolder.Path & "<br />")

          For Each objFile in objFolder.Files
               If (InStr(objFile.Name, strPartialName) <> 0) Then
                    strLogFile = objFile.Path
                    Response.Write(objFile.Path & "<br />")
                    intTotal = FileTotal(strLogFile)
                    intLogsTotal = intLogsTotal + intTotal
               End If
          Next
               
          Response.Write("Total Bytes Used in Logs for " & objSite.Name & ": " & intLogsTotal & "<br />")
     End If
Next
         
%>

</body>
</html>

A space has managed to lodge itself in an inconvenient place above...

int LogsTotal = 0

Should be

intLogsTotal = 0

Or it'll add all the totals together and the last one on the list will have a really massive amount of bandwidth usage.
Same thing, 0 bytes for everything. I'm just going to copy and paste the output for the first directory since it would be way too much if I were to copy and paste it all...

acs: D:\sites\acs\logs\W3SVC669916 - D:\sites\acs\logs\W3SVC669916
D:\sites\acs\logs\W3SVC669916\ex050301.log
D:\sites\acs\logs\W3SVC669916\ex050302.log
D:\sites\acs\logs\W3SVC669916\ex050303.log
D:\sites\acs\logs\W3SVC669916\ex050304.log
D:\sites\acs\logs\W3SVC669916\ex050305.log
D:\sites\acs\logs\W3SVC669916\ex050306.log
D:\sites\acs\logs\W3SVC669916\ex050307.log
D:\sites\acs\logs\W3SVC669916\ex050308.log
D:\sites\acs\logs\W3SVC669916\ex050309.log
D:\sites\acs\logs\W3SVC669916\ex050310.log
D:\sites\acs\logs\W3SVC669916\ex050311.log
D:\sites\acs\logs\W3SVC669916\ex050312.log
D:\sites\acs\logs\W3SVC669916\ex050313.log
D:\sites\acs\logs\W3SVC669916\ex050314.log
D:\sites\acs\logs\W3SVC669916\ex050315.log
D:\sites\acs\logs\W3SVC669916\ex050316.log
D:\sites\acs\logs\W3SVC669916\ex050317.log
D:\sites\acs\logs\W3SVC669916\ex050318.log
D:\sites\acs\logs\W3SVC669916\ex050319.log
D:\sites\acs\logs\W3SVC669916\ex050320.log
D:\sites\acs\logs\W3SVC669916\ex050321.log
D:\sites\acs\logs\W3SVC669916\ex050322.log
D:\sites\acs\logs\W3SVC669916\ex050323.log
D:\sites\acs\logs\W3SVC669916\ex050324.log
D:\sites\acs\logs\W3SVC669916\ex050325.log
D:\sites\acs\logs\W3SVC669916\ex050326.log
D:\sites\acs\logs\W3SVC669916\ex050327.log
D:\sites\acs\logs\W3SVC669916\ex050328.log
D:\sites\acs\logs\W3SVC669916\ex050329.log
D:\sites\acs\logs\W3SVC669916\ex050330.log
D:\sites\acs\logs\W3SVC669916\ex050331.log
Total Bytes Used in Logs for acs: 0

No problem.. that's plenty.

Could you open one of the log files and post the #Fields line please? The parser should auto-adjust to get the position of sc-bytes, but it requires the #Fields line. I just need to check nothing will throw up a problem there.

Basically, the problem is either with the file parser function or the sites just aren't logging the sc-bytes in the log file options.

And the two response write statements for debugging can be removed from the code above:

Response.Write(objSite.Name & ": " & strLogFolder & " - " & objFolder.Path & "<br />")
Response.Write(objFile.Path & "<br />")

Which should make the output a bit more practical.
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Cookie) cs(Referer) cs-host sc-status sc-substatus sc-win32-status sc-bytes cs-bytes

We'll just go with me breaking the function with too much playing then ;)

Try this one please:

Function FileTotal(strLogName)

' A function that returns the number of bytes from a particular log file

      intFieldCount = 0
      intFieldPosition = 0
      intFileTotal = 0
      intByteCurrent = 0
      booFieldFound = "FALSE"

      ' Clear out any previous errors and initialize error handling

      Set objFile = objFileSystem.GetFile(strLogName)
      Set objTextStream = objFile.OpenAsTextStream(1,0)
      
      Do
            booIgnore = "FALSE"
            strLine = objTextStream.ReadLine()
            arrLine = split(strLine, " ")
            
            ' Get the field positions
            
            If (arrLine(0) = "#Fields:") Then
                  For Each strElement in arrLine
                        If (strElement = "sc-bytes") Then
                              intFieldPosition = intFieldCount - 1
                              booFieldFound = "TRUE"
                        End If
                        intFieldCount = intFieldCount + 1
                  Next
            End If
                  
            ' Ignore other lines starting with #
            
            If (Left(arrLine(0), 1) = "#") Then
                  booIgnore = "TRUE"
            End If

            ' Count up the total

            If ((booFieldFound = "TRUE") and (booIgnore = "FALSE")) Then
                  intByteCurrent = arrLine(intFieldPosition)
                  intFileTotal = intFileTotal + intByteCurrent
            End If
      Loop while not objTextStream.AtEndOfStream
      FileTotal = intFileTotal
End Function
Looks like the same as last time...

acs: D:\sites\acs\logs\W3SVC669916 - D:\sites\acs\logs\W3SVC669916
D:\sites\acs\logs\W3SVC669916\ex050301.log
D:\sites\acs\logs\W3SVC669916\ex050302.log
D:\sites\acs\logs\W3SVC669916\ex050303.log
D:\sites\acs\logs\W3SVC669916\ex050304.log
D:\sites\acs\logs\W3SVC669916\ex050305.log
D:\sites\acs\logs\W3SVC669916\ex050306.log
D:\sites\acs\logs\W3SVC669916\ex050307.log
D:\sites\acs\logs\W3SVC669916\ex050308.log
D:\sites\acs\logs\W3SVC669916\ex050309.log
D:\sites\acs\logs\W3SVC669916\ex050310.log
D:\sites\acs\logs\W3SVC669916\ex050311.log
D:\sites\acs\logs\W3SVC669916\ex050312.log
D:\sites\acs\logs\W3SVC669916\ex050313.log
D:\sites\acs\logs\W3SVC669916\ex050314.log
D:\sites\acs\logs\W3SVC669916\ex050315.log
D:\sites\acs\logs\W3SVC669916\ex050316.log
D:\sites\acs\logs\W3SVC669916\ex050317.log
D:\sites\acs\logs\W3SVC669916\ex050318.log
D:\sites\acs\logs\W3SVC669916\ex050319.log
D:\sites\acs\logs\W3SVC669916\ex050320.log
D:\sites\acs\logs\W3SVC669916\ex050321.log
D:\sites\acs\logs\W3SVC669916\ex050322.log
D:\sites\acs\logs\W3SVC669916\ex050323.log
D:\sites\acs\logs\W3SVC669916\ex050324.log
D:\sites\acs\logs\W3SVC669916\ex050325.log
D:\sites\acs\logs\W3SVC669916\ex050326.log
D:\sites\acs\logs\W3SVC669916\ex050327.log
D:\sites\acs\logs\W3SVC669916\ex050328.log
D:\sites\acs\logs\W3SVC669916\ex050329.log
D:\sites\acs\logs\W3SVC669916\ex050330.log
D:\sites\acs\logs\W3SVC669916\ex050331.log
Total Bytes Used in Logs for acs: 0

How odd.. I can't get it to break on mine..

Could you post a couple of lines of a log file and I'll rerun it to check it's pulling the data out.

Oh and the path and filenames it's producing are correct?

Okay sorry about this... probably due to some mistakes I had...

So I rewrote some of the error handling and made sure it worked for my site structure - which is pretty much identical to your own except logs is another directory down.

Let me know if it still produces 0 please.

<html>
<% Server.ScriptTimeout = 900 %>
<head>
      <title>
            <%
                  Dim strDomainName
                  strDomainName = Request.ServerVariables("HTTP_HOST")
                      
                  Response.Write("Bandwidth Report")
            %>
      </title>
</head>

<body>
<%
          
' A very basic HTML wrapper for this
      
Set objFileSystem = CreateObject("Scripting.FileSystemObject")

strSiteFolder = "d:\sites"

' For this version to work you need to give the relative path from the www root to the log files.
' The user running this script must have access rights to the logs or it won't work.

strLogPath = "\logs"

' e.g.
' strLogPath = "\logs"
' This will combine to create d:\sites\<site folder>\logs

'
' Functions
'

Function FileTotal(strLogName)

' A function that returns the number of bytes from a particular log file

      intFileTotal = 0
      intByteCurrent = 0
      booFieldFound = "FALSE"

      ' Clear out any previous errors and initialize error handling

      Set objFile = objFileSystem.GetFile(strLogName)
      Set objTextStream = objFile.OpenAsTextStream(1,0)
      
      Do
            booIgnore = "FALSE"
            strLine = objTextStream.ReadLine()
            arrLine = split(strLine, " ")
            
            ' Get the field positions
            
            If (arrLine(0) = "#Fields:") Then
                  intFieldPosition = 0
                  intFieldCount = 0
                  For Each strElement in arrLine
                        If (strElement = "sc-bytes") Then
                              intFieldPosition = intFieldCount - 1
                              booFieldFound = "TRUE"
                        End If
                        intFieldCount = intFieldCount + 1
                  Next
            End If
                  
            ' Ignore other lines starting with #
            
            If (Left(arrLine(0), 1) = "#") Then
                  booIgnore = "TRUE"
            End If

            ' Count up the total

            If ((booFieldFound = "TRUE") and (booIgnore = "FALSE")) Then
                  If (Ubound(arrLine) => intFieldPosition) Then
                        intByteCurrent = arrLine(intFieldPosition)
                        intFileTotal = intFileTotal + intByteCurrent
                  End If
            End If
      Loop while not objTextStream.AtEndOfStream
      FileTotal = intFileTotal
End Function

Function FileName(strMonth, strYear)
          
' Creates the partial log filename from the Month and Year
          
      If (strMonth < 10) Then
            strMonth = "0" & strMonth
      End If
      strYear = Right(strYear, 2)
      strPartialName = "ex" & strYear & strMonth
      FileName = strPartialName
End Function
          
          
'
' Main Section
'

' Start out by running it for last month...
          
strMonth = DatePart("m",Date())
strYear = DatePart("yyyy",Date())
          
' Set it up to process logs from last month

If (strMonth = 1) Then
      strYear = strYear - 1
      strMonth = 12
Else
      strMonth = strMonth - 1
End If
          
strPartialName = FileName(strMonth, strYear)
      
' Connect to the log folder to get the full path
        
Set objSiteFolder = objFileSystem.GetFolder(strSiteFolder)

For Each objSite in objSiteFolder.SubFolders

      ' Make sure the logs folder exists first
      
      strLogFolder = objSite.Path & strLogPath

      If (objFileSystem.FolderExists(strLogFolder)) Then
            Set objFolder = objFileSystem.GetFolder(strLogFolder)

            ' Attempt to Connect to the W3SVC folder
          
            For Each objSubFolder in objFolder.SubFolders
                  If ((InStr(objSubFolder.Name, "W3SVC")) <> 0) Then
                        strLogFolder = objSubFolder.Path
                        booConnected = "TRUE"
                  End If
            Next
          
            Set objFolder = Nothing

            Set objFolder = objFileSystem.GetFolder(strLogFolder)
          
            intLogsTotal = 0
          
            For Each objFile in objFolder.Files
                  If (InStr(objFile.Name, strPartialName) <> 0) Then
                        strLogFile = objFile.Path
                        intTotal = 0
                        intTotal = FileTotal(strLogFile)
                        intLogsTotal = intLogsTotal + intTotal
                  End If
            Next
                  
            Response.Write("Total Bytes Used in Logs for " & objSite.Name & ": " & intLogsTotal & "<br />")
      End If
Next
          
%>

</body>
</html>
Total Bytes Used in Logs for acs: 0
Total Bytes Used in Logs for adr: 0
Total Bytes Used in Logs for AdvancedAudio: 0
Total Bytes Used in Logs for annabellegutman: 0
Total Bytes Used in Logs for atomiccomputerservices: 0
Total Bytes Used in Logs for Belayer: 0
etc.

I think I may have just realized what the problem is. AT the beginning of this months log files, we were not logging the bytes so the beginning of the log files doesn't have that field. Then we decided to start logging that info so we do have bytes later on. Could we try it for just the last day instead of the last month? That way the entire log, from beginning to end, will have bytes in it.

If you want to make it process for this month instead of last comment out this section like below:
         
' Set it up to process logs from last month

' If (strMonth = 1) Then
'     strYear = strYear - 1
'     strMonth = 12
' Else
'     strMonth = strMonth - 1
' End If

And it'll run for all the log files that are present for this month. Changing it to run for a single file is possible, but it would be quicker to check it works for this months logs.



Still getting 0's across the board...

Okay, this is vbscript (rather than asp) that will process a single log file. Could you try it please? It won't produce much output, but it should say if it's finding the right things.


Set objFileSystem = CreateObject("Scripting.FileSystemObject")

' Gets log file for 21st April

strLogName = "D:\sites\acs\logs\W3SVC669916\ex050421.log"

intFileTotal = 0
intByteCurrent = 0
booFieldFound = "FALSE"

' Clear out any previous errors and initialize error handling

Set objFile = objFileSystem.GetFile(strLogName)
Set objTextStream = objFile.OpenAsTextStream(1,0)
     
Do
      booIgnore = "FALSE"
      strLine = objTextStream.ReadLine()
      arrLine = split(strLine, " ")
         
      ' Get the field positions
         
      If (arrLine(0) = "#Fields:") Then
            wscript.echo "Found #Fields line"
            intFieldPosition = 0
            intFieldCount = 0
            For Each strElement in arrLine
                  If (strElement = "sc-bytes") Then
                        intFieldPosition = intFieldCount - 1
                        booFieldFound = "TRUE"
                        wscript.echo "Located sc-bytes"
                  End If
                  intFieldCount = intFieldCount + 1
            Next
      End If
               
      ' Ignore other lines starting with #
         
      If (Left(arrLine(0), 1) = "#") Then
            booIgnore = "TRUE"
      End If

      ' Count up the total

      If ((booFieldFound = "TRUE") and (booIgnore = "FALSE")) Then
            If (Ubound(arrLine) => intFieldPosition) Then
                  intByteCurrent = arrLine(intFieldPosition)
                  intFileTotal = intFileTotal + intByteCurrent
            End If
      End If
Loop while not objTextStream.AtEndOfStream

wscript.echo intFileTotal

Um, how do I go about running vbscript? Sorry, this isn't really my sorta thing...

Oops sorry...

Grab a copy of a log file (any of them).

Save the code above in a .vbs file, make sure it knows where the log file is with the line:

strLogName = "D:\sites\acs\logs\W3SVC669916\ex050421.log"

Then run the script... it'll say if it found the field it needs, and the total for the file.
I suppose I am opening this file in a web browser right? Is there something special I need to do in order to get the server to process it? When I open it now, it just comes up with the download file screen (open, save, etc...).

Ahh if it still needs running remotely use this one instead (as ASP):

<%
Set objFileSystem = CreateObject("Scripting.FileSystemObject")

' Gets log file for 21st April

strLogName = "D:\sites\acs\logs\W3SVC669916\ex050421.log"

intFileTotal = 0
intByteCurrent = 0
booFieldFound = "FALSE"

' Clear out any previous errors and initialize error handling

Set objFile = objFileSystem.GetFile(strLogName)
Set objTextStream = objFile.OpenAsTextStream(1,0)
     
Do
     booIgnore = "FALSE"
     strLine = objTextStream.ReadLine()
     arrLine = split(strLine, " ")
         
     ' Get the field positions
         
     If (arrLine(0) = "#Fields:") Then
          Response.Write "Found #Fields line"
          intFieldPosition = 0
          intFieldCount = 0
          For Each strElement in arrLine
               If (strElement = "sc-bytes") Then
                    intFieldPosition = intFieldCount - 1
                    booFieldFound = "TRUE"
                    Response.Write "Located sc-bytes"
               End If
               intFieldCount = intFieldCount + 1
          Next
     End If
               
     ' Ignore other lines starting with #
         
     If (Left(arrLine(0), 1) = "#") Then
          booIgnore = "TRUE"
     End If

     ' Count up the total

     If ((booFieldFound = "TRUE") and (booIgnore = "FALSE")) Then
          If (Ubound(arrLine) => intFieldPosition) Then
               intByteCurrent = arrLine(intFieldPosition)
               intFileTotal = intFileTotal + intByteCurrent
          End If
     End If
Loop while not objTextStream.AtEndOfStream

Response.Write intFileTotal
%>
Found #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytesFound #Fields lineLocated sc-bytes126363

hmm see that's odd.. none of the code changed except for a few additional response.writes but it worked... how frustrating..
so this aint gonna happen?

No reason why it shouldn't.... it's probably something silly like a typo creeping in when it's being copied. I'll setup a downloadable version on my website tomorrow and post that one in.
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
still all 0's

Hmm okay I'm stuck - short of it being something simple like permissions I can find no reason that it wouldn't work.

After all, running it on an individual file above did work... There's been no difference in the user you run it as, or anything else?
nope, same user for both files. it's all the default windows 2003 setup for users.

One last try perhaps, although I doubt it will make any difference?

Made sure it closed off the File Object before using it again.

Here again...

http://www.highorbit.co.uk/Bandwidth.asp
nope no difference

Hmm... sorry that isn't working, not too helpful after all that...
Yeah, could you please?
Any chance you'd like to give Chris-Dent a few points for his efforts?

(this is not an unofficial request, no pressure)
If so, tell me how many you'd like to give.  If not, ie. if you need them for the new question, that's fine, too.
how bout 100 of the original 500
Sounds great.  Would you like me to make the change?