* Remove static text from code. Set the value in appsettings

* Update azure-pipelines.yml for Azure Pipelines

Temporary yml file change

* Use azureAdInstance parameter to configure AzureServiceTokenProvider for different clouds

* Temporarily log unhandled exceptions using the Trace library.

* Show identity model errors

* Configure feature flags for each data provider

* Throw exceptions to hopefully find them in the event log

* Add App Service application logging to RuntimeHost

* Send exception events to windows event log

* Add health check for kusto data provider. Add a dependency checker API.

* Create ExecuteClusterQuery overload method to query Kusto given query, cluster, and database.

* Kusto health check calling incorrect KustoExecuteClusterQuery overloaded function. Correct this behavior.

* Add configurable AAD resource for Observer. Before it was just a static value.

* Revert "Update azure-pipelines.yml for Azure Pipelines"

This reverts commit 64fb9d5d77.

* Added some comments for the application logging

* Small refactor

* Add azure pipelines yml configuration file

* Make requestId, operationName required parameters

* I forgot to modify the interface and decorator class
This commit is contained in:
Hawk Foreste 2020-01-28 14:49:18 -08:00 коммит произвёл GitHub
Родитель 43e8b248ab
Коммит ce0a8c88c2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 232 добавлений и 40 удалений

Просмотреть файл

@ -0,0 +1,38 @@
# ASP.NET Core (.NET Framework)
# Build and test ASP.NET Core projects targeting the full .NET Framework.
# Add steps that publish symbols, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core
trigger:
- nationalcloud
pool:
vmImage: 'windows-latest'
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'build'
projects: '$(solution)'
configuration: '$(buildConfiguration)'
- task: DotNetCoreCLI@2
inputs:
command: 'test'
- task: DotNetCoreCLI@2
inputs:
command: publish
publishWebProjects: True
arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)'
zipAfterPublish: True
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: backend-drop1

Просмотреть файл

@ -44,16 +44,14 @@ namespace Diagnostics.CompilerHost
var builtConfig = builder.Build();
string keyVaultConfig = Helpers.GetKeyvaultforEnvironment(hostingEnvironment.EnvironmentName);
var tokenProvider = new AzureServiceTokenProvider();
var tokenProvider = new AzureServiceTokenProvider(azureAdInstance: builtConfig["Secrets:AzureAdInstance"]);
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
tokenProvider.KeyVaultTokenCallback
)
);
builder.AddAzureKeyVault($"https://{builtConfig[keyVaultConfig]}.vault.azure.net/",
keyVaultClient,
new DefaultKeyVaultSecretManager());
builder.AddAzureKeyVault(builtConfig[keyVaultConfig], keyVaultClient, new DefaultKeyVaultSecretManager());
Configuration = builder.Build();
}

Просмотреть файл

@ -32,7 +32,7 @@ namespace Diagnostics.DataProviders
var builtConfig = builder.Build();
var tokenProvider = new AzureServiceTokenProvider();
var tokenProvider = new AzureServiceTokenProvider(azureAdInstance: builtConfig["Secrets:AzureAdInstance"]);
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
tokenProvider.KeyVaultTokenCallback
@ -40,9 +40,7 @@ namespace Diagnostics.DataProviders
);
string keyVaultConfig = Helpers.GetKeyvaultforEnvironment(env.EnvironmentName);
builder.AddAzureKeyVault($"https://{builtConfig[keyVaultConfig]}.vault.azure.net/",
keyVaultClient,
new DefaultKeyVaultSecretManager());
builder.AddAzureKeyVault(builtConfig[keyVaultConfig], keyVaultClient, new DefaultKeyVaultSecretManager());
_configuration = builder.Build();
}

Просмотреть файл

@ -52,6 +52,11 @@
public string AppKey { get; set; }
/// <summary>
/// Enabled
/// </summary>
[ConfigurationName("Enabled")]
public bool Enabled { get; set; }
/// Header value based on which we block calls to ASC
/// </summary>
[ConfigurationName("DiagAscHeader")]

Просмотреть файл

@ -39,6 +39,12 @@
[ConfigurationName("Apiversion")]
public string Apiversion { get; set; }
/// <summary>
/// Enabled
/// </summary>
[ConfigurationName("Enabled")]
public bool Enabled { get; set; }
public void PostInitialize()
{
}

Просмотреть файл

@ -44,13 +44,9 @@ namespace Diagnostics.DataProviders
/// </summary>
public string AADAuthority { get; set; }
/// <summary>
/// Gets resourceId for WAWSObserver AAD app.
/// </summary>
public string WawsObserverResourceId
{
get { return "d1abfd91-e19c-426e-802f-a6c55421a5ef"; }
}
[ConfigurationName("AADResource")]
public string AADResource { get; set; }
/// <summary>
/// Gets uri for SupportObserverResourceAAD app.

Просмотреть файл

@ -1,23 +1,39 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Diagnostics.ModelsAndUtils.Models;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Diagnostics.DataProviders
{
public class DiagnosticDataProvider
public class DiagnosticDataProvider : IDiagnosticDataProvider, IHealthCheck
{
private OperationDataCache _cache;
private IDataProviderConfiguration _configuration;
public DiagnosticDataProvider(OperationDataCache cache)
{
_cache = cache;
}
public DiagnosticDataProvider(OperationDataCache cache, IDataProviderConfiguration configuration)
{
_cache = cache;
_configuration = configuration;
}
public DataProviderMetadata Metadata { get; set; }
public IDataProviderConfiguration DataProviderConfiguration => _configuration;
protected Task<T> GetOrAddFromCache<T>(string key, Func<string, CacheMember> addFunction)
{
return Convert.ChangeType(_cache.GetOrAdd(key, addFunction), typeof(Task<T>)) as Task<T>;
}
public DataProviderMetadata Metadata { get; set; }
public virtual Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
return null;
}
}
}

Просмотреть файл

@ -2,8 +2,10 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Diagnostics.ModelsAndUtils.Models;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Diagnostics.DataProviders
{
@ -15,7 +17,7 @@ namespace Diagnostics.DataProviders
public string OperationName;
}
public class KustoDataProvider : DiagnosticDataProvider, IDiagnosticDataProvider, IKustoDataProvider
public class KustoDataProvider : DiagnosticDataProvider, IKustoDataProvider
{
private KustoDataProviderConfiguration _configuration;
private IKustoClient _kustoClient;
@ -39,6 +41,12 @@ namespace Diagnostics.DataProviders
return await ExecuteQuery(query, DataProviderConstants.FakeStampForAnalyticsCluster, requestId, operationName);
}
public async Task<DataTable> ExecuteClusterQuery(string query, string cluster, string databaseName, string requestId, string operationName)
{
await AddQueryInformationToMetadata(query, cluster, operationName);
return await _kustoClient.ExecuteQueryAsync(query, cluster, databaseName, requestId, operationName);
}
public async Task<DataTable> ExecuteQuery(string query, string stampName, string requestId = null, string operationName = null)
{
var cluster = await GetClusterNameFromStamp(stampName);
@ -91,5 +99,31 @@ namespace Diagnostics.DataProviders
{
return await _kustoHeartBeatService.GetClusterNameFromStamp(stampName);
}
public async override Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
DataTable response;
Exception kustoException = null;
HealthCheckResult result;
try
{
var cluster = _configuration.RegionSpecificClusterNameCollection.Values.First();
response = await ExecuteClusterQuery(_configuration.HeartBeatQuery, cluster, _configuration.DBName, null, null);
}
catch (Exception ex)
{
kustoException = ex;
}
finally
{
result = new HealthCheckResult(
kustoException == null ? HealthStatus.Healthy : HealthStatus.Unhealthy,
description: "Kusto Health Check",
kustoException
);
}
return result;
}
}
}

Просмотреть файл

@ -28,6 +28,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.2.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="3.1.1" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.2" />
<PackageReference Include="Microsoft.Win32.Registry" Version="4.6.0" />
</ItemGroup>

Просмотреть файл

@ -2,6 +2,6 @@
{
public interface IDiagnosticDataProvider
{
// TODO
IDataProviderConfiguration DataProviderConfiguration { get; }
}
}

Просмотреть файл

@ -7,6 +7,8 @@ namespace Diagnostics.DataProviders
{
Task<DataTable> ExecuteClusterQuery(string query, string requestId = null, string operationName = null);
Task<DataTable> ExecuteClusterQuery(string query, string cluster, string databaseName, string requestId, string operationName);
Task<DataTable> ExecuteQuery(string query, string stampName, string requestId = null, string operationName = null);
Task<KustoQuery> GetKustoQuery(string query, string stampName);

Просмотреть файл

@ -7,7 +7,7 @@ namespace Diagnostics.DataProviders
{
public IKustoDataProvider DataProvider;
public KustoLogDecorator(DataProviderContext context, IKustoDataProvider dataProvider) : base(context, dataProvider.GetMetadata())
public KustoLogDecorator(DataProviderContext context, IKustoDataProvider dataProvider) : base((DiagnosticDataProvider)dataProvider, context, dataProvider.GetMetadata())
{
DataProvider = dataProvider;
}
@ -22,6 +22,11 @@ namespace Diagnostics.DataProviders
return ExecuteQuery(query, DataProviderConstants.FakeStampForAnalyticsCluster, requestId, operationName);
}
public Task<DataTable> ExecuteClusterQuery(string query, string cluster, string databaseName, string requestId, string operationName)
{
return ExecuteClusterQuery(query, cluster, databaseName, requestId, operationName);
}
public Task<KustoQuery> GetKustoQuery(string query, string stampName)
{
return MakeDependencyCall(DataProvider.GetKustoQuery(query, stampName));

Просмотреть файл

@ -7,12 +7,21 @@ using Diagnostics.ModelsAndUtils.Models;
namespace Diagnostics.DataProviders
{
internal abstract class LogDecoratorBase : IMetadataProvider
public abstract class LogDecoratorBase : IMetadataProvider
{
public DiagnosticDataProvider DataProvider { get; private set; }
protected string _requestId;
private DataProviderMetadata _metadataProvider;
private CancellationToken _dataSourceCancellationToken;
protected LogDecoratorBase(DiagnosticDataProvider dataProvider, DataProviderContext context, DataProviderMetadata metaData)
{
DataProvider = dataProvider;
_metadataProvider = metaData;
_requestId = context.RequestId;
_dataSourceCancellationToken = context.DataSourcesCancellationToken;
}
protected LogDecoratorBase(DataProviderContext context, DataProviderMetadata metaData)
{
_metadataProvider = metaData;

Просмотреть файл

@ -5,6 +5,8 @@ using Diagnostics.RuntimeHost.Utilities;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using System.Collections.Generic;
using Diagnostics.DataProviders;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Diagnostics.RuntimeHost.Controllers
{
@ -34,5 +36,12 @@ namespace Diagnostics.RuntimeHost.Controllers
return Ok("Server is up and running.");
}
[HttpGet("/dependencyCheck")]
public async Task<IEnumerable<HealthCheckResult>> DependencyCheck()
{
var dataProviders = new DataProviders.DataProviders((DataProviderContext)HttpContext.Items[HostConstants.DataProviderContextKey]);
return await _healthCheckService.RunDependencyCheck(dataProviders);
}
}
}

Просмотреть файл

@ -19,6 +19,7 @@
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.7.1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.3" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="2.2.0" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="5.5.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="5.5.0" />
<PackageReference Include="Octokit" Version="0.31.0" />

Просмотреть файл

@ -0,0 +1,26 @@
using Microsoft.Extensions.Logging.AzureAppServices;
namespace Microsoft.Extensions.DependencyInjection
{
public static class ApplicationLoggingExtensions
{
/// <summary>
/// Write application logs to the file system. App Services will honors the settings in the
/// App Service logs section of the App Service page of the Azure portal. When Application Logging (Filesystem) setting is updated, the changes take effect immediately without
/// requiring a restart or redeployment of the app
/// </summary>
/// <param name="services">The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services to.</param>
/// <returns>The Microsoft.Extensions.DependencyInjection.IServiceCollection so that additional calls can be chained.</returns>
public static IServiceCollection AddAppServiceApplicationLogging(this IServiceCollection services)
{
const int maxLogSizeInBytes = 50 * 1024;
services.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "diagnostics-";
options.FileSizeLimit = maxLogSizeInBytes;
options.RetainedFileCountLimit = 10;
});
return services;
}
}
}

Просмотреть файл

@ -13,16 +13,21 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;
using static Diagnostics.Logger.HeaderConstants;
using Diagnostics.RuntimeHost.Models.Exceptions;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Octokit;
namespace Diagnostics.RuntimeHost.Middleware
{
public class DiagnosticsRequestMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<DiagnosticsRequestMiddleware> _logger;
public DiagnosticsRequestMiddleware(RequestDelegate next)
public DiagnosticsRequestMiddleware(RequestDelegate next, ILogger<DiagnosticsRequestMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext httpContext)
@ -52,6 +57,7 @@ namespace Diagnostics.RuntimeHost.Middleware
{
exception = ex;
statusCode = (int)HttpStatusCode.InternalServerError;
throw;
}
finally
{
@ -146,6 +152,8 @@ namespace Diagnostics.RuntimeHost.Middleware
private void LogException(HttpContext context, Exception ex)
{
_logger.LogError(ex, $"Failed to process request for {context.Request.Path.Value}", null);
try
{
var logger = (ApiMetricsLogger)context.Items[HostConstants.ApiLoggerKey] ?? new ApiMetricsLogger(context);

Просмотреть файл

@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Extensions.Configuration.AzureKeyVault;
using Microsoft.Extensions.Logging;
using Diagnostics.DataProviders;
using System;
using Microsoft.CodeAnalysis;
@ -41,32 +42,37 @@ namespace Diagnostics.RuntimeHost
return WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
var (keyVaultConfig, keyVaultClient) = GetKeyVaultSettings(context, config);
var (keyVaultUri, keyVaultClient) = GetKeyVaultSettings(context, config);
config
.AddAzureKeyVault(
$"https://{keyVaultConfig}.vault.azure.net/",
keyVaultUri,
keyVaultClient,
new DefaultKeyVaultSecretManager())
.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();
})
.ConfigureLogging(loggingBuilder =>
{
//Send log output to text file application logs
loggingBuilder.AddAzureWebAppDiagnostics();
//Send log output to the Windows Event Log
loggingBuilder.AddEventLog();
})
.UseStartup<Startup>()
.Build();
}
private static Tuple<string, KeyVaultClient> GetKeyVaultSettings(WebHostBuilderContext context, IConfigurationBuilder config)
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var builtConfig = config.Build();
var azureServiceTokenProvider = new AzureServiceTokenProvider(azureAdInstance: builtConfig["Secrets:AzureAdInstance"]);
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
string keyVaultConfig = Helpers.GetKeyvaultforEnvironment(context.HostingEnvironment.EnvironmentName);
var builtConfig = config.Build();
return new Tuple<string, KeyVaultClient>(builtConfig[keyVaultConfig], keyVaultClient);
}
}

Просмотреть файл

@ -3,12 +3,16 @@ using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Diagnostics.RuntimeHost.Utilities;
using Diagnostics.DataProviders;
using System.Collections.Generic;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Diagnostics.RuntimeHost.Services
{
public interface IHealthCheckService : IDisposable
{
Task RunHealthCheck();
Task<IEnumerable<HealthCheckResult>> RunDependencyCheck(DataProviders.DataProviders dataProviders);
}
public class HealthCheckService : IHealthCheckService
@ -54,6 +58,14 @@ namespace Diagnostics.RuntimeHost.Services
await RetryHelper.RetryAsync(HealthCheckPing, "Healthping", "", 3, 100);
}
public async Task<IEnumerable<HealthCheckResult>> RunDependencyCheck(DataProviders.DataProviders dataProviders)
{
var results = new List<HealthCheckResult>();
DiagnosticDataProvider dp = ((LogDecoratorBase)dataProviders.Kusto).DataProvider;
results.Add(await dp.CheckHealthAsync(null));
return results;
}
public void Dispose()
{
if (_httpClient != null)

Просмотреть файл

@ -22,6 +22,7 @@ using System.Diagnostics;
using Diagnostics.RuntimeHost.Security.CertificateAuth;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.IdentityModel.Logging;
using System.Net;
namespace Diagnostics.RuntimeHost
@ -48,6 +49,7 @@ namespace Diagnostics.RuntimeHost
public void ConfigureServices(IServiceCollection services)
{
IdentityModelEventSource.ShowPII = Configuration.GetValue("ShowIdentityModelErrors", false);
var openIdConfigEndpoint = $"{Configuration["SecuritySettings:AADAuthority"]}/.well-known/openid-configuration";
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(openIdConfigEndpoint, new OpenIdConnectConfigurationRetriever());
var config = configManager.GetConfigurationAsync().Result;
@ -104,6 +106,7 @@ namespace Diagnostics.RuntimeHost
// Enable App Insights telemetry
services.AddApplicationInsightsTelemetry();
services.AddAppServiceApplicationLogging();
if(Environment.IsDevelopment())
{
services.AddMvc(options =>
@ -147,7 +150,7 @@ namespace Diagnostics.RuntimeHost
services.AddSingleton<IKustoHeartBeatService>(new KustoHeartBeatService(kustoConfiguration));
observerConfiguration.AADAuthority = dataSourcesConfigService.Config.KustoConfiguration.AADAuthority;
var wawsObserverTokenService = new ObserverTokenService(observerConfiguration.WawsObserverResourceId, observerConfiguration);
var wawsObserverTokenService = new ObserverTokenService(observerConfiguration.AADResource, observerConfiguration);
var supportBayApiObserverTokenService = new ObserverTokenService(observerConfiguration.SupportBayApiObserverResourceId, observerConfiguration);
services.AddSingleton<IWawsObserverTokenService>(wawsObserverTokenService);
services.AddSingleton<ISupportBayApiObserverTokenService>(supportBayApiObserverTokenService);
@ -155,9 +158,21 @@ namespace Diagnostics.RuntimeHost
observerServicePoint.ConnectionLeaseTimeout = 60 * 1000;
ChangeAnalysisTokenService.Instance.Initialize(dataSourcesConfigService.Config.ChangeAnalysisDataProviderConfiguration);
AscTokenService.Instance.Initialize(dataSourcesConfigService.Config.AscDataProviderConfiguration);
CompilerHostTokenService.Instance.Initialize(Configuration);
if (Configuration.GetValue("ChangeAnalysis:Enabled", true))
{
ChangeAnalysisTokenService.Instance.Initialize(dataSourcesConfigService.Config.ChangeAnalysisDataProviderConfiguration);
}
if (Configuration.GetValue("AzureSupportCenter:Enabled", true))
{
AscTokenService.Instance.Initialize(dataSourcesConfigService.Config.AscDataProviderConfiguration);
}
if (Configuration.GetValue("CompilerHost:Enabled", true))
{
CompilerHostTokenService.Instance.Initialize(Configuration);
}
if (searchApiConfiguration.SearchAPIEnabled)
{
services.AddSingleton<ISearchService, SearchService>();

Просмотреть файл

@ -1,8 +1,9 @@
{
"Secrets": {
"DevKeyVaultName": "appservicediagnostics",
"StagingKeyVaultName": "AppServiceDiagnosticsKV",
"ProdKeyVaultName": "AppServiceDiagnosticsKV"
"DevKeyVaultName": "https://appservicediagnostics.vault.azure.net/",
"StagingKeyVaultName": "https://AppServiceDiagnosticsKV.vault.azure.net/",
"ProdKeyVaultName": "https://AppServiceDiagnosticsKV.vault.azure.net/",
"AzureAdInstance": "https://login.microsoftonline.com/"
},
"Logging": {
"IncludeScopes": false,
@ -22,7 +23,8 @@
"ClientId": "",
"AppKey": "",
"AADAuthority": "",
"AADResource": ""
"AADResource": "",
"Enabled": true
},
"SourceWatcher": {
"WatcherType": "1",
@ -58,7 +60,8 @@
"ClientId": "",
"AppKey": "",
"Endpoint": "https://wawsobserver-prod.azurewebsites.net",
"ObserverLocalHostEnabled": false
"ObserverLocalHostEnabled": false,
"AADResource": "d1abfd91-e19c-426e-802f-a6c55421a5ef"
},
"GeoMaster": {
"GeoCertThumbprint": "",
@ -71,7 +74,8 @@
"Mdm": {
"MdmShoeboxEndpoint": "",
"MdmRegistrationCertThumbprint": "",
"MdmShoeboxAccount": ""
"MdmShoeboxAccount": "",
"Enabled": true
},
"ChangeAnalysis": {
"ClientId": "",
@ -79,7 +83,8 @@
"AADAuthority": "https://login.microsoftonline.com/microsoft.onmicrosoft.com",
"AADResource": "",
"Endpoint": "https://changeanalysis-dataplane-dev.azurewebsites.net/providers/microsoft.changeanalysis/",
"Apiversion": "2019-04-01-preview"
"Apiversion": "2019-04-01-preview",
"Enabled": true
},
"AzureSupportCenter": {
"BaseUri": "https://api.diagnostics.msftcloudes.com",
@ -90,6 +95,7 @@
"TokenResource": "https://microsoft.onmicrosoft.com/azurediagnostic",
"ClientId": "",
"AppKey": "",
"Enabled": true,
"DiagAscHeader": ""
},
"SearchAPI": {
@ -104,7 +110,8 @@
"SecuritySettings": {
"AADAuthority": "",
"ClientId": "",
"AllowedAppIds": ""
"AllowedAppIds": "",
"ShowIdentityModelErrors": false
},
"CloudDomain": "PublicAzure",
"HealthCheckSettings": {