Friday, July 20, 2007


A Rolling File Appender in VBScript

I use log4j and log4net in most of my projects but I did not have a decent alternative for VBScript so I implemented my own. The script below implements the most important features of the log4j/log4net rolling file appender. It lets you configure:

  • file to log to

  • size of each file

  • number of backups/old copies to keep

The code below uses test.txt as the log file with 4 backups. Test.txt contains the last logged data. When it is full, it is renamed to the backup file test.txt.1. The older logs are kept in the files test.txt.2, test.txt.3, … test.txt.N

Note that the size calculation is not accurate as the file is kept open. It is slower, but the size will be correct, if you open and close the file each time you log something. I did not care about accuracy so I chose the faster implementation below.

option explicit

const LOG_FILE = "C:\temp\test.txt"
const LOG_FILE_SIZE_KB = 1000
const LOG_TO_CONSOLE = false

const LOG_FATAL = 0
const LOG_ERROR = 1
const LOG_WARN = 2
const LOG_INFO = 3
const LOG_DEBUG = 4

const LOG_FILE_LEVEL = 4

dim currentLogStream
set currentLogStream = nothing

'==== Test ONLY. Delete this section in production code
'Main tester
WScript.echo "Press CTRL+C to exit"
do while true
 traceLog LOG_DEBUG, "Debug level test " & String(1000,"d")
 traceLog LOG_INFO, "Info level test" & String(1000,"i")
 traceLog LOG_WARN, "Warn level test" & String(1000,"w")
 traceLog LOG_ERROR, "Error level test" & String(1000,"e")
 traceLog LOG_FATAL, "Fatal level test" & String(1000,"f")
 Wscript.sleep (1)
'==== End Test

public sub traceLog (level, message)
dim prefix

 prefix = "[UNKNOWN]"
 if level <= LOG_FILE_LEVEL then
  select case level
   case LOG_FATAL
    prefix = "[FATAL]"
   case LOG_ERROR
    prefix = "[ERROR]"
   case LOG_WARN
    prefix = "[WARN]"
   case LOG_INFO
    prefix = "[INFO]"
   case LOG_DEBUG
    prefix = "[DEBUG]"
  end select

  rollingAppend prefix & vbTab & now() & vbTab & message  
 end if
end sub

sub rollingAppend (message)
'Special case the first time (file not opened)
dim oFS
dim oFile
dim fileNum
 on error resume next 'NEVER bomb while logging
 set oFS = CreateObject("Scripting.FileSystemObject")
 if currentLogStream is nothing then
  'Open stream for APPEND, creating the file if it does not exist
  set currentLogStream = oFS.OpenTextFile(LOG_FILE, 8, true)
 end if

 currentLogStream.WriteLine (message) 
 if LOG_TO_CONSOLE then WScript.echo message
 'Roll over if we should
 set oFile = oFS.getFile(LOG_FILE)
 if oFile.size >= LOG_FILE_SIZE_KB * 1024 then
  set currentLogStream = nothing
  'Delete the last backup   
  if oFS.FileExists(LOG_FILE  & "." &  LOG_FILE_BACKUPS) then
   oFS.DeleteFile LOG_FILE  & "." &  LOG_FILE_BACKUPS
  end if
  'Rename all the old log files so log_file.1 -> 2, 2->3, etc.
  for fileNum = LOG_FILE_BACKUPS - 1 to 1 step - 1
   if oFS.FileExists (LOG_FILE  & "." &  fileNum) then
    oFS.MoveFile LOG_FILE  & "." &  fileNum, LOG_FILE  & "." &  fileNum + 1
   end if
  'Move current file to .1
  oFS.MoveFile LOG_FILE, LOG_FILE & "." & 1  
 end if
end sub

Tuesday, July 17, 2007


How we see the world

I always imagined my eyes send a full color image/movie to my brain, letting the brain sort out the what happens in the world.  The brain has a lot of processing power but how can it decipher what it sees so fast? The failures of first DARPA Grand Challenge shows just how difficult it is to interpret visual data in real time.

It turns out that the brain does not accomplish the task by itself. It gets a hand by the eyes which pre-processes the data in a way I never imagined.

Frank Werblin and Botond Roska explain the results of their research in The Movies in our eyes article in Scientific American. It turns out that the eye, of a rabbit in their tests, does not send one stream of information but 12 parallel "movies" of the world.  This movie illustrates very well the different (simulated) signals sent to the brain:

Different layers of cells in the retina interpret the world and send separate “movies“. The orange movie shows the contours which is great for pattern matching whereas the beige movie focuses on bright areas. The movies are then combined by the brain to give the world we see.

Another key point is that they eyes do not send a continuous movies, it only sends highlights thereby reducing the work the brain has to do. Flashing a light for one second at a specific area in the retina does not send a continuous signal for one second. The retina sends a signal shortly after the bright flash starts, then it remains silent until there is a short signal when the light goes off again.

A great example of solving a complex problem by distributing the work and breaking it down in the manageable pieces.

Yet another lesson learned from mother nature.