Skip to content

PathRoller doesn't log to SelfLog on exception #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pvandervelde opened this issue Nov 29, 2020 · 11 comments
Closed

PathRoller doesn't log to SelfLog on exception #192

pvandervelde opened this issue Nov 29, 2020 · 11 comments

Comments

@pvandervelde
Copy link
Contributor

When the PathRoller encounters an exception it doesn't log to the Serilog self-log. Using the following code

var selfLogPath = "c://logs//serilog.log";
string logsDirectory = Path.GetDirectoryName(selfLogPath);
if (!Directory.Exists(logsDirectory))
{
    Directory.CreateDirectory(logsDirectory);
}

Serilog.Debugging.SelfLog.Enable(TextWriter.Synchronized(File.CreateText(selfLogPath)));

var serilogger = new LoggerConfiguration()
    .ReadFrom.AppSettings()
    .CreateLogger();

serilogger.Information("message");

with the following app.config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
    <add key="serilog:minimum-level" value="Verbose" />

    <add key="serilog:using:Console" value="Serilog.Sinks.Console"/>
    <add key="serilog:write-to:Console"/>

    <add key="serilog:using:File" value="Serilog.Sinks.File" />
    <add key="serilog:write-to:File.fileSizeLimitBytes" value="104857600" />
    <add key="serilog:write-to:File.formatter" value="Serilog.Formatting.Json.JsonFormatter" />
    <add key="serilog:write-to:File.path" value="xxxc:/logs/test-log.log" />
    <add key="serilog:write-to:File.rollOnFileSizeLimit" value="true" />
</appSettings>
</configuration>

Running this code throws the following exception

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NotSupportedException: The given path's format is not supported.
    at System.Security.Permissions.FileIOPermission.EmulateFileIOPermissionChecks(String fullPath)
    at System.Security.Permissions.FileIOPermission.QuickDemand(FileIOPermissionAccess access, String fullPath, Boolean checkForDuplicates, Boolean needFullPath)
    at Serilog.Sinks.File.PathRoller..ctor(String path, RollingInterval interval)
    at Serilog.Sinks.File.RollingFileSink..ctor(String path, ITextFormatter textFormatter, Nullable`1 fileSizeLimitBytes, Nullable`1 retainedFileCountLimit, Encoding encoding, Boolean buffered, Boolean shared, RollingInterval rollingInterval, Boolean rollOnFileSizeLimit, FileLifecycleHooks hooks)
    at Serilog.FileLoggerConfigurationExtensions.ConfigureFile(Func`4 addSink, ITextFormatter formatter, String path, LogEventLevel restrictedToMinimumLevel, Nullable`1 fileSizeLimitBytes, LoggingLevelSwitch levelSwitch, Boolean buffered, Boolean propagateExceptions, Boolean shared, Nullable`1 flushToDiskInterval, Encoding encoding, RollingInterval rollingInterval, Boolean rollOnFileSizeLimit, Nullable`1 retainedFileCountLimit, FileLifecycleHooks hooks)
    at Serilog.FileLoggerConfigurationExtensions.File(LoggerSinkConfiguration sinkConfiguration, ITextFormatter formatter, String path, LogEventLevel restrictedToMinimumLevel, Nullable`1 fileSizeLimitBytes, LoggingLevelSwitch levelSwitch, Boolean buffered, Boolean shared, Nullable`1 flushToDiskInterval, RollingInterval rollingInterval, Boolean rollOnFileSizeLimit, Nullable`1 retainedFileCountLimit, Encoding encoding, FileLifecycleHooks hooks)
    --- End of inner exception stack trace ---
    at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
    at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    at Serilog.Settings.KeyValuePairs.KeyValuePairSettings.ApplyDirectives(List`1 directives, IList`1 configurationMethods, Object loggerConfigMethod, IReadOnlyDictionary`2 declaredSwitches)
    at Serilog.Settings.KeyValuePairs.KeyValuePairSettings.Configure(LoggerConfiguration loggerConfiguration)
    at Serilog.Configuration.LoggerSettingsConfiguration.Settings(ILoggerSettings settings)
    at Serilog.Configuration.LoggerSettingsConfiguration.KeyValuePairs(IEnumerable`1 settings)
    at Serilog.Configuration.LoggerSettingsConfiguration.Settings(ILoggerSettings settings)
    at MyApp.Tests.ConsoleApp.Program.LogWithSerilogDirect(String selfLogPath)
    at MyApp.Tests.ConsoleApp.Program.Main()

This exception terminates the application because it is not caught anywhere. Given that Serilog internally handles exceptions and that we have turned on the self-log I would have expected that the PathRoller would have caught the exception and then written it to the selflog.

We can of course catch the exception but because the exception occurs during the configuration of our logging system it means that it is more difficult to store the information in a way that we can obtain it from the server.

@nblumhardt
Copy link
Member

Thanks, we'll take a look 👍

@pvandervelde
Copy link
Contributor Author

After digging a bit further it looks like our issue is caused by the fact that the RollingFileSink is created in the configuration object outside the try..catch that writes to the self log. See here:

if (rollOnFileSizeLimit || rollingInterval != RollingInterval.Infinite)

I'm not sure if there is an architectural reason for this code so it might well be not the reason for our issue.

If this is the correct solution I might be able to find some time to create a PR if that would help it get fixed.

@nblumhardt
Copy link
Member

In general, the Serilog API will throw for usage errors (e.g. passing null when a value is required), and SelfLog for runtime/deployment errors like the one here. It's a fuzzy distinction, so we do a bit of case-by-case inspection :-)

I think widening the try/catch block would make sense, here.

@pvandervelde
Copy link
Contributor Author

Makes sense. I forked and made the change here: https://github.com/pvandervelde/serilog-sinks-file/tree/feature/fix-192. I tried running the build.ps1 but it complains about

C:\Program Files\dotnet\sdk\3.1.202\NuGet.targets(124,5): error : '4.1.0-feature/fi-local-7b13f1e' is not a valid version string. (Parameter 'value') [F:\vcs\github\pvandervelde\serilog-sinks-file\src\Serilog.Sinks.File\Serilog.Sinks.File.csproj]

I'm guessing I named the branch wrong? Is there a "How to contribute" document somewhere?

@preet-serko
Copy link

@nblumhardt Did you get a chance to review @pvandervelde fix at all please?

@nblumhardt
Copy link
Member

Thanks for the nudge @preet-serko. @pvandervelde, the issue will be the slash in the branch name, sorry.

@pvandervelde
Copy link
Contributor Author

Ah right. I'll change the branch name and try again

@pvandervelde
Copy link
Contributor Author

@nblumhardt I've created a PR but I started from the master branch. Do you want me to rebase on dev?

@nblumhardt
Copy link
Member

Thanks Petrik, that would be great.

@pvandervelde
Copy link
Contributor Author

@nblumhardt Rebased and force pushed to the PR. Let me know if any other changes are required.

@nblumhardt
Copy link
Member

That's great, thanks @pvandervelde 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants