How to handle intermittent errors in Console output to network file

I wrote a console application that is usually launched using the Task Scheduler without user presence. If needed, it redirects the Console output to a file (with the application startup timestamp in the name) that is on the network.

I have seen a few cases - these are rare - where the contents of the file seem to end up prematurely (i.e. there are no later messages generated by the program). Output from a third-party logging tool (Gibraltar Loupe) showed me that calls to Console.WriteLine can fail if there is a network failure causing the output file to be temporarily unavailable, throwing an unhandled exception.

(At one point the normal exception handling of a normal application was - somewhat admirably - able to write an unhandled exception message that was thrown when the Console.WriteLine failed because "the specified network name is no longer available" - it must have been very temporary failure!)

I can't think of any other approach other than replacing all calls to Console.WriteLine with calls of my own, which traps such errors, waits for the network to be available again, and retries. (Or perhaps it can redirect the output to a local file for the rest of the run, but other things are likely to fail if the network remains unavailable.)

Replacing all calls to Console.WriteLine in an application with hundreds of them would result in a major source code explosion, resulting in changes to files that haven't changed in months. I have a choice?

Does anyone have any other suggestion on how to handle this (other than taking the Console.WriteLine away from the start of the project)?

Thanks for any suggestions.

+3


source to share


2 answers


It's not a good idea to try and fix the hard hardware problem in software. But consider:

  • Redirect to local file, use another scheduled task to move files.
  • Write a small defender application that uses Process.Start () to start this application. And uses Process.ExitCode to see how it works. It can restart the application multiple times if required, delaying longer between each attempt.
  • Reassign Console.Error and Console.Out with your own derived TextWriter class. Restart write (char) and call the original Error / Out.Write (char) method wrapped in try / catch. Try several times if it fails, delaying longer between attempts.


You probably think the latter is attractive. Sample code:

using System.IO;

class MyWriter : TextWriter {
    private TextWriter writer;
    public MyWriter(TextWriter writer) { this.writer = writer; }
    public override Encoding Encoding { get { return writer.Encoding; } }

    public override void Write(char value) {
        for (int delay = 1; ; delay *= 2) {
            try { writer.Write(value); return; }
            catch { if (delay > 3600) throw; }
            System.Threading.Thread.Sleep(1000*delay);
        }
    }
}

class Program {
    static void Main(string[] args) {
        Console.SetOut(new MyWriter(Console.Out));
        Console.SetError(new MyWriter(Console.Error));
        // etc...
    }
}

      

+4


source


To be honest, I believe abstracting the Console.WriteLine is exactly what you want to do. This will allow you to create a policy for handling exceptions and retries, or allow your application to continue handling the rest of what it should do when the file is available again. This will also help with UnitTesting and abstraction, etc. Etc.



However, having said that. You can write a local file while doing your task, and then move the file to a network share. This would mean that you have to "trust" that Console.WriteLine will stop working, saving you the trouble of wrapping each call. Then at the end of the task, you can move the file to a network location. You can combine this moving logic into a whole bunch of error handling and retry logic that won't affect your existing code.

+1


source







All Articles