demoncodemonkey
demoncodemonkey

Reputation: 11957

FileSystemWatcher doesn't trigger in Azure

I'm trying to find out why my FileSystemWatcher is working locally, but not when I deploy it to an Azure webapp.

I verified the files are being created in the webapp folder, but the watcher doesn't seem to trigger when the file is created. There are no related error/warning messages in the Azure logs or in my application logs. I created a sample app to investigate, and I see the same issue there.

public sealed class TestController : Controller
{
    private static readonly ILog _log = LogManager.GetLogger(typeof(TestController));
    private static readonly string _folder = ConfigurationManager.AppSettings["BasePath"];
    private static FileSystemWatcher _watcher;

    [HttpGet, Route("start-monitoring")]
    public ActionResult StartMonitoring()
    {
        if (_watcher != null)
            return new HttpStatusCodeResult(HttpStatusCode.OK);

        _watcher = new FileSystemWatcher(_folder, "*.*") { EnableRaisingEvents = true };

        _watcher.Created += (sender, args) =>
            _log.Debug($"YAY!!! Watcher triggered, new file found `{args.FullPath}`");

        _log.Debug($"Watcher started for folder `{_folder}`");
        return new HttpStatusCodeResult(HttpStatusCode.Created);
    }

    [HttpGet, Route("create-file/{filename}")]
    public async Task<ActionResult> CreateFileAsync(string filename)
    {
        string fullFilename = $"{_folder}\\{filename}.txt";
        using (var writer = new StreamWriter(fullFilename))
        {
            await writer.WriteAsync("Some content").ConfigureAwait(false);
        }

        _log.Debug($"Created file `{fullFilename}`");
        return new HttpStatusCodeResult(HttpStatusCode.OK);
    }
}

Locally

With the code above, when I go to http://localhost:23481/start-monitoring, this creates the FileSystemWatcher that monitors the C:\test folder.

Then when I go to http://localhost:23481/create-file/blahblah a file called blahblah.txt gets created in folder C:\test. The log file shows the file being created, as well as the FSW trigger to say that it's noticed a new file has appeared.

2019-08-15T10:37:54.705Z    DEBUG     TestProject.TestController
Watcher started for folder `C:\test`

2019-08-15T10:38:02.399Z    DEBUG     TestProject.TestController
Created file `C:\test\blahblah.txt`

2019-08-15T10:38:02.400Z    DEBUG     TestProject.TestController
YAY!!! Watcher triggered, new file found `C:\test\blahblah.txt`

2019-08-15T10:38:06.137Z    DEBUG     TestProject.TestController
Created file `C:\test\another.txt`

2019-08-15T10:38:06.141Z    DEBUG     TestProject.TestController
YAY!!! Watcher triggered, new file found `C:\test\another.txt`

Azure

I deployed the same code to Azure, the only code difference being the base path in the config. The logs show the FileSystemWatcher is created correctly to monitor the D:\home\site\wwwroot\test folder on the Azure webapp file system.

Then when I go to https://xxx.azurewebsites.net/create-file/blahblah a file called blahblah.txt gets created in folder D:\home\site\wwwroot\test. The log file shows the file being created, but doesn't show the FSW being triggered on create:

2019-08-15T10:43:01.681Z    DEBUG     TestProject.TestController
Watcher started for folder `D:\home\site\wwwroot\test`

2019-08-15T10:43:27.010Z    DEBUG     TestProject.TestController
Created file `D:\home\site\wwwroot\test\blahblah.txt`

2019-08-15T10:43:33.834Z    DEBUG     TestProject.TestController
Created file `D:\home\site\wwwroot\test\another.txt`

I've also tried creating a file in the folder manually and this still doesn't trigger the YAY!!! log entry. Is it a known issue that FileSystemWatcher doesn't trigger in Azure, or have I missed something?


Edit

I've assigned handlers to all events supported by FileSystemWatcher, i.e. Changed/Created/Deleted/ Disposed/Error/Renamed, and the only one that fires for me in Azure is Changed. I suppose I'll have to do some kind of hack to monitor the Changed event, I can probably assume if the file exists it was a "Created" event, otherwise a "Deleted" event.

Upvotes: 1

Views: 1384

Answers (1)

demoncodemonkey
demoncodemonkey

Reputation: 11957

I changed my code to listen to all events supported by the FileSystemWatcher. I found that the only event triggered on Azure is the Changed event. No other events are called. I can't find any documentation about this so it may be a bug or it may be as designed, who knows.

The fix I'm using for now is below, basically on the Changed event I check to see if the file exists, and if it does I assume it was a "file created event" otherwise a "file deleted event".

[HttpGet, Route("start-monitoring")]
public ActionResult StartMonitoring()
{
    if (_watcher != null)
        return new HttpStatusCodeResult(HttpStatusCode.OK);

    _watcher = new FileSystemWatcher(_folder, "*.*") { EnableRaisingEvents = true };

    //none of these events are triggered in Azure
    _watcher.Created += (sender, args) =>
        _log.Debug($"Watcher triggered `Created`, `{args.FullPath}`");
    _watcher.Deleted += (sender, args) =>
        _log.Debug($"Watcher triggered `Deleted`, `{args.FullPath}`");
    _watcher.Renamed += (sender, args) =>
        _log.Debug($"Watcher triggered `Renamed`, `{args.OldFullPath}` to `{args.FullPath}`");
    _watcher.Error += (sender, args) =>
        _log.Debug($"Watcher triggered `Error`, `{args.GetException().ToString()}`");
    _watcher.Disposed += (sender, args) =>
        _log.Debug($"Watcher triggered `Disposed`");

    //Changed is the only event that gets triggered in Azure
    _watcher.Changed += (sender, args) =>
    {
        if (System.IO.File.Exists(args.FullPath))
            _log.Debug($"Watcher triggered `Changed (created)`, `{args.FullPath}`");
        else
            _log.Debug($"Watcher triggered `Changed (deleted)`, `{args.FullPath}`");
    };

    _log.Debug($"Watcher started for folder `{_folder}`");

    return new HttpStatusCodeResult(HttpStatusCode.Created);
}

This seems to work fine for me now:

2019-08-16T08:54:37.419Z    DEBUG     TestProject.TestController
Watcher started for folder `C:\test`

2019-08-16T08:55:16.625Z    DEBUG     TestProject.TestController
Created file `C:\test\moo.txt`

2019-08-16T08:55:16.634Z    DEBUG     TestProject.TestController
Watcher triggered `Changed (created)`, `C:\test\moo.txt`

2019-08-16T08:55:50.096Z    DEBUG     TestProject.TestController
Created file `C:\test\poop.txt`

2019-08-16T08:55:50.101Z    DEBUG     TestProject.TestController
Watcher triggered `Changed (created)`, `C:\test\poop.txt`

Upvotes: 1

Related Questions