Azure / data-api-builder

Data API builder provides modern REST and GraphQL endpoints to your Azure Databases and on-prem stores.
https://aka.ms/dab/docs
MIT License
787 stars 142 forks source link

[Bug]: Error message 'Could not initialize the engine with the runtime config file: dab-config.json' isn't clear enough #2260

Open TimNilimaa opened 2 weeks ago

TimNilimaa commented 2 weeks ago

What happened?

Running latest docker image with the provided example from here https://learn.microsoft.com/en-us/azure/data-api-builder/how-to-run-container Only alteration I made was to the password in the file. { "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json", "data-source": { "database-type": "mssql", "connection-string": "Server=host.docker.internal\mssql,1433;Initial Catalog=Library;User Id=sa;Password=;TrustServerCertificate=true;" }, "entities": { "book": { "source": "dbo.Books", "permissions": [ { "actions": [ "read" ], "role": "anonymous" } ] } } }

Main issue is that the error message is too abstract in that it doesn't say anything useful to the 'end user' on what is the issue with the config file.

Version

1.1.7

What database are you using?

Azure SQL

What hosting model are you using?

Container Apps, Custom Docker host

Which API approach are you accessing DAB through?

REST, GraphQL

Relevant log output

Starting the runtime engine...
Loading config file from dab-config.json.
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {2abf94d1-f041-473a-9bbc-d440b03ca439} may be persisted to storage in unencrypted form.
fail: Azure.DataApiBuilder.Service.Startup[0]
      Unable to complete runtime initialization. Refer to exception for error details.
      System.NullReferenceException: Object reference not set to an instance of an object.
         at Azure.DataApiBuilder.Core.Configurations.RuntimeConfigValidator.ValidateAppInsightsTelemetryConnectionString(RuntimeConfig runtimeConfig) in /_/src/Core/Configurations/RuntimeConfigValidator.cs:line 128
         at Azure.DataApiBuilder.Core.Configurations.RuntimeConfigValidator.ValidateConfigProperties() in /_/src/Core/Configurations/RuntimeConfigValidator.cs:line 84
         at Azure.DataApiBuilder.Service.Startup.PerformOnConfigChangeAsync(IApplicationBuilder app) in /_/src/Service/Startup.cs:line 602
fail: Azure.DataApiBuilder.Service.Startup[0]
      Could not initialize the engine with the runtime config file: dab-config.json
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
Unable to launch the Data API builder engine.

Code of Conduct

kallsu commented 2 weeks ago

I agree.

To resolve is required to inspect the code and understand that the "telemetry" configuration should be added in the configuration file, under the section "runtime".

The solution is explained Use Application Insight

abhishekkumams commented 1 week ago

@TimNilimaa , can you share the runtime section of the config file? specifically the telemetry section? Looking at the logs seems like an invalid AppInsights connection string.

JerryNixon commented 1 week ago

Related #1925

kallsu commented 1 week ago

@abhishekkumams This is my procedure, probably can help you.

I started from the documentation Run In Container

In the sample configuration missing of the telemetry configuration, explained in the other section, and I have the same result of @TimNilimaa

This is my working configuration of dab-config.json

{
    "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
    "data-source": {
        "database-type": "mssql",
        "connection-string": "MyHandsomeConnectionString"
    },
    "runtime": {
        "telemetry": {
            "application-insights": {
                "enabled": true,
                "connection-string": "InstrumentationKey=......;IngestionEndpoint=https://REGION.in.applicationinsights.azure.com/;LiveEndpoint=https://REGION.livediagnostics.monitor.azure.com/;ApplicationId=...."
            }
        }
    },
  "entities": {  
   }

This configuration worked for the time that I used.

However, according to my analysis, the bug is placed here, line 128 of RuntimeConfigValidator.cs taken from main branch, at today.

public void ValidateAppInsightsTelemetryConnectionString(RuntimeConfig runtimeConfig)
    {
        if (runtimeConfig.Runtime!.Telemetry is not null && runtimeConfig.Runtime.Telemetry.ApplicationInsights is not null)
        {
            ApplicationInsightsOptions applicationInsightsOptions = runtimeConfig.Runtime.Telemetry.ApplicationInsights;
            if (applicationInsightsOptions.Enabled && string.IsNullOrWhiteSpace(applicationInsightsOptions.ConnectionString))
            {
                HandleOrRecordException(new DataApiBuilderException(
                    message: "Application Insights connection string cannot be null or empty if enabled.",
                    statusCode: HttpStatusCode.ServiceUnavailable,
                    subStatusCode: DataApiBuilderException.SubStatusCodes.ConfigValidationError));
            }
        }
    }

So, following the main purpose of this topic, and, using the documented configuration, the IF-cases are passed with success, and, a possible solution can be achieved following 2 possible cases:

  1. Review the initialization of the default values for ApplicationInsightsOptions applicationInsightsOptions and be compliant with the example, OR,

  2. Keep the code like that but modify the message: "Application Insights connection string cannot be null or empty if enabled.", with a proper text user-friendly message, such as "The default configuration has the AppInsight telemetry enabled, please refer to the link [PUT THE LINK HERE] to complete the actual configuration"

According to my opinion, the 2nd one is preferable because it is cost-effective and reduce the development effort. Of course, the message can be different from the suggestion of mine.

P.S.: @JerryNixon I am sorry, but I aggregated all the information here.