Best practice for thread logging?

I have a web app which has a number of different “worker” threads. These threads need to write to a single shared log file. What is the best practice for doing this without getting into trouble with deadlocks, race conditions, barometric pressure changes, etc.?

Currently I have a single “WriteToLog” method on the app class. Each thread calls that. WriteToLog just opens a TextOutputStream, does a WriteLine, and closes it.

Will I get into trouble with this approach? If so, what’s the best practice for doing something like this?

Thanks!

That sounds like it might be asking for trouble. Easiest thing would be to use a Semaphore to control access.

static s as new Semaphore( 1 )
s.Signal
// Write to the log
s.Release

There are more robust ways of doing it if you want to account for potential Exceptions, but that’s the basic idea.

Thanks Kem.

The semaphore itself belongs in the app class, right?

Then in the threads, they call Signal and Release on the app.semaphore.

What happens if a thread crashes after calling signal but before Release? I see in the CriticalSection docs it says “If a thread that has a lock crashes, the lock is not released.” Does the same apply to Semaphore, and if so how could I release the crashed lock?

The Semaphore can belong to the method exactly as I showed it.

The Thread would only “crash” in that method if the method itself crashed or if you happened to kill the Thread right when it was in that method. There are two ways to deal with that:

  1. Add an Exception handler to that method. Something like this:
static s as new Semaphore
s.Signal
// Write to log
s.Leave

Exception err as RuntimeException
s.Leave
raise err
  1. (Better) Create a wrapper class for the Semaphore, SemaphoreHolder, that Enters the Semaphore in its Constructor and Leaves it in its Destructor. The code would look something like this
static s as new Semaphore
dim holder as new SemaphoreHolder( s )
// Write to log

The Semaphore will be released no matter how holder goes nil, be it the end of the method or an Exception.

Thanks. Just to clarify here, I DO think I need the thread on the app class.

I don’t have one thread class that I’m instantiating over and over; I have several different classes, all of which are threads, that do different things.

So I think I have to have the semaphore on the app class, right? Otherwise the different thread types will each have their own unique semaphore, which isn’t very useful.

No, a Static variable works exactly the same way as a property in a module. Only one exists for the entire app.

I guess I’m not understanding something. If each of my thread types is a class, and I define a static variable inside that class, then it’s not visible by other classes. So how does “static” help in this instance? The semaphore needs to be visible by all in order to be effective, no?

You said:

The Static variable would be defined within that method. You can put a property into the App class instead if you prefer, but that’s extra code that will have exactly the same result.

Since each Thread uses that WriteToLog method, only one Thread at a time will be able write to the log at a time.

My misunderstanding, sorry. I thought you were suggesting I put the static variable into the thread class.

Thanks for your help!

I separate thread log output into different log files for each thread for just that reason and to make following the processes easier.

I thought about doing it that way, but I need a single consolidated log that can be read by timestamp.