logging to a text file in high demand environment

Discussion in 'ASP .Net' started by kpg, Apr 1, 2008.

  1. kpg

    kpg Guest

    Hi all,

    I have a vb asp.net web service where I log user activity to a
    text file like this:


    Using sw As StreamWriter = New StreamWriter(file, True)
    sw.WriteLine(data)
    sw.Flush()
    sw.Close()
    End Using


    I'm using the 'using' block becuase after reading about it, it
    seems like a good idea to ensure resources are released properly.

    Question:

    When the web service is called simultaneously by several users do
    I need to worry about the file being inaccessible because another
    process is writing to it?

    If so, what is the best way to do this? In a Try..catch I would assume,
    perhaps this:


    Try
    Using sw As StreamWriter = New StreamWriter(file, True)
    sw.WriteLine(data)
    sw.Flush()
    sw.Close()
    End Using
    Catch ex as exception
    '??? - wait for a few milliseconds and retry?
    'give up after several attempts???
    End Try

    Ideally I would like to 'never give up' but then again I don't want a
    race condition either.


    Thanks,
    kpg
    kpg, Apr 1, 2008
    #1
    1. Advertising

  2. kpg

    Martin Guest

    On 1 Apr, 16:39, kpg <> wrote:
    > Hi all,
    >
    > I have a vb asp.net web service where I log user activity to a
    > text file like this:
    >
    > Using sw As StreamWriter = New StreamWriter(file, True)
    >   sw.WriteLine(data)
    >   sw.Flush()
    >   sw.Close()
    > End Using
    >
    > I'm using the 'using' block becuase after reading about it, it
    > seems like a good idea to ensure resources are released properly.
    >
    > Question:
    >
    > When the web service is called simultaneously by several users do
    > I need to worry about the file being inaccessible because another
    > process is writing to it?
    >
    > If so, what is the best way to do this?  In a Try..catch I would assume,
    > perhaps this:
    >
    > Try
    >   Using sw As StreamWriter = New StreamWriter(file, True)
    >     sw.WriteLine(data)
    >     sw.Flush()
    >     sw.Close()
    >   End Using
    > Catch ex as exception
    >   '??? - wait for a few milliseconds and retry?
    >   'give up after several attempts???
    > End Try
    >
    > Ideally I would like to 'never give up' but then again I don't want a
    > race condition either.
    >
    > Thanks,
    > kpg


    You could look at using a Mutex object (in the System.Threading
    namespace). These are essentially mutually exclusive objects that can
    control access to shared resources.

    Declare the mutex object as private and shared in the declarations
    section of your class:

    Private Shared ThreadLock as new Mutex()

    Then, in the actual routine you would put something like the
    following:

    dim sw as StreamWriter
    try


    if Threadlock.WaitOne() Then
    sw = New StreamWriter(file, True)
    sw.WriteLine(data)
    sw.Flush()
    End if

    catch ex as exception

    finally
    'Close the stream writer
    If not sw is nothing then sw.Close
    'always call the release method, otherwise the mutex will be held in
    a locked state
    Threadlock.ReleaseMutex()
    end try

    I've left the Try-Catch block, as whenever you do IO operations, you
    should always anticipate an error.

    I've also added a Finally block. This will ensure that the code in
    this section is always executed.

    Hope this helps...

    Martin
    Martin, Apr 1, 2008
    #2
    1. Advertising

  3. kpg

    kpg Guest

    That sounds good. The mutex is declared as shared (which is
    static) so it exists independent of an instance of the class.

    Does the thread pooling method specified in IIS effect the scope
    (may not be the right word) of the mutex?

    I'm confused as to how several other users on the system, using
    the web service (and the class) will be using the same mutex
    when that mutex was not given an explicit name. I see that the
    mutex, being shared, has only one copy that exists for all
    instances of the class.

    I may have just answered my question

    Maybe I'm confusing IIS 5.0 thread pooling with IIS 6.0,
    In 5.0 there was a thread pool setting that ran everything in
    a different thread (isolated, I think). In 6.0 that seems to
    have changed. I specify different thread pools for different
    types of services. But of course this particular service will
    run in its assigned pool, so again I guess it works as you
    described - not that the thread pool setting would effect this
    anyway, now that I think about it.

    cool.

    thanks,
    kpg
    kpg, Apr 1, 2008
    #3
  4. kpg

    Mick Wilson Guest

    On Apr 1, 11:39 am, kpg <> wrote:
    > When the web service is called simultaneously by several users do
    > I need to worry about the file being inaccessible because another
    > process is writing to it?
    >
    > If so, what is the best way to do this?


    Why not use the Trace class to do your logging, which is thread safe?

    http://msdn2.microsoft.com/en-us/library/zd83saa2(VS.80).aspx
    Mick Wilson, Apr 1, 2008
    #4
  5. kpg

    kpg Guest

    Mick Wilson <> wrote in news:62316b20-c8fa-431b-98f7-
    :

    > http://msdn2.microsoft.com/en-us/library/zd83saa2(VS.80).aspx


    seems like such a simple concept...

    I do this:


    Dim myTraceLog As New System.IO.FileStream(sLogFile, _
    IO.FileMode.OpenOrCreate)

    Dim myListener As New TextWriterTraceListener(myTraceLog)

    Trace.WriteLine(Now.ToShortTimeString & "," & data)


    ....but the Trace statement is never run. That is, it's like its
    commented out - the compiler is not seeing it.

    I'm running a web service, does that matter?
    kpg, Apr 1, 2008
    #5
  6. kpg

    Mick Wilson Guest

    On Apr 1, 3:01 pm, kpg <> wrote:
    > ...but the Trace statement is never run.


    You're almost there. You need to add the listener object to the
    collection:

    Trace.Listeners.Add(myListener)
    Mick Wilson, Apr 1, 2008
    #6
  7. I believe that you can not log into text file in high demand environment...
    Writing to file does not support multithreaded access.... You will mess-up
    your log file if you try to write in it from different threads
    simultaneously.

    documentation says about TextWriterTraceListener "Any instance members are
    not guaranteed to be thread safe. "


    George


    "kpg" <> wrote in message
    news:Xns9A738EABDAF20ipostthereforeiam@207.46.248.16...
    > Mick Wilson <> wrote in news:62316b20-c8fa-431b-98f7-
    > :
    >
    >> http://msdn2.microsoft.com/en-us/library/zd83saa2(VS.80).aspx

    >
    > seems like such a simple concept...
    >
    > I do this:
    >
    >
    > Dim myTraceLog As New System.IO.FileStream(sLogFile, _
    > IO.FileMode.OpenOrCreate)
    >
    > Dim myListener As New TextWriterTraceListener(myTraceLog)
    >
    > Trace.WriteLine(Now.ToShortTimeString & "," & data)
    >
    >
    > ...but the Trace statement is never run. That is, it's like its
    > commented out - the compiler is not seeing it.
    >
    > I'm running a web service, does that matter?
    >
    >
    George Ter-Saakov, Apr 1, 2008
    #7
  8. kpg

    Mick Wilson Guest

    On Apr 1, 3:51 pm, "George Ter-Saakov" <> wrote:
    > documentation says about TextWriterTraceListener "Any instance members are
    > not guaranteed to be thread safe. "


    Does that matter if all of the write activities go through the thread-
    safe Trace class methods? You may be right about the disk contention
    issues, but I'm curious about what you mentioned with regard to the
    TextWriterTraceListener itself because I don't have a lot of
    experience dealing with concurrency issues.

    Thanks,
    Mick
    Mick Wilson, Apr 1, 2008
    #8
  9. kpg

    kpg Guest

    Thanks for the input.

    Here's what I ended up with. As usual, when I spend too much
    time on a piece of code I start embellishing it and have to
    stop myself.

    The reason I broke out WriteTofile is that I also write data
    dumps to a unique filename that will never be in use, so why
    go through the trouble of 'locking' it, plus I needed it in
    the exception handler for AbandonedMutexException.

    WriteToLog builds my date-based file name (simplified here),
    then calls the protected WriteToSharedFile routine.

    I added a handler and log entry for the AbandonedMutexException,
    knowing that if I'm writing to a 'shared' file it must be the
    log file. Works for me in this case.

    ASP.NET 2.0 documentation says the thread receiving the
    AbandonedMutexException now owns the mutex so I can proceed.

    I contemplated adding a timeout to the WaitOne, say 1000, but
    was not sure how to set the 2nd Boolean argument, plus if it's
    locked for that long there must be a problem. Not sure how
    likly that is.


    Sub WriteToLog(ByVal data As String)
    Dim sLogFile As String = "c:\path\myfile.log"
    WriteToSharedFile(sLogFile, data)
    End Sub

    Sub WriteToSharedFile(ByVal file As String, ByVal data As String)
    Try
    If ThreadLock.WaitOne() Then
    WriteToFile(file, data)
    End If
    Catch ex As AbandonedMutexException
    WriteToFile(file, "AbandonedMutexException")
    WriteToFile(file, data)
    Catch ex As Exception
    Finally
    ThreadLock.ReleaseMutex()
    End Try
    End Sub

    Sub WriteToFile(ByVal file As String, ByVal data As String)
    Dim sw As StreamWriter
    Try
    sw = New StreamWriter(file, True)
    sw.WriteLine(data)
    sw.Flush()
    Catch ex As Exception
    Finally
    If Not sw Is Nothing Then sw.Close()
    End Try
    End Sub

    kpg
    kpg, Apr 1, 2008
    #9
  10. If Trace is Thread safe you should be ok......
    Apparently it prevents multiple threads from writing at the same time but
    then it contradict to "high demand environment"

    ----------------------------------------------------------------------

    Somehow I did not think that they (Microsoft) make Trace a thread safe. I
    kind of expected that underlying writer will have to take care of thread
    safety.. .What if I am logging into database then I have unnecessary
    contention in Trace class since it's still going to prevent multiple threads
    from writing at the same time......

    ---------------------------------------
    Actually I always used MS Sql for logging. But it's just because I have not
    written application that is not using DB for years....

    George.




    "Mick Wilson" <> wrote in message
    news:...
    > On Apr 1, 3:51 pm, "George Ter-Saakov" <> wrote:
    >> documentation says about TextWriterTraceListener "Any instance members
    >> are
    >> not guaranteed to be thread safe. "

    >
    > Does that matter if all of the write activities go through the thread-
    > safe Trace class methods? You may be right about the disk contention
    > issues, but I'm curious about what you mentioned with regard to the
    > TextWriterTraceListener itself because I don't have a lot of
    > experience dealing with concurrency issues.
    >
    > Thanks,
    > Mick
    George Ter-Saakov, Apr 2, 2008
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stefan Siegl
    Replies:
    0
    Views:
    939
    Stefan Siegl
    Aug 27, 2003
  2. Christoph Haas
    Replies:
    0
    Views:
    431
    Christoph Haas
    Jun 12, 2006
  3. Christoph Haas
    Replies:
    1
    Views:
    440
    Vinay Sajip
    Jun 14, 2006
  4. RM
    Replies:
    0
    Views:
    266
  5. Chris M. Thomasson
    Replies:
    0
    Views:
    458
    Chris M. Thomasson
    Nov 15, 2010
Loading...

Share This Page