Azure / azure-functions-host

The host/runtime that powers Azure Functions
https://functions.azure.com
MIT License
1.91k stars 435 forks source link

Explicitly handle and log startup errors #4705

Open brettsam opened 4 years ago

brettsam commented 4 years ago

For example, if an invalid storage connection string is set in an App Setting, we will throw an exception very early in the startup pipeline (specifically in BlobStorageSecretsRepository). This will go unhandled and cause the process to exit, leaving us with no trace of the error.

We need to catch and log this properly.

fabiocav commented 4 years ago

Flagging this as a supportability issue.

fabiocav commented 4 years ago

Need to flush out the details and perhaps break this up before moving forward with implementation.

fabiocav commented 4 years ago

This needs clarification and better design. Moving back to triaged

brettsam commented 4 years ago

One scenario we need to handle better: Exceptions being thrown from Startup.cs. Today App Insights isn't initialized so these logs can just disappear and customers can't tell that they have an exception.

Possible solution:

If we catch an exception in a startup, we:

  1. Make sure the exception is returned as part of the Errors that the portal sees when pinging for host status. I'm fairly certain this is true today but we need to double-check.
  2. Explicitly check the environment for App Insights keys. If they exist, create a one-off TelemetryClient so we can log this error to the customer. This would go outside of our normal App Insights configuration (since startup was canceled by the exception), but it would give better insight to customers when they hit this. Today they get nothing.

One example: https://github.com/Azure/azure-functions-host/issues/6278#issuecomment-653049243

ChristopherL-STCU commented 3 years ago

Is there currently a way to surface exception information in the startup of a v3 app? For example, when my startup consists of:

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        throw new NotImplementedException("Does this end up anywhere?");
    }
}

And I have an APPINSIGHTS_INSTRUMENTATIONKEY defined in Application Settings with a host.json containing:

    "logging": {
        "fileLoggingMode": "always",
        "logLevel": {
            "default": "Trace"
        },
        "console": {
            "isEnabled": "true"
        }
    }

I cannot find the exception message anywhere. Should I expect to? Is it possible to?

brettsam commented 3 years ago

One thing you can always do if you're using App Insights is try/catch around your Startup and then log the exception directly to App Insights yourself. This is effectively what I'm going to propose we do in the host. The current issue is that when we're calling your Startup class, we have not yet constructed the App Insights services (since we're still in DI initialization) so the exception isn't logged automatically.

I'm thinking something like:

try
{
    // do all your DI stuff
}
catch (Exception ex)
{
    var config = new TelemetryConfiguration(Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY"));
    var client = new TelemetryClient(config);
    client.TrackException(ex);
    client.Flush();

    throw;
}
norvegec commented 3 years ago

Ofc we can write all the "wiring" ourselfves, the question is - should we? Azure functions states the serverless aproach - and logging to attached AppInsights exceptions thrown in Startup class should be somthing that host does.

MTCMarkFranco commented 3 years ago

Hi All,

Anything wrong with this approach:

define a private member in startup class:

private ILogger Logger()
{

   var loggerFactory = LoggerFactory.Create(startupLogbuilder =>
           {
                      startupLogbuilder.AddConsole();
                      startupLogbuilder.AddDebug();
           }); 

  return loggerFactory.CreateLogger<Startup>();
}

then I can reference it within Configure and ConfigureAppConfiguration and any other override like so:

this.Logger().LogError(errorMessage);

Does anyone see any issues with this? I've tested it and works consistently.

konstantinmiller commented 1 week ago

I am running a Python function app and have the same issue. No access to start-up logs. Sometimes, for example, due to a missing environment variable, the function won't properly start and all I get is...

"No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.)."

...while the error is actually totally unrelated to public classes or methods or binding extensions.

Any plans to make this happen anytime soon?