-
Notifications
You must be signed in to change notification settings - Fork 367
Expand file tree
/
Copy pathAzureLogAnalyticsTests.cs
More file actions
182 lines (154 loc) · 8.53 KB
/
Copy pathAzureLogAnalyticsTests.cs
File metadata and controls
182 lines (154 loc) · 8.53 KB
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Azure.DataApiBuilder.Config.ObjectModel;
using Azure.DataApiBuilder.Service.Telemetry;
using Azure.Identity;
using Azure.Monitor.Ingestion;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using static Azure.DataApiBuilder.Service.Tests.Configuration.ConfigurationTests;
namespace Azure.DataApiBuilder.Service.Tests.Configuration.Telemetry;
/// <summary>
/// Contains tests for Azure Log Analytics functionality.
/// </summary>
[TestClass, TestCategory(TestCategory.MSSQL)]
public class AzureLogAnalyticsTests
{
public TestContext TestContext { get; set; }
private const string CONFIG_WITH_TELEMETRY = "dab-azure-log-analytics-test-config.json";
private const string CONFIG_WITHOUT_TELEMETRY = "dab-no-azure-log-analytics-test-config.json";
private static RuntimeConfig _configuration;
/// <summary>
/// This is a helper function that creates runtime config file with specified telemetry options.
/// </summary>
/// <param name="configFileName">Name of the config file to be created.</param>
/// <param name="isTelemetryEnabled">Whether telemetry is enabled or not.</param>
/// <param name="telemetryConnectionString">Telemetry connection string.</param>
public static void SetUpTelemetryInConfig(string configFileName, bool isLogAnalyticsEnabled, string logAnalyticsCustomTable, string logAnalyticsDcrImmutableId, string logAnalyticsDceEndpoint)
{
DataSource dataSource = new(DatabaseType.MSSQL,
GetConnectionStringFromEnvironmentConfig(environment: TestCategory.MSSQL), Options: null);
_configuration = InitMinimalRuntimeConfig(dataSource, graphqlOptions: new(), restOptions: new(), mcpOptions: new());
TelemetryOptions _testTelemetryOptions = new(AzureLogAnalytics: new AzureLogAnalyticsOptions(isLogAnalyticsEnabled, new AzureLogAnalyticsAuthOptions(logAnalyticsCustomTable, logAnalyticsDcrImmutableId, logAnalyticsDceEndpoint)));
_configuration = _configuration with { Runtime = _configuration.Runtime with { Telemetry = _testTelemetryOptions } };
File.WriteAllText(configFileName, _configuration.ToJson());
}
/// <summary>
/// Cleans up the test environment by deleting the runtime config with telemetry options.
/// </summary>
[TestCleanup]
public void CleanUpTelemetryConfig()
{
if (File.Exists(CONFIG_WITH_TELEMETRY))
{
File.Delete(CONFIG_WITH_TELEMETRY);
}
if (File.Exists(CONFIG_WITHOUT_TELEMETRY))
{
File.Delete(CONFIG_WITHOUT_TELEMETRY);
}
}
/// <summary>
/// Tests if the services are correctly enabled for Azure Log Analytics.
/// </summary>
[TestMethod]
public void TestAzureLogAnalyticsServicesEnabled()
{
// Arrange
SetUpTelemetryInConfig(CONFIG_WITH_TELEMETRY, true, "Custom-Table-Name-Test", "DCR-Immutable-ID-Test", "https://fake.dce.endpoint");
string[] args = new[]
{
$"--ConfigFileName={CONFIG_WITH_TELEMETRY}"
};
using TestServer server = new(Program.CreateWebHostBuilder(args));
// Additional assertions to check if AzureLogAnalytics is enabled correctly in services
IServiceProvider serviceProvider = server.Services;
AzureLogAnalyticsCustomLogCollector customLogCollector = (AzureLogAnalyticsCustomLogCollector)serviceProvider.GetService<ICustomLogCollector>();
AzureLogAnalyticsFlusherService flusherService = serviceProvider.GetService<AzureLogAnalyticsFlusherService>();
IEnumerable<ILoggerProvider> loggerProvidersServices = serviceProvider.GetServices<ILoggerProvider>();
AzureLogAnalyticsLoggerProvider loggerProvider = loggerProvidersServices.OfType<AzureLogAnalyticsLoggerProvider>().FirstOrDefault();
// If customLogCollector, flusherService, and loggerProvider are not null when AzureLogAnalytics is enabled
Assert.IsNotNull(customLogCollector, "AzureLogAnalyticsCustomLogCollector should be registered.");
Assert.IsNotNull(flusherService, "AzureLogAnalyticsFlusherService should be registered.");
Assert.IsNotNull(loggerProvider, "AzureLogAnalyticsLoggerProvider should be registered.");
}
/// <summary>
/// Tests if the logs are flushed correctly when Azure Log Analytics is enabled.
/// </summary>
[DataTestMethod]
[DataRow("Information Test Message", LogLevel.Information)]
[DataRow("Trace Test Message", LogLevel.Trace)]
[DataRow("Warning Test Message", LogLevel.Warning)]
public async Task TestAzureLogAnalyticsFlushServiceSucceed(string message, LogLevel logLevel)
{
// Arrange
CancellationTokenSource tokenSource = new();
AzureLogAnalyticsOptions azureLogAnalyticsOptions = new(true, new AzureLogAnalyticsAuthOptions("custom-table-name-test", "dcr-immutable-id-test", "https://fake.dce.endpoint"), "DABLogs", 1);
CustomLogsIngestionClient customClient = new(azureLogAnalyticsOptions.Auth.DceEndpoint);
AzureLogAnalyticsCustomLogCollector customLogCollector = new();
ILoggerFactory loggerFactory = new LoggerFactory();
ILogger<Startup> logger = loggerFactory.CreateLogger<Startup>();
AzureLogAnalyticsFlusherService flusherService = new(azureLogAnalyticsOptions, customLogCollector, customClient, logger);
// Act
await customLogCollector.LogAsync(message, logLevel);
_ = Task.Run(() => flusherService.StartAsync(tokenSource.Token));
// Poll until the log appears (the flusher service needs time to dequeue and upload)
int maxWaitMs = 10000;
int pollIntervalMs = 100;
int elapsed = 0;
while (customClient.LogAnalyticsLogs.Count == 0 && elapsed < maxWaitMs)
{
await Task.Delay(pollIntervalMs);
elapsed += pollIntervalMs;
}
// Assert
Assert.IsTrue(customClient.LogAnalyticsLogs.Count > 0, $"Expected at least one log entry after waiting {elapsed}ms, but found none.");
AzureLogAnalyticsLogs actualLog = customClient.LogAnalyticsLogs[0];
Assert.AreEqual(logLevel.ToString(), actualLog.LogLevel);
Assert.AreEqual(message, actualLog.Message);
}
/// <summary>
/// Tests if the services are correctly disabled for Azure Log Analytics.
/// </summary>
[TestMethod]
public void TestAzureLogAnalyticsServicesDisabled()
{
// Arrange
SetUpTelemetryInConfig(CONFIG_WITHOUT_TELEMETRY, false, null, null, null);
string[] args = new[]
{
$"--ConfigFileName={CONFIG_WITHOUT_TELEMETRY}"
};
using TestServer server = new(Program.CreateWebHostBuilder(args));
// Additional assertions to check if Azure Log Analytics is disabled correctly in services
IServiceProvider serviceProvider = server.Services;
AzureLogAnalyticsFlusherService flusherService = serviceProvider.GetService<AzureLogAnalyticsFlusherService>();
AzureLogAnalyticsLoggerProvider loggerProvider = serviceProvider.GetService<AzureLogAnalyticsLoggerProvider>();
// If flusherService and loggerProvider are null, Azure Log Analytics is disabled
Assert.IsNull(flusherService, "AzureLogAnalyticsFlusherService should not be registered.");
Assert.IsNull(loggerProvider, "AzureLogAnalyticsLoggerProvider should not be registered.");
}
/// <summary>
/// Custom logs ingestion to test that all the logs are being sent correctly to Azure Log Analytics
/// </summary>
private class CustomLogsIngestionClient : LogsIngestionClient
{
public List<AzureLogAnalyticsLogs> LogAnalyticsLogs { get; } = new();
public CustomLogsIngestionClient(string dceEndpoint) : base(new Uri(dceEndpoint), new DefaultAzureCredential()) { } // CodeQL [SM05137] DefaultAzureCredential will use Managed Identity if available or fallback to default.
public async override Task<Response> UploadAsync<T>(string ruleId, string streamName, IEnumerable<T> logs, LogsUploadOptions options = null, CancellationToken cancellationToken = default)
{
LogAnalyticsLogs.AddRange(logs.Cast<AzureLogAnalyticsLogs>());
Response mockResponse = Response.FromValue(Mock.Of<Response>(), Mock.Of<Response>());
return await Task.FromResult(mockResponse);
}
}
}