Dev/saars/split service collection (#151)

* Refactor service collection builder

* Update version number and build scripts

* Build basic services

* Add logging for user configurations

* Clean up the APIs to enable AI.K8S

* Add unit tests for configurations

* Update readme

* Fix a mistake in the readme
This commit is contained in:
Saar Shen 2018-11-19 11:01:28 -08:00 коммит произвёл GitHub
Родитель de1b629fea
Коммит 68922e6242
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
14 изменённых файлов: 612 добавлений и 156 удалений

38
.vscode/tasks.json поставляемый
Просмотреть файл

@ -2,16 +2,44 @@
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"label": "Build Debug",
"command": "${workspaceFolder}/build/Build.cmd",
"type": "shell",
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build Release",
"command": "${workspaceFolder}/build/Build.cmd",
"type": "shell",
"group": "build",
"args": [
"build",
"${workspaceFolder}/ApplicationInsights.Kubernetes.sln"
"Release",
],
"problemMatcher": "$msCompile",
},
{
"label": "ReBuild Debug",
"command": "${workspaceFolder}/build/Build.cmd",
"type": "shell",
"group": "build",
"args": [
"Debug",
"True",
],
"problemMatcher": "$msCompile"
},
{
"label": "ReBuild Release",
"command": "${workspaceFolder}/build/Build.cmd",
"type": "shell",
"group": "build",
"args": [
"Release",
"True",
],
"problemMatcher": "$msCompile",
},
{
"label": "Run Unit Tests",
"command": "dotnet",

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

@ -24,6 +24,42 @@ We support **ASP.NET Core** application as well as **.NET Core** application.
* Follow [this example](examples/BasicUsage_clr21_RBAC) for Role-based access control (RBAC) enabled Kubernetes clusters.
### Configuration Details
Customize configurations are supported for `v1.0.2+`. There are several ways to customize the settings. For example:
1. By the code:
```csharp
services.AddApplicationInsightsKubernetesEnricher(option=> {
option.InitializationTimeout = TimeSpan.FromSeconds(15);
});
```
2. By `appsettings.json`:
```jsonc
{
"Logging": {
// ...
},
// Adding the following section to set the timeout to 15 seconds
"AppInsightsForKubernetes": {
"InitializationTimeout": "00:00:15"
}
}
```
3. By environment varialbe:
```
AppInsightsForKubernetes__InitializationTimeout=3.1:12:15.34
```
All the related configurations have to be put in a section named `AppInsightsForKubernetes`. The supported keys/values are listed below:
| Key | Value/Types | Default Value | Description |
|-----------------------|-------------|---------------|--------------------------------------------------------------------------------------------------------|
| InitializationTimeout | TimeSpan | 00:02:00 | Maximum time to wait for spinning up the container. Accepted format: [d.]hh:mm:ss[.fffffff]. |
The configuration uses with the conventions in ASP.NET Core. Refer [Configuration in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1) for more information.
### Verify the cluster configuration
Use the [troubleshooting image](https://github.com/Microsoft/ApplicationInsights-Kubernetes/tree/develop/troubleshooting) to verify the cluster is properly configured.

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

@ -3,6 +3,9 @@ SETLOCAL
SET CONFIG=%1
SET REBUILD=%2
IF '%CONFIG%' == '' SET CONFIG=Debug
SET REBUILD_PARAM=--no-incremental
IF '%REBUILD%' == '' SET REBUILD_PARAM=
ECHO Target Configuration: %CONFIG%.
FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET CDATE=%%B
@ -13,7 +16,7 @@ FOR /F "TOKENS=1-2 delims=/:" %%a in ("%TIME%") DO SET mytime=%%a%%b
SET CURRENT_DATE_TIME=%yyyy%%mm%%dd%%mytime%
ECHO Version:%CURRENT_DATE_TIME%
dotnet build %~dp0\..\ApplicationInsights.Kubernetes.sln
dotnet build -c %CONFIG% %REBUILD_PARAM% %~dp0\..\ApplicationInsights.Kubernetes.sln
:HELP
GOTO :EXIT

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

@ -27,17 +27,23 @@
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.3'">
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.6'">
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.1" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.4.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.4.1" />
</ItemGroup>
</Project>

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

@ -0,0 +1,19 @@
using System;
using Newtonsoft.Json;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Object model of configuration for Application Insights for Kubernetes.
/// </summary>
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class AppInsightsForKubernetesOptions
{
/// <summary>
/// Maximum time to wait for spinning up the container.
/// </summary>
/// <value></value>
[JsonProperty("InitializationTimeout")]
public TimeSpan InitializationTimeout { get; set; } = TimeSpan.FromMinutes(2);
}
}

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

@ -4,54 +4,91 @@ using System.Linq;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Kubernetes;
using Microsoft.ApplicationInsights.Kubernetes.Utilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using static Microsoft.ApplicationInsights.Kubernetes.StringUtils;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extnesion method to inject Kubernetes Telemtry Initializer.
/// </summary>
public static class ApplicationInsightsExtensions
public static partial class ApplicationInsightsExtensions
{
private const string ConfigurationSectionName = "AppInsightsForKubernetes";
/// <summary>
/// Enables Application Insights for Kubernetes on the Default TelemtryConfiguration in the dependency injection system.
/// </summary>
/// <param name="services">Collection of service descriptors.</param>
/// <param name="timeout">Maximum time to wait for spinning up the container.</param>
/// <param name="kubernetesServiceCollectionBuilder">Collection builder.</param>
/// <param name="detectKubernetes">Delegate to detect if the current application is running in Kubernetes hosted container.</param>
/// <returns>The collection of services descriptors we injected into.</returns>
/// <returns>The collection of services descriptors injected into.</returns>
public static IServiceCollection AddApplicationInsightsKubernetesEnricher(
this IServiceCollection services)
{
return services.AddApplicationInsightsKubernetesEnricher(applyOptions: null);
}
/// <summary>
/// Enables Application Insights for Kubernetes on the Default TelemtryConfiguration in the dependency injection system with custom options.
/// </summary>
/// <param name="services">Collection of service descriptors.</param>
/// <param name="applyOptions">Action to customize the configuration of Application Insights for Kubernetes.</param>
/// <returns>The collection of services descriptors injected into.</returns>
public static IServiceCollection AddApplicationInsightsKubernetesEnricher(
this IServiceCollection services,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null)
Action<AppInsightsForKubernetesOptions> applyOptions)
{
return services.AddApplicationInsightsKubernetesEnricher(
applyOptions,
kubernetesServiceCollectionBuilder: null,
detectKubernetes: null,
logger: null
);
}
/// <summary>
/// Enables Application Insights for Kubernetes on the Default TelemtryConfiguration in the dependency injection system with custom options and debugging components.
/// </summary>
/// <param name="services">Collection of service descriptors.</param>
/// <param name="applyOptions">Action to customize the configuration of Application Insights for Kubernetes.</param>
/// <param name="kubernetesServiceCollectionBuilder">Sets the service collection builder for Application Insights for Kubernetes to overwrite the default one.</param>
/// <param name="detectKubernetes">Sets a delegate overwrite the default detector of the Kubernetes environment.</param>
/// <param name="logger">Sets a logger to overwrite the default logger from the given service collection.</param>
/// <returns>The collection of services descriptors injected into.</returns>
public static IServiceCollection AddApplicationInsightsKubernetesEnricher(
this IServiceCollection services,
Action<AppInsightsForKubernetesOptions> applyOptions,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder,
Func<bool> detectKubernetes,
ILogger<IKubernetesServiceCollectionBuilder> logger)
{
// Inject of the service shall return immediately.
EnableKubernetesImpl(services, detectKubernetes, kubernetesServiceCollectionBuilder, null, timeout);
return services;
return EnableKubernetesImpl(services, detectKubernetes, kubernetesServiceCollectionBuilder, applyOptions: applyOptions, logger: logger);
}
/// <summary>
/// Enables Application Insights Kubernetes for a given TelemetryConfiguration.
/// </summary>
/// <remarks>
/// The use of AddApplicationInsightsKubernetesEnricher() on the ServiceCollection is always preferred unless you have more than one TelemetryConfiguration
/// instance, or if you are using Application Insights from a non ASP.NET environment, like a console app.
/// </remarks>
/// <param name="telemetryConfiguration">Sets the telemetry configuration to add the telemetry initializer to.</param>
/// <param name="applyOptions">Sets a delegate to apply the configuration for the telemetry initializer.</param>
/// <param name="kubernetesServiceCollectionBuilder">Sets a service collection builder.</param>
/// <param name="detectKubernetes">Sets a delegate to detect if the current application is running in Kubernetes hosted container.</param>
/// <param name="logger">Sets a logger for building the service collection.</param>
public static void AddApplicationInsightsKubernetesEnricher(
this TelemetryConfiguration telemetryConfiguration,
TimeSpan? timeout = null,
Action<AppInsightsForKubernetesOptions> applyOptions = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null)
Func<bool> detectKubernetes = null,
ILogger<IKubernetesServiceCollectionBuilder> logger = null)
{
IServiceCollection standaloneServiceCollection = new ServiceCollection();
standaloneServiceCollection = EnableKubernetesImpl(standaloneServiceCollection, detectKubernetes, kubernetesServiceCollectionBuilder, null, timeout);
standaloneServiceCollection = standaloneServiceCollection.AddApplicationInsightsKubernetesEnricher(
applyOptions,
kubernetesServiceCollectionBuilder,
detectKubernetes,
logger);
// Static class can't used as generic types.
ILogger logger = standaloneServiceCollection.GetLogger<IKubernetesServiceCollectionBuilder>();
IServiceProvider serviceProvider = standaloneServiceCollection.BuildServiceProvider();
ITelemetryInitializer k8sTelemetryInitializer = serviceProvider.GetServices<ITelemetryInitializer>()
.FirstOrDefault(ti => ti is KubernetesTelemetryInitializer);
@ -59,104 +96,85 @@ namespace Microsoft.Extensions.DependencyInjection
if (k8sTelemetryInitializer != null)
{
telemetryConfiguration.TelemetryInitializers.Add(k8sTelemetryInitializer);
logger?.LogInformation($"{nameof(KubernetesTelemetryInitializer)} is injected.");
}
else
{
logger.LogError($"Getting ${nameof(KubernetesTelemetryInitializer)} from the service provider failed.");
logger?.LogError($"Getting ${nameof(KubernetesTelemetryInitializer)} from the service provider failed.");
}
}
/// <summary>
/// Please use AddApplicationInsightsKubernetesEnricher() insead.
/// Enables Application Insights Kubernetes for the Default TelemtryConfiguration in the dependency injection system.
/// </summary>
/// <param name="services">Collection of service descriptors.</param>
/// <param name="timeout">Maximum time to wait for spinning up the container.</param>
/// <param name="kubernetesServiceCollectionBuilder">Collection builder.</param>
/// <param name="detectKubernetes">Delegate to detect if the current application is running in Kubernetes hosted container.</param>
/// <returns>The collection of services descriptors we injected into.</returns>
[Obsolete("Use AddApplicationInsightsKubernetesEnricher() instead", false)]
public static IServiceCollection EnableKubernetes(
this IServiceCollection services,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null)
{
return services.AddApplicationInsightsKubernetesEnricher(timeout, kubernetesServiceCollectionBuilder, detectKubernetes);
}
/// <summary>
/// Please use "AddApplicationInsightsKubernetesEnricher()" insead.
/// Enables Application Insights Kubernetes for a given
/// TelemetryConfiguration.
/// </summary>
/// <remarks>
/// The use of AddApplicationInsightsKubernetesEnricher() on the ServiceCollection is always
/// preferred unless you have more than one TelemetryConfiguration
/// instance, or if you are using Application Insights from a non ASP.NET
/// environment, like a console app.
/// </remarks>
[Obsolete("Use AddApplicationInsightsKubernetesEnricher() instead", false)]
public static void EnableKubernetes(
this TelemetryConfiguration telemetryConfiguration,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null)
{
telemetryConfiguration.AddApplicationInsightsKubernetesEnricher(
timeout, kubernetesServiceCollectionBuilder, detectKubernetes);
}
/// <summary>
/// Enables applicaiton insights for kubernetes.
/// </summary>
private static IServiceCollection EnableKubernetesImpl(IServiceCollection serviceCollection,
Func<bool> detectKubernetes,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder,
ILogger<KubernetesServiceCollectionBuilder> logger = null,
TimeSpan? timeout = null)
Action<AppInsightsForKubernetesOptions> applyOptions,
ILogger<IKubernetesServiceCollectionBuilder> logger = null)
{
logger = logger ?? serviceCollection.GetLogger<KubernetesServiceCollectionBuilder>();
// 2 minutes by default maximum to wait for spinning up the container.
timeout = timeout ?? TimeSpan.FromMinutes(2);
logger.LogInformation(Invariant($"ApplicationInsights.Kubernetes.Version:{SDKVersionUtils.Instance.CurrentSDKVersion}"));
try
{
serviceCollection = BuildK8sServiceCollection(serviceCollection, timeout.Value, detectKubernetes, logger, kubernetesServiceCollectionBuilder);
}
catch (Exception ex)
{
logger.LogError("Failed to fetch ApplicaitonInsights.Kubernetes' info. Details " + ex.ToString());
}
BuildServiceBases(serviceCollection, applyOptions, ref logger);
serviceCollection = BuildK8sServiceCollection(
serviceCollection,
detectKubernetes,
logger: logger,
kubernetesServiceCollectionBuilder: kubernetesServiceCollectionBuilder);
return serviceCollection;
}
private static void BuildServiceBases(
IServiceCollection serviceCollection,
Action<AppInsightsForKubernetesOptions> applyOptions,
ref ILogger<IKubernetesServiceCollectionBuilder> logger)
{
serviceCollection.AddLogging();
serviceCollection.AddOptions();
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
// Create a default logger when not passed in.
logger = logger ?? serviceProvider.GetService<ILogger<IKubernetesServiceCollectionBuilder>>();
// Apply the conifguraitons ifnot yet.
IOptions<AppInsightsForKubernetesOptions> options = serviceProvider.GetService<IOptions<AppInsightsForKubernetesOptions>>();
if (options.Value == null)
{
serviceCollection.AddSingleton<IOptions<AppInsightsForKubernetesOptions>>(
new OptionsWrapper<AppInsightsForKubernetesOptions>(new AppInsightsForKubernetesOptions()));
}
// Update settings from configuration.
IConfiguration configuration = serviceProvider.GetService<IConfiguration>();
if (configuration != null)
{
serviceCollection.Configure<AppInsightsForKubernetesOptions>(configuration.GetSection(ConfigurationSectionName));
}
// Update settings when parameter is provided for backward compatibility.
if (applyOptions != null)
{
serviceCollection.Configure<AppInsightsForKubernetesOptions>(option =>
{
applyOptions(option);
});
}
}
private static IServiceCollection BuildK8sServiceCollection(
IServiceCollection services,
TimeSpan timeout,
Func<bool> detectKubernetes,
ILogger<KubernetesServiceCollectionBuilder> logger,
ILogger<IKubernetesServiceCollectionBuilder> logger,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null)
{
detectKubernetes = detectKubernetes ?? IsRunningInKubernetes;
kubernetesServiceCollectionBuilder = kubernetesServiceCollectionBuilder ?? new KubernetesServiceCollectionBuilder(detectKubernetes, logger);
services = kubernetesServiceCollectionBuilder.InjectServices(services, timeout);
kubernetesServiceCollectionBuilder = kubernetesServiceCollectionBuilder ??
new KubernetesServiceCollectionBuilder(detectKubernetes, logger);
services = kubernetesServiceCollectionBuilder.InjectServices(services);
return services;
}
private static bool IsRunningInKubernetes() => Directory.Exists(@"/var/run/secrets/kubernetes.io") || Directory.Exists(@"C:\var\run\secrets\kubernetes.io");
/// <summary>
/// Gets a logger for given type.
/// Note: This method leads to build service provider during the injection of services and shall be avoid whenever possible.
/// </summary>
private static ILogger<T> GetLogger<T>(this IServiceCollection services)
{
// AddLogging() is safe to call multiple times.
// https://github.com/aspnet/Logging/blob/75a1cecf24f8418a45426b6cc3606f0d53640f89/src/Microsoft.Extensions.Logging/LoggingServiceCollectionExtensions.cs#L41
return services.AddLogging().BuildServiceProvider().GetService<ILogger<T>>();
}
}
}

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

@ -7,12 +7,20 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary>
public interface IKubernetesServiceCollectionBuilder
{
/// <summary>
/// Injects Application Insights for Kubernetes services into the service collection.
/// </summary>
/// <param name="serviceCollection">The collection of service descriptors.</param>
/// <returns>The collection of services descriptors we injected into.</returns>
IServiceCollection InjectServices(IServiceCollection serviceCollection);
/// <summary>
/// Injects Application Insights for Kubernetes services into the service collection.
/// </summary>
/// <param name="serviceCollection">The collection of service descriptors.</param>
/// <param name="timeout">Maximum time to wait for spinning up the container.</param>
/// <returns>The collection of services descriptors we injected into.</returns>
[Obsolete("Use InjectServices(IServiceCollection serviceCollection) instead.", error: true)]
IServiceCollection InjectServices(IServiceCollection serviceCollection, TimeSpan timeout);
}
}

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

@ -14,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
private readonly ILogger _logger;
private readonly Func<bool> _isRunningInKubernetes;
/// <summary>
/// Construction for <see cref="KubernetesServiceCollectionBuilder"/>.
/// </summary>
@ -22,12 +22,36 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="logger"></param>
public KubernetesServiceCollectionBuilder(
Func<bool> isRunningInKubernetes,
ILogger<KubernetesServiceCollectionBuilder> logger)
ILogger<IKubernetesServiceCollectionBuilder> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_logger = logger;
_isRunningInKubernetes = isRunningInKubernetes ?? throw new ArgumentNullException(nameof(isRunningInKubernetes));
}
/// <summary>
/// Injects Kubernetes related service into the service collection.
/// </summary>
/// <param name="serviceCollection">The service collector to inject the services into.</param>
/// <returns>Returns the service collector with services injected.</returns>
public IServiceCollection InjectServices(IServiceCollection serviceCollection)
{
if (_isRunningInKubernetes())
{
IServiceCollection services = serviceCollection ?? throw new ArgumentNullException(nameof(serviceCollection));
InjectCommonServices(services);
InjectChangableServices(services);
services.AddSingleton<ITelemetryInitializer, KubernetesTelemetryInitializer>();
_logger?.LogDebug("Application Insights Kubernetes injected the service successfully.");
return services;
}
else
{
_logger?.LogWarning("Application is not running inside a Kubernetes cluster.");
return serviceCollection;
}
}
/// <summary>
/// Injects Kubernetes related service into the service collection.
/// </summary>
@ -38,29 +62,16 @@ namespace Microsoft.Extensions.DependencyInjection
{
if (_isRunningInKubernetes())
{
IServiceCollection services = serviceCollection ?? new ServiceCollection();
InjectCommonServices(services);
InjectChangableServices(services);
// Inject the telemetry initializer.
services.AddSingleton<ITelemetryInitializer>(provider =>
{
KubernetesTelemetryInitializer initializer = new KubernetesTelemetryInitializer(
provider.GetRequiredService<IK8sEnvironmentFactory>(),
timeout,
SDKVersionUtils.Instance,
provider.GetRequiredService<ILogger<KubernetesTelemetryInitializer>>()
);
_logger.LogDebug("Application Insights Kubernetes injected the service successfully.");
return initializer;
});
return services;
}
else
{
_logger.LogWarning("Application is not running inside a Kubernetes cluster.");
_logger?.LogWarning("Application is not running inside a Kubernetes cluster.");
return serviceCollection;
}
}
@ -69,6 +80,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
serviceCollection.AddSingleton<KubeHttpClientFactory>();
serviceCollection.AddSingleton<K8sQueryClientFactory>();
serviceCollection.AddSingleton<SDKVersionUtils>(SDKVersionUtils.Instance);
}
/// <summary>
@ -79,11 +91,13 @@ namespace Microsoft.Extensions.DependencyInjection
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
serviceCollection.AddSingleton<IKubeHttpClientSettingsProvider>(p => new KubeHttpClientSettingsProvider(logger: p.GetService<ILogger<KubeHttpClientSettingsProvider>>()));
serviceCollection.AddSingleton<IKubeHttpClientSettingsProvider>(p =>
new KubeHttpClientSettingsProvider(logger: p.GetService<ILogger<KubeHttpClientSettingsProvider>>()));
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
serviceCollection.AddSingleton<IKubeHttpClientSettingsProvider>(p => new KubeHttpSettingsWinContainerProvider(logger: p.GetService<ILogger<KubeHttpSettingsWinContainerProvider>>()));
serviceCollection.AddSingleton<IKubeHttpClientSettingsProvider>(p =>
new KubeHttpSettingsWinContainerProvider(logger: p.GetService<ILogger<KubeHttpSettingsWinContainerProvider>>()));
}
else
{

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

@ -0,0 +1,117 @@
using System;
using System.Linq;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Kubernetes;
using Microsoft.Extensions.Logging;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// This class holds all the obsoleted methods for ApplicationInsightsExtensions for readability.
/// </summary>
public static partial class ApplicationInsightsExtensions
{
/// <summary>
/// Enables Application Insights for Kubernetes on the Default TelemtryConfiguration in the dependency injection system.
/// </summary>
/// <param name="services">Sets the collection of service descriptors.</param>
/// <param name="timeout">Sets the maximum time to wait for spinning up the container.</param>
/// <param name="kubernetesServiceCollectionBuilder">Sets the collection builder.</param>
/// <param name="detectKubernetes">Sets a delegate to detect if the current application is running in Kubernetes hosted container.</param>
/// <param name="logger">Sets a logger for building the service collection.</param>
/// <returns>The collection of services descriptors injected into.</returns>
[Obsolete("Use AddApplicationInsightsKubernetesEnricher with Options instead.", error: false)]
public static IServiceCollection AddApplicationInsightsKubernetesEnricher(
this IServiceCollection services,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null,
ILogger<IKubernetesServiceCollectionBuilder> logger = null)
{
return services.AddApplicationInsightsKubernetesEnricher(option =>
{
if (timeout != null && timeout.HasValue)
{
option.InitializationTimeout = timeout.Value;
}
}, kubernetesServiceCollectionBuilder, detectKubernetes, logger);
}
/// <summary>
/// Enables Application Insights Kubernetes for a given TelemetryConfiguration.
/// </summary>
/// <remarks>
/// The use of AddApplicationInsightsKubernetesEnricher() on the ServiceCollection is always preferred unless you have more than one TelemetryConfiguration
/// instance, or if you are using Application Insights from a non ASP.NET environment, like a console app.
/// </remarks>
[Obsolete("Use AddApplicationInsightsKubernetesEnricher with Options instead.", error: false)]
public static void AddApplicationInsightsKubernetesEnricher(
this TelemetryConfiguration telemetryConfiguration,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null,
ILogger<IKubernetesServiceCollectionBuilder> logger = null)
{
IServiceCollection standaloneServiceCollection = new ServiceCollection();
standaloneServiceCollection = standaloneServiceCollection.AddApplicationInsightsKubernetesEnricher(
timeout, kubernetesServiceCollectionBuilder, detectKubernetes);
// Static class can't used as generic types.
IServiceProvider serviceProvider = standaloneServiceCollection.BuildServiceProvider();
ITelemetryInitializer k8sTelemetryInitializer = serviceProvider.GetServices<ITelemetryInitializer>()
.FirstOrDefault(ti => ti is KubernetesTelemetryInitializer);
if (k8sTelemetryInitializer != null)
{
telemetryConfiguration.TelemetryInitializers.Add(k8sTelemetryInitializer);
logger?.LogInformation($"{nameof(KubernetesTelemetryInitializer)} is injected.");
}
else
{
logger?.LogError($"Getting ${nameof(KubernetesTelemetryInitializer)} from the service provider failed.");
}
}
/// <summary>
/// Please use AddApplicationInsightsKubernetesEnricher() insead.
/// Enables Application Insights Kubernetes for the Default TelemtryConfiguration in the dependency injection system.
/// </summary>
/// <param name="services">Collection of service descriptors.</param>
/// <param name="timeout">Maximum time to wait for spinning up the container.</param>
/// <param name="kubernetesServiceCollectionBuilder">Collection builder.</param>
/// <param name="detectKubernetes">Delegate to detect if the current application is running in Kubernetes hosted container.</param>
/// <returns>The collection of services descriptors injected into.</returns>
[Obsolete("Use AddApplicationInsightsKubernetesEnricher() instead", false)]
public static IServiceCollection EnableKubernetes(
this IServiceCollection services,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null)
{
return services.AddApplicationInsightsKubernetesEnricher(timeout, kubernetesServiceCollectionBuilder, detectKubernetes);
}
/// <summary>
/// Please use "AddApplicationInsightsKubernetesEnricher()" insead.
/// Enables Application Insights Kubernetes for a given
/// TelemetryConfiguration.
/// </summary>
/// <remarks>
/// The use of AddApplicationInsightsKubernetesEnricher() on the ServiceCollection is always
/// preferred unless you have more than one TelemetryConfiguration
/// instance, or if you are using Application Insights from a non ASP.NET
/// environment, like a console app.
/// </remarks>
[Obsolete("Use AddApplicationInsightsKubernetesEnricher() instead", false)]
public static void EnableKubernetes(
this TelemetryConfiguration telemetryConfiguration,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null)
{
telemetryConfiguration.AddApplicationInsightsKubernetesEnricher(
timeout, kubernetesServiceCollectionBuilder, detectKubernetes);
}
}
}

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

@ -1,15 +1,17 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Extensibility.Implementation;
using Microsoft.ApplicationInsights.Kubernetes.Utilities;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using static Microsoft.ApplicationInsights.Kubernetes.StringUtils;
#if !NETSTANDARD1_3 && !NETSTANDARD1_6
using System.Diagnostics;
using System.Globalization;
#endif
@ -31,26 +33,24 @@ namespace Microsoft.ApplicationInsights.Kubernetes
public const string CPU = "CPU";
public const string Memory = "Memory";
private readonly ILogger _logger;
private readonly SDKVersionUtils _sdkVersionUtils;
private readonly DateTime _timeoutAt;
internal readonly IK8sEnvironmentFactory _k8sEnvFactory;
internal IK8sEnvironment _k8sEnvironment { get; private set; }
internal bool _isK8sQueryTimeout = false;
private bool _isK8sQueryTimeoutReported = false;
public KubernetesTelemetryInitializer(
IK8sEnvironmentFactory k8sEnvFactory,
TimeSpan timeout,
IOptions<AppInsightsForKubernetesOptions> options,
SDKVersionUtils sdkVersionUtils,
ILogger<KubernetesTelemetryInitializer> logger)
{
_k8sEnvironment = null;
_logger = logger;
// Options can't be null.
Debug.Assert(options != null, "Options can't be null.");
_options = Arguments.IsNotNull(options?.Value, nameof(options));
_logger.LogDebug($@"Initialize Application Insihgts for Kubernetes telemetry initializer with Options:
{JsonConvert.SerializeObject(_options)}");
_sdkVersionUtils = Arguments.IsNotNull(sdkVersionUtils, nameof(sdkVersionUtils));
_timeoutAt = DateTime.Now.Add(Arguments.IsNotNull(timeout, nameof(timeout)));
_timeoutAt = DateTime.Now.Add(_options.InitializationTimeout);
_k8sEnvFactory = Arguments.IsNotNull(k8sEnvFactory, nameof(k8sEnvFactory));
var _forget = SetK8sEnvironment();
@ -206,5 +206,17 @@ namespace Microsoft.ApplicationInsights.Kubernetes
}
}
}
private readonly ILogger _logger;
private readonly SDKVersionUtils _sdkVersionUtils;
private readonly DateTime _timeoutAt;
internal readonly IK8sEnvironmentFactory _k8sEnvFactory;
internal IK8sEnvironment _k8sEnvironment { get; private set; }
internal AppInsightsForKubernetesOptions _options { get; private set; }
internal bool _isK8sQueryTimeout = false;
private bool _isK8sQueryTimeoutReported = false;
}
}

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

@ -15,8 +15,8 @@
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)PublicKey.snk</AssemblyOriginatorKeyFile>
<!--Package-->
<VersionSuffix Condition=" '$(VersionSuffix)' == '' ">$([System.DateTime]::Now.ToString(yyyyMMddHHmm))</VersionSuffix>
<Version Condition=" '$(Version)' == '' ">1.0.1-private-$(VersionSuffix)</Version>
<AssemblyVersion Condition=" '$(AssemblyVersion)' == '' " >1.0.1.0</AssemblyVersion>
<Version Condition=" '$(Version)' == '' ">1.0.2-private-$(VersionSuffix)</Version>
<AssemblyVersion Condition=" '$(AssemblyVersion)' == '' " >1.0.2.0</AssemblyVersion>
<Authors>Microsoft</Authors>
<Company>Microsoft</Company>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>

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

@ -51,7 +51,7 @@ namespace Microsoft.ApplicationInsights.Netcore.Kubernetes
using (KubeHttpClient httpClient = new KubeHttpClient(settingsMock.Object, GetLogger<KubeHttpClient>()))
using (K8sQueryClient target = new K8sQueryClient(httpClient, GetLogger<K8sQueryClient>()))
{
Assert.Equal(httpClient, target.KubeHttpClient);
Assert.Same(httpClient, target.KubeHttpClient);
}
}

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

@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Kubernetes;
using Microsoft.ApplicationInsights.Kubernetes.Utilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
@ -17,7 +20,8 @@ namespace Microsoft.ApplicationInsights.Netcore.Kubernetes
public void ServiceInjected()
{
IServiceCollection services = new ServiceCollection();
services = services.AddApplicationInsightsKubernetesEnricher(detectKubernetes: () => true);
services = services.AddApplicationInsightsKubernetesEnricher(applyOptions: null, kubernetesServiceCollectionBuilder: null, detectKubernetes: () => true, logger: null);
Assert.NotNull(services.FirstOrDefault(sd => sd.ImplementationType == typeof(KubernetesTelemetryInitializer)));
// Replace the IKubeHttpClientSetingsProvider in case the test is not running inside a container.
Assert.NotNull(services.FirstOrDefault(s => s.ServiceType == typeof(IKubeHttpClientSettingsProvider)));
@ -26,6 +30,7 @@ namespace Microsoft.ApplicationInsights.Netcore.Kubernetes
services.AddSingleton<IKubeHttpClientSettingsProvider>(p => mock.Object);
IServiceProvider serviceProvider = services.BuildServiceProvider();
ITelemetryInitializer targetTelemetryInitializer = serviceProvider.GetServices<ITelemetryInitializer>().FirstOrDefault(ti => ti is KubernetesTelemetryInitializer);
// Logging
serviceProvider.GetRequiredService<ILoggerFactory>();
@ -38,6 +43,137 @@ namespace Microsoft.ApplicationInsights.Netcore.Kubernetes
serviceProvider.GetRequiredService<IK8sEnvironmentFactory>();
}
[Fact(DisplayName = "Default timeout for waiting container to spin us is 2 minutes")]
public void EnableAppInsightsForKubernetesWithDefaultTimeOut()
{
IServiceCollection services = new ServiceCollection();
services = services.AddApplicationInsightsKubernetesEnricher(
applyOptions:null,
kubernetesServiceCollectionBuilder: null,
detectKubernetes: () => true,
logger: null);
Assert.NotNull(services.FirstOrDefault(sd => sd.ImplementationType == typeof(KubernetesTelemetryInitializer)));
// Replace the IKubeHttpClientSetingsProvider in case the test is not running inside a container.
Assert.NotNull(services.FirstOrDefault(s => s.ServiceType == typeof(IKubeHttpClientSettingsProvider)));
Mock<IKubeHttpClientSettingsProvider> mock = new Mock<IKubeHttpClientSettingsProvider>();
services.Remove(new ServiceDescriptor(typeof(IKubeHttpClientSettingsProvider), typeof(KubeHttpClientSettingsProvider), ServiceLifetime.Singleton));
services.AddSingleton<IKubeHttpClientSettingsProvider>(p => mock.Object);
IServiceProvider serviceProvider = services.BuildServiceProvider();
ITelemetryInitializer targetTelemetryInitializer = serviceProvider.GetServices<ITelemetryInitializer>().FirstOrDefault(ti => ti is KubernetesTelemetryInitializer);
if (targetTelemetryInitializer is KubernetesTelemetryInitializer target)
{
Assert.StrictEqual(TimeSpan.FromMinutes(2), target._options.InitializationTimeout);
}
else
{
Assert.True(false, "Not the target telementry initializer.");
}
}
[Fact(DisplayName = "Set timeout through options works for telemetry initializer.")]
public void EnableAppInsightsForKubernetesWithTimeOutSetThroughOptions()
{
IServiceCollection services = new ServiceCollection();
services = services.AddApplicationInsightsKubernetesEnricher(applyOptions:
option =>
{
option.InitializationTimeout = TimeSpan.FromSeconds(5);
}, kubernetesServiceCollectionBuilder: null, detectKubernetes: () => true, logger: null);
Assert.NotNull(services.FirstOrDefault(sd => sd.ImplementationType == typeof(KubernetesTelemetryInitializer)));
// Replace the IKubeHttpClientSetingsProvider in case the test is not running inside a container.
Assert.NotNull(services.FirstOrDefault(s => s.ServiceType == typeof(IKubeHttpClientSettingsProvider)));
Mock<IKubeHttpClientSettingsProvider> mock = new Mock<IKubeHttpClientSettingsProvider>();
services.Remove(new ServiceDescriptor(typeof(IKubeHttpClientSettingsProvider), typeof(KubeHttpClientSettingsProvider), ServiceLifetime.Singleton));
services.AddSingleton<IKubeHttpClientSettingsProvider>(p => mock.Object);
IServiceProvider serviceProvider = services.BuildServiceProvider();
ITelemetryInitializer targetTelemetryInitializer = serviceProvider.GetServices<ITelemetryInitializer>().FirstOrDefault(ti => ti is KubernetesTelemetryInitializer);
if (targetTelemetryInitializer is KubernetesTelemetryInitializer target)
{
Assert.StrictEqual(TimeSpan.FromSeconds(5), target._options.InitializationTimeout);
}
else
{
Assert.True(false, "Not the target telementry initializer.");
}
}
[Fact(DisplayName = "Set timeout through configuration works for telemetry initializer.")]
public void EnableAppInsightsForKubernetesWithTimeOutSetThroughConfiguration()
{
IServiceCollection services = new ServiceCollection();
IConfiguration config = new ConfigurationBuilder().AddInMemoryCollection(
new Dictionary<string, string>(){
{"a" , "b"},
{"AppInsightsForKubernetes:InitializationTimeout", "3.1:12:15.34"}
}).Build();
services.AddSingleton<IConfiguration>(config);
services = services.AddApplicationInsightsKubernetesEnricher(
applyOptions: null, kubernetesServiceCollectionBuilder: null, detectKubernetes: () => true, logger: null);
Assert.NotNull(services.FirstOrDefault(sd => sd.ImplementationType == typeof(KubernetesTelemetryInitializer)));
// Replace the IKubeHttpClientSetingsProvider in case the test is not running inside a container.
Assert.NotNull(services.FirstOrDefault(s => s.ServiceType == typeof(IKubeHttpClientSettingsProvider)));
Mock<IKubeHttpClientSettingsProvider> mock = new Mock<IKubeHttpClientSettingsProvider>();
services.Remove(new ServiceDescriptor(typeof(IKubeHttpClientSettingsProvider), typeof(KubeHttpClientSettingsProvider), ServiceLifetime.Singleton));
services.AddSingleton<IKubeHttpClientSettingsProvider>(p => mock.Object);
IServiceProvider serviceProvider = services.BuildServiceProvider();
ITelemetryInitializer targetTelemetryInitializer = serviceProvider.GetServices<ITelemetryInitializer>().FirstOrDefault(ti => ti is KubernetesTelemetryInitializer);
if (targetTelemetryInitializer is KubernetesTelemetryInitializer target)
{
Assert.StrictEqual(new TimeSpan(days: 3, hours: 1, minutes: 12, seconds: 15, milliseconds: 340), target._options.InitializationTimeout);
}
else
{
Assert.True(false, "Not the target telementry initializer.");
}
}
[Fact(DisplayName = "Set timeout through configuration works for telemetry initializer.")]
public void EnableAppInsightsForKubernetesWithTimeOutSetThroughOptionsOverwritingConfiugure()
{
IServiceCollection services = new ServiceCollection();
IConfiguration config = new ConfigurationBuilder().AddInMemoryCollection(
new Dictionary<string, string>(){
{"a" , "b"},
{"AppInsightsForKubernetes:InitializationTimeout", "3.1:12:15.34"}
}).Build();
services.AddSingleton<IConfiguration>(config);
services = services.AddApplicationInsightsKubernetesEnricher(
applyOptions: option =>
{
option.InitializationTimeout = TimeSpan.FromSeconds(30);
}, kubernetesServiceCollectionBuilder: null, detectKubernetes: () => true, logger: null);
Assert.NotNull(services.FirstOrDefault(sd => sd.ImplementationType == typeof(KubernetesTelemetryInitializer)));
// Replace the IKubeHttpClientSetingsProvider in case the test is not running inside a container.
Assert.NotNull(services.FirstOrDefault(s => s.ServiceType == typeof(IKubeHttpClientSettingsProvider)));
Mock<IKubeHttpClientSettingsProvider> mock = new Mock<IKubeHttpClientSettingsProvider>();
services.Remove(new ServiceDescriptor(typeof(IKubeHttpClientSettingsProvider), typeof(KubeHttpClientSettingsProvider), ServiceLifetime.Singleton));
services.AddSingleton<IKubeHttpClientSettingsProvider>(p => mock.Object);
IServiceProvider serviceProvider = services.BuildServiceProvider();
ITelemetryInitializer targetTelemetryInitializer = serviceProvider.GetServices<ITelemetryInitializer>().FirstOrDefault(ti => ti is KubernetesTelemetryInitializer);
if (targetTelemetryInitializer is KubernetesTelemetryInitializer target)
{
Assert.StrictEqual(TimeSpan.FromSeconds(30), target._options.InitializationTimeout);
}
else
{
Assert.True(false, "Not the target telementry initializer.");
}
}
[Fact(DisplayName = "Support adding KubernetesTelemetryInitializer to given TelemetryConfiguration")]
public void AddTheInitializerToGivenConfiguration()
{
@ -45,6 +181,8 @@ namespace Microsoft.ApplicationInsights.Netcore.Kubernetes
Mock<IKubernetesServiceCollectionBuilder> serviceCollectionBuilderMock = new Mock<IKubernetesServiceCollectionBuilder>();
ServiceCollection sc = new ServiceCollection();
sc.AddLogging();
sc.AddOptions();
sc.Configure<AppInsightsForKubernetesOptions>(options => options.InitializationTimeout = TimeSpan.FromSeconds(5));
sc.AddSingleton<ITelemetryInitializer>(p =>
{
@ -52,16 +190,23 @@ namespace Microsoft.ApplicationInsights.Netcore.Kubernetes
envMock.Setup(env => env.ContainerID).Returns("Cid");
var envFactoryMock = new Mock<IK8sEnvironmentFactory>();
envFactoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(envMock.Object, TimeSpan.FromMinutes(1));
return new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(5), SDKVersionUtils.Instance, p.GetService<ILogger<KubernetesTelemetryInitializer>>());
return new KubernetesTelemetryInitializer(
envFactoryMock.Object,
p.GetService<IOptions<AppInsightsForKubernetesOptions>>(),
SDKVersionUtils.Instance,
p.GetService<ILogger<KubernetesTelemetryInitializer>>());
});
serviceCollectionBuilderMock.Setup(b => b.InjectServices(It.IsAny<IServiceCollection>(), It.IsAny<TimeSpan>()))
serviceCollectionBuilderMock.Setup(b => b.InjectServices(It.IsAny<IServiceCollection>()))
.Returns(sc);
TelemetryConfiguration telemetryConfiguration = new TelemetryConfiguration("123", channelMock.Object);
telemetryConfiguration.AddApplicationInsightsKubernetesEnricher(null, serviceCollectionBuilderMock.Object, detectKubernetes: () => true);
telemetryConfiguration.AddApplicationInsightsKubernetesEnricher(
applyOptions: null,
kubernetesServiceCollectionBuilder: serviceCollectionBuilderMock.Object,
detectKubernetes: () => true);
Assert.NotNull(telemetryConfiguration.TelemetryInitializers);
Assert.True(telemetryConfiguration.TelemetryInitializers.Count == 1);
Assert.Single(telemetryConfiguration.TelemetryInitializers);
Assert.True(telemetryConfiguration.TelemetryInitializers.First() is KubernetesTelemetryInitializer);
}
}

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

@ -6,6 +6,7 @@ using Microsoft.ApplicationInsights.Kubernetes.Utilities;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Internal;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
@ -18,7 +19,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
{
Exception ex = Assert.Throws<ArgumentNullException>(() =>
{
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(null, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
null,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
GetLogger());
});
Assert.Equal("Value cannot be null.\r\nParameter name: k8sEnvFactory", ex.Message);
@ -31,7 +36,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
var factoryMock = new Mock<IK8sEnvironmentFactory>();
factoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(() => envMock.Object);
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(factoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
factoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
GetLogger());
Assert.NotNull(target._k8sEnvironment);
Assert.Equal(factoryMock.Object, target._k8sEnvFactory);
@ -46,7 +55,10 @@ namespace Microsoft.ApplicationInsights.Kubernetes
var envFactoryMock = new Mock<IK8sEnvironmentFactory>();
envFactoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(() => envMock.Object);
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
GetLogger());
ITelemetry telemetry = new TraceTelemetry();
target.Initialize(telemetry);
@ -61,7 +73,10 @@ namespace Microsoft.ApplicationInsights.Kubernetes
var envFactoryMock = new Mock<IK8sEnvironmentFactory>();
envFactoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(() => envMock.Object);
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance, GetLogger());
ITelemetry telemetry = new TraceTelemetry();
telemetry.Context.Cloud.RoleName = "Existing RoleName";
target.Initialize(telemetry);
@ -93,7 +108,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
var loggerMock = new Mock<ILogger<KubernetesTelemetryInitializer>>();
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, loggerMock.Object);
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
loggerMock.Object);
ITelemetry telemetry = new TraceTelemetry();
target.Initialize(telemetry);
loggerMock.Verify(l => l.Log(LogLevel.Error, 0, It.IsAny<FormattedLogValues>(), It.IsAny<Exception>(), It.IsAny<Func<object, Exception, string>>()), Times.Never());
@ -123,7 +142,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
var loggerMock = new Mock<ILogger<KubernetesTelemetryInitializer>>();
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, loggerMock.Object);
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
loggerMock.Object);
ITelemetry telemetry = new TraceTelemetry();
target.Initialize(telemetry);
loggerMock.Verify(l => l.Log(LogLevel.Error, 0, It.IsAny<FormattedLogValues>(), It.IsAny<Exception>(), It.IsAny<Func<object, Exception, string>>()), Times.Exactly(2));
@ -150,7 +173,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
var envFactoryMock = new Mock<IK8sEnvironmentFactory>();
envFactoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(() => envMock.Object);
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
GetLogger());
ITelemetry telemetry = new TraceTelemetry();
target.Initialize(telemetry);
@ -184,7 +211,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
var envFactoryMock = new Mock<IK8sEnvironmentFactory>();
envFactoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(() => envMock.Object);
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
GetLogger());
ITelemetry telemetry = new TraceTelemetry();
telemetry.Context.Properties["K8s.Container.ID"] = "Existing Cid";
target.Initialize(telemetry);
@ -199,7 +230,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
envMock.Setup(env => env.ContainerID).Returns("Cid");
var envFactoryMock = new Mock<IK8sEnvironmentFactory>();
envFactoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(envMock.Object, TimeSpan.FromMinutes(1));
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
GetLogger());
ITelemetry telemetry = new TraceTelemetry();
telemetry.Context.Properties["K8s.Container.ID"] = "No Crash";
@ -215,8 +250,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
envMock.Setup(env => env.ContainerID).Returns("Cid");
var envFactoryMock = new Mock<IK8sEnvironmentFactory>();
envFactoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(envMock.Object, TimeSpan.FromMinutes(1));
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(1), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(1)),
SDKVersionUtils.Instance,
GetLogger());
Assert.False(target._isK8sQueryTimeout);
await Task.Delay(TimeSpan.FromSeconds(1));
Assert.True(target._isK8sQueryTimeout);
@ -229,7 +267,11 @@ namespace Microsoft.ApplicationInsights.Kubernetes
envMock.Setup(env => env.ContainerID).Returns("Cid");
var envFactoryMock = new Mock<IK8sEnvironmentFactory>();
envFactoryMock.Setup(f => f.CreateAsync(It.IsAny<DateTime>())).ReturnsAsync(envMock.Object, TimeSpan.FromMinutes(1));
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(envFactoryMock.Object, TimeSpan.FromSeconds(30), SDKVersionUtils.Instance, GetLogger());
KubernetesTelemetryInitializer target = new KubernetesTelemetryInitializer(
envFactoryMock.Object,
GetOptions(TimeSpan.FromSeconds(30)),
SDKVersionUtils.Instance,
GetLogger());
// K8s Enviornment is still null.
Assert.Null(target._k8sEnvironment);
@ -254,5 +296,13 @@ namespace Microsoft.ApplicationInsights.Kubernetes
serviceCollection.AddLogging();
return serviceCollection.BuildServiceProvider();
}
private IOptions<AppInsightsForKubernetesOptions> GetOptions(TimeSpan timeout)
{
return new OptionsWrapper<AppInsightsForKubernetesOptions>(new AppInsightsForKubernetesOptions()
{
InitializationTimeout = timeout,
});
}
}
}