question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't copy Serilog file on Xamarin.Android while logger is active

See original GitHub issue

We are currently using Serilog as bases for logging in Xamarin.Android project. We have a function in the app which allows users to push their local logs on demand. So, we’ll go to root logging directory, copy the existing logs to a new temp location, zip them and then upload to our cloud. Everything was working fine till the latest Xamarin.Android release. Now, as soon as you try to copy the file which is currently being used by Serilog File sink, your receive the following exception System.IO.IOException: Sharing violation on path

Here is example that I’ve created that demonstrates the issue SerilogSample.zip

Here is a small piece from the above sample


LoggerConfiguration loggerConfig = new LoggerConfiguration()
                                                   .MinimumLevel.Verbose()
                                                   .WriteTo.Debug()
                                                   .WriteTo.File(new JsonFormatter(),
                                                                 logPath,
                                                                 rollingInterval:RollingInterval.Day
                                                                 // ,shared:true
                                                                );
Logger logger = loggerConfig.CreateLogger();
for(int index = 0; index < 10; index++)
{
    logger.Information($"Log message {index}");
}
// logger.Dispose();
string[] logFiles = Directory.GetFiles(rootLoggingDirPath);
foreach(string file in logFiles)
{
    File.Copy(file, Path.Combine(logArchive, Path.GetFileName(file)));
}

If I uncomment the line logger.Dispose(); everything will start to work as expected. But without that the app crashes on line File.Copy The project has 3 targets - iOS, Droid & .NET Core console. The app runs perfectly fine on Console both Mac & Windows, but not on iOS/Droid. This code also worked perfectly fine on VS 2017.

Another aspect is that I tried to set sharing flag to true, and file wasn’t being created at all. Only later I discovered that shared files are not supported in Xamarin in another issue #44

I dug a little bit deeper and checked how file sink opens up a stream to write, and I was able to reproduce this issue without Serilog using ordinary streams and File.Copy. Here’s the sample

using(Stream outputStream = File.Open(testFile, FileMode.Append, FileAccess.Write, FileShare.Read))
using (StreamWriter outputFile = new StreamWriter(outputStream, encoding))
{
    for(int index = 0; index < 10; index++)
    {
        outputFile.WriteLine($"Log message {index}");
    }
    outputFile.Flush();
    File.Copy(testFile, archiveFile);
}

The above code has exact behavior as the Serilog issue I am experiencing. Probably this is not a Serilog issue but something that is related to Xamarin, and in fact I’ve created an issue in Xamairn.Android repo as well.

For now, I’m seeking for workaround. The ideal solution would be to force the Serilog file sink to create a new file on demand, so all locks from existing files are removed, and I’ll be able to copy that file with ease. In fact, this is the initial way I wanted to implement log upload, and I wasn’t able to find such solution in File sink, and went with hard route of tracking exact file position, and then using streams to copy files partially as they might have been already uploaded partially previously. We can’t dispose the logger either, cause it’s dependency injected and is used in other places of the app. So, couple of questions

  1. What can be done to workaround this situation? Is it possible to force a new file to be created?
  2. Is there something that can be done to overcome this locking issue in general from Serilog code perspective without Xamarin intervention?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
kyurkchyancommented, Aug 13, 2019

After more thorough investigation I can see that File.Copy issue is not Serilog’s issue. We’ve found a workaround and instead of using File.Copy we use the following code for copying files

public static async Task CopyFileAsync(string sourceFilePath, string destinationFilePath)
{
    using(FileStream sourceStream = File.Open(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using(FileStream destinationStream = File.Create(destinationFilePath))
    {
        await sourceStream.CopyToAsync(destinationStream);
    }
}

The crucial aspect in here is that you use File.Open method with parameter FileShare.ReadWrite to make this stream work nicely with Serilog’s internal open write stream. Though performance testing revealed this approach to be 5 times slower than File.Copy in our system the largest file is 30MB and it’s still matter of milliseconds to do the copy on Android device, so the workaround was acceptable in our scenario. I’m sure If I spend several hours I’d be able to optimize the stream copy process a bit, but it’s not going to be as optimal as File.Copy ever.

Thus, I’d say this issue is more feature request than an issue. If we had a possibility to force the loggers to roll over a new file, than all of the problems would be resolved.

0reactions
nblumhardtcommented, Jun 1, 2020

Hi @mikegoatly ! Yes, that’s the goal of the shared file sink - multiple processes can concurrently log to the same file 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

Writing logs to file using Xamarin.Forms and Serilog
First, you have to allow permissions in your AndroidManifest.xml file. <uses-permission android:name="android.permission.
Read more >
Bringing .NET extensions to Xamarin.Forms
This blog post will show you a way of integrating configuration, dependency injection, logging and localization of the .NET extensions stack ...
Read more >
ASP.NET Core Logging with Azure App Service and Serilog
Application logging can be enabled in the Azure portal under the app service's 'Diagnostic logs' page. Logging can be sent either to the...
Read more >
Android Debug Log - Xamarin
The Debug Log tool provides a way to view log output while debugging an app through Visual Studio. The debug log supports the...
Read more >
C# Log Collection
Log to a file and then tail that file with your Datadog Agent. Enable Agentless logging. Use the Serilog sink. This page details...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found