Browse Source

Merge pull request #1425 from colinin/auditlog-index-template

feat: Use the generic audit log index template
pull/1431/head
yx lin 2 months ago
committed by GitHub
parent
commit
e4ced9e0b2
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 25
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs
  2. 8
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs
  3. 115
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLoggingIndexInitializer.cs
  4. 9
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IAuditLoggingIndexInitializer.cs
  5. 8
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexInitializer.cs
  6. 20
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializerService.cs

25
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs

@ -1,7 +1,12 @@
using LINGYUN.Abp.Elasticsearch;
using Microsoft.Extensions.DependencyInjection;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
@ -11,11 +16,29 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
typeof(AbpJsonModule))]
public class AbpAuditLoggingElasticsearchModule : AbpModule
{
private readonly CancellationTokenSource _cancellationTokenSource = new();
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpAuditLoggingElasticsearchOptions>(configuration.GetSection("AuditLogging:Elasticsearch"));
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context));
}
context.Services.AddHostedService<IndexInitializerService>();
public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
var rootServiceProvider = context.ServiceProvider.GetRequiredService<IRootServiceProvider>();
var initializer = rootServiceProvider.GetRequiredService<IAuditLoggingIndexInitializer>();
await initializer.InitializeAsync(_cancellationTokenSource.Token);
}
public override Task OnApplicationShutdownAsync(ApplicationShutdownContext context)
{
_cancellationTokenSource.Cancel();
return Task.CompletedTask;
}
}

8
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs

@ -7,6 +7,13 @@ public class AbpAuditLoggingElasticsearchOptions
public const string DefaultIndexPrefix = "auditlogging";
public string IndexPrefix { get; set; }
/// <summary>
/// 索引初始化失败抛出异常
/// </summary>
/// <remarks>
/// 默认为: true, 索引初始化失败后应用程序停止运行
/// </remarks>
public bool ThrowIfIndexInitFailed { get; set; }
/// <summary>
/// 是否启用审计日志记录
/// </summary>
public bool IsAuditLogEnabled { get; set; }
@ -27,6 +34,7 @@ public class AbpAuditLoggingElasticsearchOptions
{
IndexPrefix = DefaultIndexPrefix;
IsAuditLogEnabled = true;
ThrowIfIndexInitFailed = true;
AuditLogSettings = new IndexSettings()
{
NumberOfReplicas = 1,

115
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs → aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLoggingIndexInitializer.cs

@ -1,26 +1,30 @@
using Elastic.Clients.Elasticsearch;
using Elastic.Clients.Elasticsearch.Mapping;
using Elastic.Transport.Products.Elasticsearch;
using LINGYUN.Abp.Elasticsearch;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public class IndexInitializer : IIndexInitializer, ISingletonDependency
public class AuditLoggingIndexInitializer : IAuditLoggingIndexInitializer, ISingletonDependency
{
private readonly AbpJsonOptions _jsonOptions;
private readonly AbpAuditLoggingElasticsearchOptions _elasticsearchOptions;
private readonly IIndexNameNormalizer _nameNormalizer;
private readonly IElasticsearchClientFactory _clientFactory;
public ILogger<IndexInitializer> Logger { protected get; set; }
public ILogger<AuditLoggingIndexInitializer> Logger { protected get; set; }
public IndexInitializer(
public AuditLoggingIndexInitializer(
IOptions<AbpJsonOptions> jsonOptions,
IOptions<AbpAuditLoggingElasticsearchOptions> elasticsearchOptions,
IIndexNameNormalizer nameNormalizer,
@ -31,29 +35,40 @@ public class IndexInitializer : IIndexInitializer, ISingletonDependency
_nameNormalizer = nameNormalizer;
_clientFactory = clientFactory;
Logger = NullLogger<IndexInitializer>.Instance;
Logger = NullLogger<AuditLoggingIndexInitializer>.Instance;
}
public async virtual Task InitializeAsync()
public async virtual Task InitializeAsync(CancellationToken cancellationToken = default)
{
var client = _clientFactory.Create();
var dateTimeFormat = !_jsonOptions.OutputDateTimeFormat.IsNullOrWhiteSpace()
? $"{_jsonOptions.OutputDateTimeFormat}||strict_date_optional_time||epoch_millis"
: "strict_date_optional_time||epoch_millis";
await InitlizeAuditLogIndex(client, dateTimeFormat);
await InitlizeSecurityLogIndex(client, dateTimeFormat);
await InitlizeAuditLogIndexTemplate(client, dateTimeFormat, cancellationToken);
await InitlizeSecurityLogIndexTemplate(client, dateTimeFormat, cancellationToken);
}
protected async virtual Task InitlizeAuditLogIndex(ElasticsearchClient client, string dateTimeFormat)
protected async virtual Task InitlizeAuditLogIndexTemplate(ElasticsearchClient client, string dateTimeFormat, CancellationToken cancellationToken = default)
{
var indexName = _nameNormalizer.NormalizeIndex("audit-log");
var indexExists = await client.Indices.ExistsAsync(indexName);
if (!indexExists.Exists)
var indexPatterns = new[] { indexName + "-*" };
var indexTemplateName = indexName + "-generic";
var indexTemplateExists = await client.Indices.ExistsIndexTemplateAsync(indexTemplateName, cancellationToken);
if (indexTemplateExists.Exists)
{
return;
}
var putTemplateResponse = await client.Indices.PutIndexTemplateAsync(indexTemplateName, setup =>
{
var indexCreateResponse = await client.Indices.CreateAsync(indexName, c =>
setup.IndexPatterns(indexPatterns);
setup.Priority(100);
setup.Version(1);
setup.Template(template =>
{
c.Settings(_elasticsearchOptions.AuditLogSettings);
c.Mappings(mp => mp
template.Settings(_elasticsearchOptions.AuditLogSettings);
template.Mappings(mp => mp
.Dynamic(DynamicMapping.False)
.Properties<AuditLog>(pd =>
{
@ -128,30 +143,57 @@ public class IndexInitializer : IIndexInitializer, ISingletonDependency
pd.Flattened(f => f.ExtraProperties, f => f.DepthLimit(5).EagerGlobalOrdinals(false));
}));
});
}, cancellationToken);
if (!indexCreateResponse.IsValidResponse)
if (!putTemplateResponse.IsValidResponse)
{
if (indexCreateResponse.TryGetOriginalException(out var ex))
var errorBuilder = new StringBuilder();
if (putTemplateResponse.TryGetOriginalException(out var ex))
{
errorBuilder.AppendLine(ex.Message);
Logger.LogWarning(ex, "Failed to initialize index and audit log may not be retrieved.");
return;
}
Logger.LogWarning("Failed to initialize index and audit log may not be retrieved.");
Logger.LogWarning(indexCreateResponse.DebugInformation);
else if (putTemplateResponse.TryGetElasticsearchServerError(out var error))
{
errorBuilder.AppendLine(error.ToString());
}
else
{
errorBuilder.AppendLine(putTemplateResponse.DebugInformation);
}
if (_elasticsearchOptions.ThrowIfIndexInitFailed)
{
throw new AbpInitializationException($"Failed to initialize audit log index template, the error: {errorBuilder.ToString()}");
}
protected async virtual Task InitlizeSecurityLogIndex(ElasticsearchClient client, string dateTimeFormat)
Logger.LogWarning("Failed to initialize index and audit log may not be retrieved.");
Logger.LogWarning("The error: {error}", errorBuilder.ToString());
}
}
protected async virtual Task InitlizeSecurityLogIndexTemplate(ElasticsearchClient client, string dateTimeFormat, CancellationToken cancellationToken = default)
{
var indexName = _nameNormalizer.NormalizeIndex("security-log");
var indexExists = await client.Indices.ExistsAsync(indexName);
if (!indexExists.Exists)
var indexPatterns = new[] { indexName + "-*" };
var indexTemplateName = indexName + "-generic";
var indexTemplateExists = await client.Indices.ExistsIndexTemplateAsync(indexTemplateName, cancellationToken);
if (indexTemplateExists.Exists)
{
var indexCreateResponse = await client.Indices.CreateAsync(indexName, c =>
return;
}
var putTemplateResponse = await client.Indices.PutIndexTemplateAsync(indexTemplateName, setup =>
{
setup.IndexPatterns(indexPatterns);
setup.Priority(100);
setup.Version(1);
setup.Template(template =>
{
c.Settings(_elasticsearchOptions.SecurityLogSettings);
c.Mappings(mp =>
template.Settings(_elasticsearchOptions.SecurityLogSettings);
template.Mappings(mp =>
{
mp.Dynamic(DynamicMapping.False);
mp.Properties<SecurityLog>(pd =>
@ -173,16 +215,33 @@ public class IndexInitializer : IIndexInitializer, ISingletonDependency
});
});
});
if (!indexCreateResponse.IsValidResponse)
}, cancellationToken);
if (!putTemplateResponse.IsValidResponse)
{
if (indexCreateResponse.TryGetOriginalException(out var ex))
var errorBuilder = new StringBuilder();
if (putTemplateResponse.TryGetOriginalException(out var ex))
{
Logger.LogWarning(ex, "Failed to initialize index and audit log may not be retrieved.");
errorBuilder.AppendLine(ex.Message);
Logger.LogWarning(ex, "Failed to initialize index and security log may not be retrieved.");
return;
}
Logger.LogWarning("Failed to initialize index and audit log may not be retrieved.");
Logger.LogWarning(indexCreateResponse.DebugInformation);
else if (putTemplateResponse.TryGetElasticsearchServerError(out var error))
{
errorBuilder.AppendLine(error.ToString());
}
else
{
errorBuilder.AppendLine(putTemplateResponse.DebugInformation);
}
if (_elasticsearchOptions.ThrowIfIndexInitFailed)
{
throw new AbpInitializationException($"Failed to initialize security log index template, the error: {errorBuilder.ToString()}");
}
Logger.LogWarning("Failed to initialize index and security log may not be retrieved.");
Logger.LogWarning("The error: {error}", errorBuilder.ToString());
}
}
}

9
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IAuditLoggingIndexInitializer.cs

@ -0,0 +1,9 @@
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public interface IAuditLoggingIndexInitializer
{
Task InitializeAsync(CancellationToken cancellationToken = default);
}

8
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexInitializer.cs

@ -1,8 +0,0 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public interface IIndexInitializer
{
Task InitializeAsync();
}

20
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializerService.cs

@ -1,20 +0,0 @@
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public class IndexInitializerService : BackgroundService
{
private readonly IIndexInitializer _indexInitializer;
public IndexInitializerService(IIndexInitializer indexInitializer)
{
_indexInitializer = indexInitializer;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await _indexInitializer.InitializeAsync();
}
}
Loading…
Cancel
Save