/
ApplicationInsightsExtensions.cs
162 lines (149 loc) · 8.49 KB
/
ApplicationInsightsExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using System;
using System.IO;
using System.Linq;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Kubernetes;
using Microsoft.ApplicationInsights.Kubernetes.Utilities;
using Microsoft.Extensions.Logging;
using static Microsoft.ApplicationInsights.Kubernetes.StringUtils;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extnesion method to inject Kubernetes Telemtry Initializer.
/// </summary>
public static class ApplicationInsightsExtensions
{
/// <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>
public static IServiceCollection AddApplicationInsightsKubernetesEnricher(
this IServiceCollection services,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null)
{
// Inject of the service shall return immediately.
EnableKubernetesImpl(services, detectKubernetes, kubernetesServiceCollectionBuilder, null, timeout);
return services;
}
/// <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>
public static void AddApplicationInsightsKubernetesEnricher(
this TelemetryConfiguration telemetryConfiguration,
TimeSpan? timeout = null,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null,
Func<bool> detectKubernetes = null)
{
IServiceCollection standaloneServiceCollection = new ServiceCollection();
standaloneServiceCollection = EnableKubernetesImpl(standaloneServiceCollection, detectKubernetes, kubernetesServiceCollectionBuilder, null, timeout);
// 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);
if (k8sTelemetryInitializer != null)
{
telemetryConfiguration.TelemetryInitializers.Add(k8sTelemetryInitializer);
}
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 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)
{
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());
}
return serviceCollection;
}
private static IServiceCollection BuildK8sServiceCollection(
IServiceCollection services,
TimeSpan timeout,
Func<bool> detectKubernetes,
ILogger<KubernetesServiceCollectionBuilder> logger,
IKubernetesServiceCollectionBuilder kubernetesServiceCollectionBuilder = null)
{
detectKubernetes = detectKubernetes ?? IsRunningInKubernetes;
kubernetesServiceCollectionBuilder = kubernetesServiceCollectionBuilder ?? new KubernetesServiceCollectionBuilder(detectKubernetes, logger);
services = kubernetesServiceCollectionBuilder.InjectServices(services, timeout);
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>>();
}
}
}