Browse Source

feat(auditlog): Optimize the index of audit logs

pull/1416/head
colin 4 weeks ago
parent
commit
dd68d30558
  1. 41
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs
  2. 52
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs
  3. 27
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs
  4. 116
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs
  5. 2
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChange.cs
  6. 31
      aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChangeTypeConverter.cs
  7. 40
      aspnet-core/framework/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogElasticsearchLoggingManager.cs

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

@ -6,11 +6,48 @@ public class AbpAuditLoggingElasticsearchOptions
{ {
public const string DefaultIndexPrefix = "auditlogging"; public const string DefaultIndexPrefix = "auditlogging";
public string IndexPrefix { get; set; } public string IndexPrefix { get; set; }
public IndexSettings IndexSettings { get; set; } /// <summary>
/// 是否启用审计日志记录
/// </summary>
public bool IsAuditLogEnabled { get; set; }
/// <summary>
/// 审计日志索引设置
/// </summary>
public IndexSettings AuditLogSettings { get; set; }
/// <summary>
/// 是否启用安全日志记录
/// </summary>
public bool IsSecurityLogEnabled { get; set; }
/// <summary>
/// 安全日志索引设置
/// </summary>
public IndexSettings SecurityLogSettings { get; set; }
public AbpAuditLoggingElasticsearchOptions() public AbpAuditLoggingElasticsearchOptions()
{ {
IndexPrefix = DefaultIndexPrefix; IndexPrefix = DefaultIndexPrefix;
IndexSettings = new IndexSettings(); IsAuditLogEnabled = true;
AuditLogSettings = new IndexSettings()
{
NumberOfReplicas = 1,
NumberOfShards = 3,
Mapping = new MappingLimitSettings
{
TotalFields = new MappingLimitSettingsTotalFields
{
Limit = 1000,
},
NestedFields = new MappingLimitSettingsNestedFields
{
Limit = 50,
},
Depth = new MappingLimitSettingsDepth
{
Limit = 10,
},
}
};
IsSecurityLogEnabled = true;
SecurityLogSettings = new IndexSettings();
} }
} }

52
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs

@ -8,8 +8,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Timing; using Volo.Abp.Timing;
@ -21,6 +23,7 @@ public class ElasticsearchAuditLogManager : IAuditLogManager, ITransientDependen
{ {
private readonly AbpAuditingOptions _auditingOptions; private readonly AbpAuditingOptions _auditingOptions;
private readonly AbpElasticsearchOptions _elasticsearchOptions; private readonly AbpElasticsearchOptions _elasticsearchOptions;
private readonly AbpAuditLoggingElasticsearchOptions _loggingEsOptions;
private readonly IIndexNameNormalizer _indexNameNormalizer; private readonly IIndexNameNormalizer _indexNameNormalizer;
private readonly IElasticsearchClientFactory _clientFactory; private readonly IElasticsearchClientFactory _clientFactory;
private readonly IAuditLogInfoToAuditLogConverter _converter; private readonly IAuditLogInfoToAuditLogConverter _converter;
@ -34,7 +37,8 @@ public class ElasticsearchAuditLogManager : IAuditLogManager, ITransientDependen
IOptions<AbpElasticsearchOptions> elasticsearchOptions, IOptions<AbpElasticsearchOptions> elasticsearchOptions,
IElasticsearchClientFactory clientFactory, IElasticsearchClientFactory clientFactory,
IOptions<AbpAuditingOptions> auditingOptions, IOptions<AbpAuditingOptions> auditingOptions,
IAuditLogInfoToAuditLogConverter converter) IAuditLogInfoToAuditLogConverter converter,
IOptionsMonitor<AbpAuditLoggingElasticsearchOptions> loggingEsOptions)
{ {
_clock = clock; _clock = clock;
_converter = converter; _converter = converter;
@ -42,6 +46,7 @@ public class ElasticsearchAuditLogManager : IAuditLogManager, ITransientDependen
_auditingOptions = auditingOptions.Value; _auditingOptions = auditingOptions.Value;
_elasticsearchOptions = elasticsearchOptions.Value; _elasticsearchOptions = elasticsearchOptions.Value;
_indexNameNormalizer = indexNameNormalizer; _indexNameNormalizer = indexNameNormalizer;
_loggingEsOptions = loggingEsOptions.CurrentValue;
Logger = NullLogger<ElasticsearchAuditLogManager>.Instance; Logger = NullLogger<ElasticsearchAuditLogManager>.Instance;
} }
@ -175,7 +180,18 @@ public class ElasticsearchAuditLogManager : IAuditLogManager, ITransientDependen
var response = await client.GetAsync<AuditLog>( var response = await client.GetAsync<AuditLog>(
id.ToString(), id.ToString(),
dsl => dsl.Index(CreateIndex()), dsl =>
{
dsl.Index(CreateIndex());
if (!includeDetails)
{
dsl.SourceExcludes(
ex => ex.Actions,
ex => ex.Comments,
ex => ex.Exceptions,
ex => ex.EntityChanges);
}
},
cancellationToken); cancellationToken);
return response.Source; return response.Source;
@ -209,6 +225,12 @@ public class ElasticsearchAuditLogManager : IAuditLogManager, ITransientDependen
AuditLogInfo auditInfo, AuditLogInfo auditInfo,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
if (!_loggingEsOptions.IsAuditLogEnabled)
{
Logger.LogInformation(auditInfo.ToString());
return "";
}
if (!_auditingOptions.HideErrors) if (!_auditingOptions.HideErrors)
{ {
return await SaveLogAsync(auditInfo, cancellationToken); return await SaveLogAsync(auditInfo, cancellationToken);
@ -244,6 +266,32 @@ public class ElasticsearchAuditLogManager : IAuditLogManager, ITransientDependen
var response = await client.BulkAsync( var response = await client.BulkAsync(
dsl => dsl.Index(CreateIndex()) dsl => dsl.Index(CreateIndex())
.Create(auditLog, ct => ct.Id(auditLog.Id))); .Create(auditLog, ct => ct.Id(auditLog.Id)));
if (!response.IsValidResponse)
{
if (response.TryGetOriginalException(out var ex))
{
throw ex;
}
else if (response.ElasticsearchServerError != null)
{
throw new AbpException(response.ElasticsearchServerError.ToString());
}
else if (response.ItemsWithErrors.Any())
{
var reasonBuilder = new StringBuilder();
foreach (var itemError in response.ItemsWithErrors)
{
if (itemError.Error?.Reason.IsNullOrWhiteSpace() == false)
{
reasonBuilder.AppendLine(itemError.Error.Reason);
}
}
if (reasonBuilder.Length > 0)
{
throw new AbpException(reasonBuilder.ToString());
}
}
}
return response.Items?.FirstOrDefault()?.Id; return response.Items?.FirstOrDefault()?.Id;
} }

27
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs

@ -21,6 +21,7 @@ public class ElasticsearchSecurityLogManager : ISecurityLogManager, ITransientDe
{ {
private readonly AbpSecurityLogOptions _securityLogOptions; private readonly AbpSecurityLogOptions _securityLogOptions;
private readonly AbpElasticsearchOptions _elasticsearchOptions; private readonly AbpElasticsearchOptions _elasticsearchOptions;
private readonly AbpAuditLoggingElasticsearchOptions _loggingEsOptions;
private readonly IIndexNameNormalizer _indexNameNormalizer; private readonly IIndexNameNormalizer _indexNameNormalizer;
private readonly IGuidGenerator _guidGenerator; private readonly IGuidGenerator _guidGenerator;
private readonly IElasticsearchClientFactory _clientFactory; private readonly IElasticsearchClientFactory _clientFactory;
@ -34,7 +35,8 @@ public class ElasticsearchSecurityLogManager : ISecurityLogManager, ITransientDe
IIndexNameNormalizer indexNameNormalizer, IIndexNameNormalizer indexNameNormalizer,
IOptions<AbpSecurityLogOptions> securityLogOptions, IOptions<AbpSecurityLogOptions> securityLogOptions,
IOptions<AbpElasticsearchOptions> elasticsearchOptions, IOptions<AbpElasticsearchOptions> elasticsearchOptions,
IElasticsearchClientFactory clientFactory) IElasticsearchClientFactory clientFactory,
IOptionsMonitor<AbpAuditLoggingElasticsearchOptions> loggingEsOptions)
{ {
_clock = clock; _clock = clock;
_guidGenerator = guidGenerator; _guidGenerator = guidGenerator;
@ -42,6 +44,7 @@ public class ElasticsearchSecurityLogManager : ISecurityLogManager, ITransientDe
_indexNameNormalizer = indexNameNormalizer; _indexNameNormalizer = indexNameNormalizer;
_securityLogOptions = securityLogOptions.Value; _securityLogOptions = securityLogOptions.Value;
_elasticsearchOptions = elasticsearchOptions.Value; _elasticsearchOptions = elasticsearchOptions.Value;
_loggingEsOptions = loggingEsOptions.CurrentValue;
Logger = NullLogger<ElasticsearchSecurityLogManager>.Instance; Logger = NullLogger<ElasticsearchSecurityLogManager>.Instance;
} }
@ -56,17 +59,37 @@ public class ElasticsearchSecurityLogManager : ISecurityLogManager, ITransientDe
return; return;
} }
if (!_loggingEsOptions.IsSecurityLogEnabled)
{
Logger.LogInformation(securityLogInfo.ToString());
return;
}
var client = _clientFactory.Create(); var client = _clientFactory.Create();
var securityLog = new SecurityLog( var securityLog = new SecurityLog(
_guidGenerator.Create(), _guidGenerator.Create(),
securityLogInfo); securityLogInfo);
await client.IndexAsync( var response = await client.IndexAsync(
securityLog, securityLog,
(x) => x.Index(CreateIndex()) (x) => x.Index(CreateIndex())
.Id(securityLog.Id), .Id(securityLog.Id),
cancellationToken); cancellationToken);
if (!response.IsValidResponse)
{
Logger.LogWarning("Could not save the security log object: " + Environment.NewLine + securityLogInfo.ToString());
if (response.TryGetOriginalException(out var ex))
{
Logger.LogWarning(ex, ex.Message);
}
else if (response.ElasticsearchServerError != null)
{
Logger.LogWarning(response.ElasticsearchServerError.ToString());
}
}
} }
public async virtual Task<SecurityLog> GetAsync( public async virtual Task<SecurityLog> GetAsync(

116
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs

@ -52,60 +52,61 @@ public class IndexInitializer : IIndexInitializer, ISingletonDependency
{ {
var indexCreateResponse = await client.Indices.CreateAsync(indexName, c => var indexCreateResponse = await client.Indices.CreateAsync(indexName, c =>
{ {
c.Settings(_elasticsearchOptions.IndexSettings); c.Settings(_elasticsearchOptions.AuditLogSettings);
c.Mappings(mp => mp c.Mappings(mp => mp
.Dynamic(DynamicMapping.False)
.Properties<AuditLog>(pd => .Properties<AuditLog>(pd =>
{ {
pd.Keyword(k => k.Id); pd.Text(k => k.Id, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.ApplicationName); pd.Text(t => t.ApplicationName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(64))));
pd.Keyword(k => k.UserId); pd.Text(k => k.UserId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.UserName); pd.Text(t => t.UserName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.TenantId); pd.Text(k => k.TenantId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.TenantName); pd.Text(t => t.TenantName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(64))));
pd.Keyword(k => k.ImpersonatorUserId); pd.Text(k => k.ImpersonatorUserId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.ImpersonatorUserName); pd.Text(t => t.ImpersonatorUserName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.ImpersonatorTenantId); pd.Text(k => k.ImpersonatorTenantId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.ImpersonatorTenantName); pd.Text(t => t.ImpersonatorTenantName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(64))));
pd.Date(d => d.ExecutionTime, d => d.Format(dateTimeFormat)); pd.Date(d => d.ExecutionTime, d => d.Format(dateTimeFormat));
pd.IntegerNumber(n => n.ExecutionDuration); pd.IntegerNumber(n => n.ExecutionDuration);
pd.Keyword(k => k.ClientIpAddress); pd.Text(k => k.ClientIpAddress, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.ClientName); pd.Text(k => k.ClientName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.ClientId); pd.Text(k => k.ClientId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.CorrelationId); pd.Text(k => k.CorrelationId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(64))));
pd.Keyword(k => k.BrowserInfo); pd.Text(k => k.BrowserInfo, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(512))));
pd.Keyword(k => k.HttpMethod); pd.Text(k => k.HttpMethod, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.Url); pd.Text(k => k.Url, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(1024))));
pd.Keyword(k => k.Exceptions); pd.Text(k => k.Exceptions, p => p.Store(true).Index(false));
pd.Keyword(k => k.Comments); pd.Text(k => k.Comments, p => p.Store(true).Index(false));
pd.IntegerNumber(n => n.HttpStatusCode); pd.IntegerNumber(n => n.HttpStatusCode);
pd.Nested(n => n.EntityChanges, np => pd.Nested(n => n.EntityChanges, np =>
{ {
np.Dynamic(DynamicMapping.False); np.Dynamic(DynamicMapping.False);
np.Properties(npd => np.Properties(npd =>
{ {
npd.Keyword(nameof(EntityChange.Id)); npd.Text(nameof(EntityChange.Id), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
npd.Keyword(nameof(EntityChange.AuditLogId)); npd.Text(nameof(EntityChange.AuditLogId), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
npd.Keyword(nameof(EntityChange.TenantId)); npd.Text(nameof(EntityChange.TenantId), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
npd.Date(nameof(EntityChange.ChangeTime), d => d.Format(dateTimeFormat)); npd.Date(nameof(EntityChange.ChangeTime), d => d.Format(dateTimeFormat));
npd.IntegerNumber(nameof(EntityChange.ChangeType)); npd.ByteNumber(nameof(EntityChange.ChangeType));
npd.Keyword(nameof(EntityChange.EntityTenantId)); npd.Text(nameof(EntityChange.EntityTenantId), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
npd.Keyword(nameof(EntityChange.EntityId)); npd.Text(nameof(EntityChange.EntityId), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(128))));
npd.Keyword(nameof(EntityChange.EntityTypeFullName)); npd.Text(nameof(EntityChange.EntityTypeFullName), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
npd.Nested(nameof(EntityChange.PropertyChanges), pc => npd.Nested(nameof(EntityChange.PropertyChanges), pc =>
{ {
pc.Dynamic(DynamicMapping.False); pc.Dynamic(DynamicMapping.False);
pc.Properties(pcn => pc.Properties(pcn =>
{ {
pcn.Keyword(nameof(EntityPropertyChange.Id)); pcn.Text(nameof(EntityPropertyChange.Id), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pcn.Keyword(nameof(EntityPropertyChange.TenantId)); pcn.Text(nameof(EntityPropertyChange.TenantId), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pcn.Keyword(nameof(EntityPropertyChange.EntityChangeId)); pcn.Text(nameof(EntityPropertyChange.EntityChangeId), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pcn.Keyword(nameof(EntityPropertyChange.NewValue)); pcn.Text(nameof(EntityPropertyChange.NewValue), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pcn.Keyword(nameof(EntityPropertyChange.OriginalValue)); pcn.Text(nameof(EntityPropertyChange.OriginalValue), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pcn.Keyword(nameof(EntityPropertyChange.PropertyName)); pcn.Text(nameof(EntityPropertyChange.PropertyName), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pcn.Keyword(nameof(EntityPropertyChange.PropertyTypeFullName)); pcn.Text(nameof(EntityPropertyChange.PropertyTypeFullName), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
}); });
}); });
npd.Object(nameof(EntityChange.ExtraProperties)); npd.Flattened(nameof(EntityChange.ExtraProperties), f => f.DepthLimit(5).EagerGlobalOrdinals(false));
}); });
}); });
pd.Nested(n => n.Actions, np => pd.Nested(n => n.Actions, np =>
@ -113,18 +114,18 @@ public class IndexInitializer : IIndexInitializer, ISingletonDependency
np.Dynamic(DynamicMapping.False); np.Dynamic(DynamicMapping.False);
np.Properties(npd => np.Properties(npd =>
{ {
npd.Keyword(nameof(AuditLogAction.Id)); npd.Text(nameof(AuditLogAction.Id), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
npd.Keyword(nameof(AuditLogAction.TenantId)); npd.Text(nameof(AuditLogAction.TenantId), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
npd.Keyword(nameof(AuditLogAction.AuditLogId)); npd.Text(nameof(AuditLogAction.AuditLogId), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
npd.Keyword(nameof(AuditLogAction.ServiceName)); npd.Text(nameof(AuditLogAction.ServiceName), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
npd.Keyword(nameof(AuditLogAction.MethodName)); npd.Text(nameof(AuditLogAction.MethodName), p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
npd.Keyword(nameof(AuditLogAction.Parameters)); npd.Text(nameof(AuditLogAction.Parameters), p => p.Store(true).Index(false));
npd.Date(nameof(AuditLogAction.ExecutionTime), d => d.Format(dateTimeFormat)); npd.Date(nameof(AuditLogAction.ExecutionTime), d => d.Format(dateTimeFormat));
npd.IntegerNumber(nameof(AuditLogAction.ExecutionDuration)); npd.IntegerNumber(nameof(AuditLogAction.ExecutionDuration));
npd.Object(nameof(AuditLogAction.ExtraProperties)); npd.Flattened(nameof(AuditLogAction.ExtraProperties), f => f.DepthLimit(5).EagerGlobalOrdinals(false));
}); });
}); });
pd.Object(f => f.ExtraProperties); pd.Flattened(f => f.ExtraProperties, f => f.DepthLimit(5).EagerGlobalOrdinals(false));
})); }));
}); });
@ -149,25 +150,26 @@ public class IndexInitializer : IIndexInitializer, ISingletonDependency
{ {
var indexCreateResponse = await client.Indices.CreateAsync(indexName, c => var indexCreateResponse = await client.Indices.CreateAsync(indexName, c =>
{ {
c.Settings(_elasticsearchOptions.IndexSettings); c.Settings(_elasticsearchOptions.SecurityLogSettings);
c.Mappings(mp => c.Mappings(mp =>
{ {
mp.Dynamic(DynamicMapping.False);
mp.Properties<SecurityLog>(pd => mp.Properties<SecurityLog>(pd =>
{ {
pd.Keyword(k => k.Id); pd.Text(k => k.Id, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.TenantId); pd.Text(k => k.TenantId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.ApplicationName); pd.Text(k => k.ApplicationName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.Identity); pd.Text(k => k.Identity, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.Action); pd.Text(k => k.Action, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.UserId); pd.Text(k => k.UserId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(36))));
pd.Keyword(k => k.UserName); pd.Text(k => k.UserName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(64))));
pd.Keyword(k => k.TenantName); pd.Text(k => k.TenantName, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(64))));
pd.Keyword(k => k.ClientId); pd.Text(k => k.ClientId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.CorrelationId); pd.Text(k => k.CorrelationId, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.ClientIpAddress); pd.Text(k => k.ClientIpAddress, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(256))));
pd.Keyword(k => k.BrowserInfo); pd.Text(k => k.BrowserInfo, p => p.Fields(f => f.Keyword("keyword", k => k.IgnoreAbove(512))));
pd.Date(k => k.CreationTime, d => d.Format(dateTimeFormat)); pd.Date(k => k.CreationTime, d => d.Format(dateTimeFormat));
pd.Object(f => f.ExtraProperties); pd.Flattened(f => f.ExtraProperties, f => f.DepthLimit(5).EagerGlobalOrdinals(false));
}); });
}); });
}); });

2
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChange.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json.Serialization;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.Guids; using Volo.Abp.Guids;
@ -18,6 +19,7 @@ public class EntityChange : IHasExtraProperties
public DateTime ChangeTime { get; set; } public DateTime ChangeTime { get; set; }
[JsonConverter(typeof(EntityChangeTypeConverter))]
public EntityChangeType ChangeType { get; set; } public EntityChangeType ChangeType { get; set; }
public Guid? EntityTenantId { get; set; } public Guid? EntityTenantId { get; set; }

31
aspnet-core/framework/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChangeTypeConverter.cs

@ -0,0 +1,31 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Volo.Abp.Auditing;
namespace LINGYUN.Abp.AuditLogging;
public class EntityChangeTypeConverter : JsonConverter<EntityChangeType>
{
public override EntityChangeType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var stringValue = reader.GetString();
if (int.TryParse(stringValue, out var intValue))
{
return (EntityChangeType)Enum.ToObject(typeof(EntityChangeType), intValue);
}
}
else if (reader.TokenType == JsonTokenType.Number)
{
return (EntityChangeType)Enum.ToObject(typeof(EntityChangeType), reader.GetInt32());
}
throw new JsonException($"Unable to convert value to enum {typeof(EntityChangeType).Name}");
}
public override void Write(Utf8JsonWriter writer, EntityChangeType value, JsonSerializerOptions options)
{
writer.WriteStringValue(Convert.ToInt32(value).ToString());
}
}

40
aspnet-core/framework/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogElasticsearchLoggingManager.cs

@ -293,15 +293,27 @@ public class SerilogElasticsearchLoggingManager : ILoggingManager, ISingletonDep
} }
if (!machineName.IsNullOrWhiteSpace()) if (!machineName.IsNullOrWhiteSpace())
{ {
queries.Add(new TermQuery(GetField(nameof(SerilogInfo.Fields.MachineName)), machineName)); // 模糊匹配
queries.Add(new WildcardQuery(GetField(nameof(SerilogInfo.Fields.MachineName)))
{
Value = $"*{machineName}*"
});
} }
if (!environment.IsNullOrWhiteSpace()) if (!environment.IsNullOrWhiteSpace())
{ {
queries.Add(new TermQuery(GetField(nameof(SerilogInfo.Fields.Environment)), environment)); // 模糊匹配
queries.Add(new WildcardQuery(GetField(nameof(SerilogInfo.Fields.Environment)))
{
Value = $"*{environment}*"
});
} }
if (!application.IsNullOrWhiteSpace()) if (!application.IsNullOrWhiteSpace())
{ {
queries.Add(new TermQuery(GetField(nameof(SerilogInfo.Fields.Application)), application)); // 模糊匹配
queries.Add(new WildcardQuery(GetField(nameof(SerilogInfo.Fields.Application)))
{
Value = $"*{application}*"
});
} }
if (!context.IsNullOrWhiteSpace()) if (!context.IsNullOrWhiteSpace())
{ {
@ -396,19 +408,19 @@ public class SerilogElasticsearchLoggingManager : ILoggingManager, ISingletonDep
private readonly static IDictionary<string, string> _fieldMaps = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) private readonly static IDictionary<string, string> _fieldMaps = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
{ {
{ "timestamp", "@timestamp" }, { "timestamp", "@timestamp" },
{ "level", "level.raw" }, { "level", "level.keyword" },
{ "machinename", $"fields.{AbpLoggingEnricherPropertyNames.MachineName}.raw" }, { "machinename", $"fields.{AbpLoggingEnricherPropertyNames.MachineName}.keyword" },
{ "environment", $"fields.{AbpLoggingEnricherPropertyNames.EnvironmentName}.raw" }, { "environment", $"fields.{AbpLoggingEnricherPropertyNames.EnvironmentName}.keyword" },
{ "application", $"fields.{AbpSerilogEnrichersConsts.ApplicationNamePropertyName}.raw" }, { "application", $"fields.{AbpSerilogEnrichersConsts.ApplicationNamePropertyName}.keyword" },
{ "context", "fields.SourceContext.raw" }, { "context", "fields.SourceContext.keyword" },
{ "actionid", "fields.ActionId.raw" }, { "actionid", "fields.ActionId.keyword" },
{ "actionname", "fields.ActionName.raw" }, { "actionname", "fields.ActionName.keyword" },
{ "requestid", "fields.RequestId.raw" }, { "requestid", "fields.RequestId.keyword" },
{ "requestpath", "fields.RequestPath" }, { "requestpath", "fields.RequestPath" },
{ "connectionid", "fields.ConnectionId" }, { "connectionid", "fields.ConnectionId" },
{ "correlationid", "fields.CorrelationId.raw" }, { "correlationid", "fields.CorrelationId.keyword" },
{ "clientid", "fields.ClientId.raw" }, { "clientid", "fields.ClientId.keyword" },
{ "userid", "fields.UserId.raw" }, { "userid", "fields.UserId.keyword" },
{ "processid", "fields.ProcessId" }, { "processid", "fields.ProcessId" },
{ "threadid", "fields.ThreadId" }, { "threadid", "fields.ThreadId" },
{ "id", $"fields.{AbpSerilogUniqueIdConsts.UniqueIdPropertyName}" }, { "id", $"fields.{AbpSerilogUniqueIdConsts.UniqueIdPropertyName}" },

Loading…
Cancel
Save