* Add live server logs Spec Kit plan * Implement live server logs diagnostics module * Add server log sources and redaction hardening * Add diagnostics unit tests * Harden server log hub subscriptions * Secure server log hub permissions * Validate server log filter updates * Add diagnostics logger and source tests * Add diagnostics integration test project * Add multi-source diagnostics provider coverage * Broadcast server log source changes * Document diagnostics server log streaming * Add diagnostics sample host wiring * Record diagnostics validation results * Address server log PR feedback * Rename diagnostics module to server logs * Add server logs shell feature * Make server logs shell options bindable * Accept read wildcard for server logs * Align server logs authorization with API patterns * Update CShells structure and logging levels, add diagnostics module * Rename PostgreSql shell feature classes for consistency * Switch from Sqlite to PostgreSQL for workflow and identity persistence, add QuartzPostgreSql configuration * Refactor server logs into diagnostics structured logs (#7440) * Specify diagnostics structured logs refactor * docs: clarify structured logs spec * docs: plan diagnostics structured logs * docs: add diagnostics structured logs tasks * refactor: rename server logs to diagnostics structured logs * Refactor PostgreSql persistence features to use centralized entity model handler registration. * Refactor EFCore persistence features to centralize entity model handler registration for MySql, Sqlite, and Oracle providers. * Integrate structured logs by renaming server logs, adjusting appsettings, and updating project references. * Switch from PostgreSQL to Sqlite for workflow and identity persistence, update appsettings configuration.
90 lines
3.6 KiB
C#
90 lines
3.6 KiB
C#
using Elsa.Diagnostics.StructuredLogs.Features;
|
|
using CShells.AspNetCore.Features;
|
|
using CShells.FastEndpoints.Features;
|
|
using Elsa.Diagnostics.StructuredLogs.Options;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Options;
|
|
using ShellStructuredLogsFeature = Elsa.Diagnostics.StructuredLogs.ShellFeatures.StructuredLogsFeature;
|
|
|
|
namespace Elsa.Diagnostics.StructuredLogs.IntegrationTests;
|
|
|
|
public class StructuredLogsModuleTests
|
|
{
|
|
[Fact]
|
|
public void StructuredLogsFeature_BelongsToStructuredLogsAssembly()
|
|
{
|
|
Assert.Equal("Elsa.Diagnostics.StructuredLogs", typeof(StructuredLogsFeature).Assembly.GetName().Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void ShellStructuredLogsFeature_BelongsToStructuredLogsAssembly()
|
|
{
|
|
Assert.Equal("Elsa.Diagnostics.StructuredLogs", typeof(ShellStructuredLogsFeature).Assembly.GetName().Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void ShellStructuredLogsFeature_UsesDiagnosticsStructuredLogsFeatureName()
|
|
{
|
|
Assert.Equal("Elsa.Diagnostics.StructuredLogs.ShellFeatures.StructuredLogsFeature", typeof(ShellStructuredLogsFeature).FullName);
|
|
}
|
|
|
|
[Fact]
|
|
public void Readme_SeparatesStructuredLogsFromFutureDiagnosticsModules()
|
|
{
|
|
var readme = File.ReadAllText(FindReadme());
|
|
|
|
Assert.Contains("semantic `ILogger` records only", readme);
|
|
Assert.Contains("future diagnostics console logs module", readme);
|
|
Assert.Contains("future diagnostics OpenTelemetry module", readme);
|
|
}
|
|
|
|
[Fact]
|
|
public void ShellStructuredLogsFeature_RegistersFastEndpointsAndWebEndpointMapping()
|
|
{
|
|
Assert.True(typeof(IFastEndpointsShellFeature).IsAssignableFrom(typeof(ShellStructuredLogsFeature)));
|
|
Assert.True(typeof(IWebShellFeature).IsAssignableFrom(typeof(ShellStructuredLogsFeature)));
|
|
}
|
|
|
|
[Fact]
|
|
public void ShellStructuredLogsFeature_CopiesBindablePropertiesToOptions()
|
|
{
|
|
var feature = new ShellStructuredLogsFeature
|
|
{
|
|
RecentLogCapacity = 123,
|
|
SubscriberChannelCapacity = 45,
|
|
MaxRecentLogQuerySize = 67,
|
|
SourceHeartbeatTimeout = TimeSpan.FromSeconds(89),
|
|
IncludeStructuredLogsInternalLogs = true,
|
|
SensitiveNames = ["credential"],
|
|
SensitiveTextPatterns = ["(?i)credential=([^\\s]+)"]
|
|
};
|
|
var services = new ServiceCollection();
|
|
|
|
feature.ConfigureServices(services);
|
|
|
|
var options = services.BuildServiceProvider().GetRequiredService<IOptions<StructuredLogsOptions>>().Value;
|
|
Assert.Equal(feature.RecentLogCapacity, options.RecentLogCapacity);
|
|
Assert.Equal(feature.SubscriberChannelCapacity, options.SubscriberChannelCapacity);
|
|
Assert.Equal(feature.MaxRecentLogQuerySize, options.MaxRecentLogQuerySize);
|
|
Assert.Equal(feature.SourceHeartbeatTimeout, options.SourceHeartbeatTimeout);
|
|
Assert.Equal(feature.IncludeStructuredLogsInternalLogs, options.IncludeStructuredLogsInternalLogs);
|
|
Assert.Equal(feature.SensitiveNames, options.SensitiveNames);
|
|
Assert.Equal(feature.SensitiveTextPatterns, options.SensitiveTextPatterns);
|
|
}
|
|
|
|
private static string FindReadme()
|
|
{
|
|
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (directory != null)
|
|
{
|
|
var candidate = Path.Combine(directory.FullName, "src", "modules", "Elsa.Diagnostics.StructuredLogs", "README.md");
|
|
if (File.Exists(candidate))
|
|
return candidate;
|
|
|
|
directory = directory.Parent;
|
|
}
|
|
|
|
throw new FileNotFoundException("Could not find the structured logs README.");
|
|
}
|
|
}
|