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 LINGYUN.Abp.Elasticsearch;
using Microsoft.Extensions.DependencyInjection; 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.Json;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch; namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
@ -11,11 +16,29 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
typeof(AbpJsonModule))] typeof(AbpJsonModule))]
public class AbpAuditLoggingElasticsearchModule : AbpModule public class AbpAuditLoggingElasticsearchModule : AbpModule
{ {
private readonly CancellationTokenSource _cancellationTokenSource = new();
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
var configuration = context.Services.GetConfiguration(); var configuration = context.Services.GetConfiguration();
Configure<AbpAuditLoggingElasticsearchOptions>(configuration.GetSection("AuditLogging:Elasticsearch")); 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 const string DefaultIndexPrefix = "auditlogging";
public string IndexPrefix { get; set; } public string IndexPrefix { get; set; }
/// <summary> /// <summary>
/// 索引初始化失败抛出异常
/// </summary>
/// <remarks>
/// 默认为: true, 索引初始化失败后应用程序停止运行
/// </remarks>
public bool ThrowIfIndexInitFailed { get; set; }
/// <summary>
/// 是否启用审计日志记录 /// 是否启用审计日志记录
/// </summary> /// </summary>
public bool IsAuditLogEnabled { get; set; } public bool IsAuditLogEnabled { get; set; }
@ -27,6 +34,7 @@ public class AbpAuditLoggingElasticsearchOptions
{ {
IndexPrefix = DefaultIndexPrefix; IndexPrefix = DefaultIndexPrefix;
IsAuditLogEnabled = true; IsAuditLogEnabled = true;
ThrowIfIndexInitFailed = true;
AuditLogSettings = new IndexSettings() AuditLogSettings = new IndexSettings()
{ {
NumberOfReplicas = 1, 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;
using Elastic.Clients.Elasticsearch.Mapping; using Elastic.Clients.Elasticsearch.Mapping;
using Elastic.Transport.Products.Elasticsearch;
using LINGYUN.Abp.Elasticsearch; using LINGYUN.Abp.Elasticsearch;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Json; using Volo.Abp.Json;
namespace LINGYUN.Abp.AuditLogging.Elasticsearch; namespace LINGYUN.Abp.AuditLogging.Elasticsearch;
public class IndexInitializer : IIndexInitializer, ISingletonDependency public class AuditLoggingIndexInitializer : IAuditLoggingIndexInitializer, ISingletonDependency
{ {
private readonly AbpJsonOptions _jsonOptions; private readonly AbpJsonOptions _jsonOptions;
private readonly AbpAuditLoggingElasticsearchOptions _elasticsearchOptions; private readonly AbpAuditLoggingElasticsearchOptions _elasticsearchOptions;
private readonly IIndexNameNormalizer _nameNormalizer; private readonly IIndexNameNormalizer _nameNormalizer;
private readonly IElasticsearchClientFactory _clientFactory; 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<AbpJsonOptions> jsonOptions,
IOptions<AbpAuditLoggingElasticsearchOptions> elasticsearchOptions, IOptions<AbpAuditLoggingElasticsearchOptions> elasticsearchOptions,
IIndexNameNormalizer nameNormalizer, IIndexNameNormalizer nameNormalizer,
@ -31,29 +35,40 @@ public class IndexInitializer : IIndexInitializer, ISingletonDependency
_nameNormalizer = nameNormalizer; _nameNormalizer = nameNormalizer;
_clientFactory = clientFactory; _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 client = _clientFactory.Create();
var dateTimeFormat = !_jsonOptions.OutputDateTimeFormat.IsNullOrWhiteSpace() var dateTimeFormat = !_jsonOptions.OutputDateTimeFormat.IsNullOrWhiteSpace()
? $"{_jsonOptions.OutputDateTimeFormat}||strict_date_optional_time||epoch_millis" ? $"{_jsonOptions.OutputDateTimeFormat}||strict_date_optional_time||epoch_millis"
: "strict_date_optional_time||epoch_millis"; : "strict_date_optional_time||epoch_millis";
await InitlizeAuditLogIndex(client, dateTimeFormat); await InitlizeAuditLogIndexTemplate(client, dateTimeFormat, cancellationToken);
await InitlizeSecurityLogIndex(client, dateTimeFormat); 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 indexName = _nameNormalizer.NormalizeIndex("audit-log");
var indexExists = await client.Indices.ExistsAsync(indexName); var indexPatterns = new[] { indexName + "-*" };
if (!indexExists.Exists) 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); template.Settings(_elasticsearchOptions.AuditLogSettings);
c.Mappings(mp => mp template.Mappings(mp => mp
.Dynamic(DynamicMapping.False) .Dynamic(DynamicMapping.False)
.Properties<AuditLog>(pd => .Properties<AuditLog>(pd =>
{ {
@ -128,30 +143,57 @@ public class IndexInitializer : IIndexInitializer, ISingletonDependency
pd.Flattened(f => f.ExtraProperties, f => f.DepthLimit(5).EagerGlobalOrdinals(false)); 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."); Logger.LogWarning(ex, "Failed to initialize index and audit log may not be retrieved.");
return; return;
} }
Logger.LogWarning("Failed to initialize index and audit log may not be retrieved."); else if (putTemplateResponse.TryGetElasticsearchServerError(out var error))
Logger.LogWarning(indexCreateResponse.DebugInformation); {
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 indexName = _nameNormalizer.NormalizeIndex("security-log");
var indexExists = await client.Indices.ExistsAsync(indexName); var indexPatterns = new[] { indexName + "-*" };
if (!indexExists.Exists) 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); template.Settings(_elasticsearchOptions.SecurityLogSettings);
c.Mappings(mp => template.Mappings(mp =>
{ {
mp.Dynamic(DynamicMapping.False); mp.Dynamic(DynamicMapping.False);
mp.Properties<SecurityLog>(pd => 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; return;
} }
Logger.LogWarning("Failed to initialize index and audit log may not be retrieved."); else if (putTemplateResponse.TryGetElasticsearchServerError(out var error))
Logger.LogWarning(indexCreateResponse.DebugInformation); {
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