Skip to content
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.

Always log startup exceptions #1153

Closed
wants to merge 1 commit into from
Closed

Always log startup exceptions #1153

wants to merge 1 commit into from

Conversation

cwe1ss
Copy link
Contributor

@cwe1ss cwe1ss commented Jul 31, 2017

The following sample currently does not send the exception to the logger:

public class Program
{
    public static void Main(string[] args)
    {
        new WebHostBuilder()
            .UseKestrel()
            .ConfigureLogging(logging =>
             {
                 logging.AddConsole();
             })
            .Configure(app =>
            {
                throw new InvalidOperationException("Something went wrong!");
            })
            .Build()
            .Run();
    }
}

It will send it if CaptureStartupErrors(true) is called. However, this will also keep the application running and display an error to the user.

I'm using Service Fabric so I want the application to crash in order to let Service Fabric know that something is wrong. And I also want the exception in my logger.

Before logging was using DI, I created my own logger factory and caught startup exceptions manually (with some ugly code). This is no longer possible/reasonable now.

This PR would always send startup exceptions to the logger, no matter what value CaptureStartupErrors has.

We already discussed this in #622 and one concern was that this is a case of a "logging and re-throw anti-pattern" however I think that this is acceptable in this case as this is a very common use-case (IMO). Also, due to recent changes (e.g. logging DI) there's less and less reasons to have logic outside of the WebHostBuilder that would want to prevent that log message.

if (!_options.CaptureStartupErrors)
throw;

EnsureServer();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason you moved this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't called before when CaptureStartupErrors=false. Since it re-throws, there's no need to create the server.

// Write errors to standard out so they can be retrieved when not in development mode.
Console.Out.WriteLine("Application startup exception: " + ex.ToString());
var logger = _applicationServices.GetRequiredService<ILogger<WebHost>>();
logger.ApplicationError(ex);

if (!_options.CaptureStartupErrors)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the braces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed the braces - sorry for that!

{
// EnsureApplicationServices may have failed due to a missing or throwing Startup class.
if (_applicationServices == null)
{
_applicationServices = _applicationServiceCollection.BuildServiceProvider();
}

EnsureServer();

// Write errors to standard out so they can be retrieved when not in development mode.
Console.Out.WriteLine("Application startup exception: " + ex.ToString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't still want the ConsoleWriteline do we?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd keep it as people probably don't use the Console Logger in non-development environments and having the console output as an additional troubleshooting mechanism could be helpful.

E.g. in Service Fabric you can redirect console output to a file - by keeping this Console.WriteLine one would at least get the startup messages ("Listening on...") and any startup exceptions.

@davidfowl
Copy link
Member

This looks good to me.

@davidfowl
Copy link
Member

This is something we might want to back port to 1.x.

/cc @DamianEdwards @Eilon @muratg

@muratg
Copy link

muratg commented Aug 7, 2017

@jkotalik could you file two bugs to bring this back to 1.0.x and 1.1.x?

@jkotalik
Copy link
Contributor

jkotalik commented Aug 7, 2017

#1159 and #1160. Once fully approved I'll add this to 2.0.x, 1.1.x, and 1.0.x

@Tratcher
Copy link
Member

Tratcher commented Aug 7, 2017

@jkotalik please review and merge.

@jkotalik
Copy link
Contributor

jkotalik commented Aug 7, 2017

@cwe1ss Would it be possible to add tests for this change?

@cwe1ss
Copy link
Contributor Author

cwe1ss commented Aug 8, 2017

@jkotalik I added two tests. Hope they are ok?!

@jkotalik
Copy link
Contributor

jkotalik commented Aug 8, 2017

Looks good! @muratg @Eilon how do you want to handle this for 2.0.x? As a patch?

@jkotalik
Copy link
Contributor

jkotalik commented Aug 8, 2017

Merged with: 07f96a4

@Eilon
Copy link
Member

Eilon commented Aug 8, 2017

If I understand correctly, this has a simple workaround: just enable the setting, right? If that's the case, then this isn't particularly suitable for a patch candidate.

@Tratcher
Copy link
Member

Tratcher commented Aug 8, 2017

The setting has significant side effects. It keeps your app running and serves up an error page rather than letting it crash and restart.

@Eilon
Copy link
Member

Eilon commented Aug 8, 2017

And we'd want to turn that behavior on by default? That's a pretty significant breaking change, no? If another process is monitoring the Kestrel process (dotnet.exe), it won't know that it's dead and it won't spin a new one up... is that correct?

@Tratcher
Copy link
Member

Tratcher commented Aug 8, 2017

This change doesn't turn that behavior on by default, it only moves things around so that the logging happens prior to the crash. Before no logging would happen for the crash scenario.

@Eilon
Copy link
Member

Eilon commented Aug 8, 2017

Ok sorry I'm not quite understanding this. What behavior exactly are we considering porting to 1.0.x/1.1.x? What exactly would it do by default that is different from what it used to do?

@Eilon
Copy link
Member

Eilon commented Aug 8, 2017

Ok just synced with @Tratcher on IM. We're only changing that the logging will still happen. No change to whether the server lives or dies.

@jkotalik jkotalik closed this Aug 9, 2017
@cwe1ss
Copy link
Contributor Author

cwe1ss commented Aug 9, 2017

Thank you very much for accepting this PR!! 👍

@cwe1ss cwe1ss deleted the cweiss/LogStartupErrors branch August 9, 2017 07:12
@Tratcher Tratcher added this to the 2.1.0 milestone Sep 14, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants