Check the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples, to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, please use the search on the homepage.
- ABP Framework version: v2.7.0
- UI type: Angular
- Tiered (MVC) or Identity Server Seperated (Angular): no / Yes
- Exception message and stack trace: N.A
- Steps to reproduce the issue: N.A
Hi,
I need to know how the record get inserted into AbpAuditLogs
and AbpAuditLogActions
as I want to implement a bit customized logging of my own.
How can I implement the same for my own tables or you can say I just want to insert only few Http Status code related data to my own custom table.
How can I do it ?
7 Answer(s)
-
0
Hi,
See https://docs.abp.io/en/abp/latest/Audit-Logging#audit-log-contributors
-
0
Hi,
I have implemented
Serilog.Sinks.AwsCloudWatch
to log my data toAWS-CloudWatch
But the problem is according to the documentations of SeriLog I can log data as per LogEventLevel to the CloudWatch which creates huge amout of unnecessary dataWhat if I want to log only the data which get logged into
AuditLog and AuditLogAction
table from database toAWS-CloudWatch
.Is this possible and how to implement it ?
-
0
Yes you can.
You can custom
AuditingStore
to save auditlog toAWS-CloudWatch
. -
0
Thanks @liangshiwei
It will be very helpfull if u can provide some sample code to demonstrate implementation of custom
AudtingStore
-
0
Hi,
As you said I tried implementing
AudtingStore
. But I was not able to log the data likeAbpAuditLog
.I think I missed out something I got reference from the source code Below is my code , Please help if something is wrong in the implementation[Dependency(TryRegister = true)] public class AWSAuditingStore: IAuditingStore, ISingletonDependency { public ILogger<AWSAuditingStore> Logger { get; set; } public AWSAuditingStore() { Logger = NullLogger<AWSAuditingStore>.Instance; } public Task SaveAsync(AuditLogInfo auditInfo) { Logger.LogInformation("AWSAuditingStore : {0}", auditInfo.ToString()); return Task.FromResult(0); } }
-
0
Hi,
I create a simple implementation, but I don't know about
AWS-CloudWatch
, I hope I can help you.[Dependency(ReplaceServices = true)] [ExposeServices(typeof(IAuditingStore))] public class CustomAuditingStore : AuditingStore { private readonly LogEventBatch _repo = new LogEventBatch(); private readonly IAmazonCloudWatchLogs _client; private int _requestCount = 5; private static readonly Regex InvalidSequenceTokenRegex = new Regex(@"The given sequenceToken is invalid. The next expected sequenceToken is: (\d+)"); public CustomAuditingStore( IAuditLogRepository auditLogRepository, IGuidGenerator guidGenerator, IUnitOfWorkManager unitOfWorkManager, IOptions<AbpAuditingOptions> options) : base(auditLogRepository, guidGenerator, unitOfWorkManager, options) { _client = new AmazonCloudWatchLogsClient(..your config); } public override async Task SaveAsync(AuditLogInfo auditInfo) { AddSingleMessage(JsonConvert.SerializeObject(auditInfo)); await SendMessages(); await base.SaveAsync(auditInfo); } private void AddSingleMessage(string message) { _repo.AddMessage(new InputLogEvent() { Timestamp = DateTime.Now, Message = message, }); } private async Task SendMessages() { try { //Make sure the log events are in the right order. _repo._request.LogEvents.Sort((ev1, ev2) => ev1.Timestamp.CompareTo(ev2.Timestamp)); var response = await _client.PutLogEventsAsync(_repo._request).ConfigureAwait(false); _repo.Reset(response.NextSequenceToken); _requestCount = 5; } catch (InvalidSequenceTokenException ex) { //In case the NextSequenceToken is invalid for the last sent message, a new stream would be //created for the said application. if (_requestCount > 0) { _requestCount--; var regexResult = InvalidSequenceTokenRegex.Match(ex.Message); if (regexResult.Success) { _repo._request.SequenceToken = regexResult.Groups[1].Value; await SendMessages().ConfigureAwait(false); } } } } } /// <summary> /// Class to handle PutLogEvent request and associated parameters. /// Also has the requisite checks to determine when the object is ready for Transmission. /// </summary> public class LogEventBatch { public TimeSpan TimeIntervalBetweenPushes { get; private set; } public int MaxBatchSize { get; private set; } public bool ShouldSendRequest(int maxQueuedEvents) { if (_request.LogEvents.Count == 0) { return false; } if (_nextPushTime < DateTime.UtcNow) { return true; } if (maxQueuedEvents <= _request.LogEvents.Count) { return true; } return false; } int _totalMessageSize { get; set; } DateTime _nextPushTime; public PutLogEventsRequest _request = new PutLogEventsRequest(); public LogEventBatch(string logGroupName, string streamName, int timeIntervalBetweenPushes, int maxBatchSize) { _request.LogGroupName = logGroupName; _request.LogStreamName = streamName; TimeIntervalBetweenPushes = TimeSpan.FromSeconds(timeIntervalBetweenPushes); MaxBatchSize = maxBatchSize; Reset(null); } public LogEventBatch() { } public int CurrentBatchMessageCount { get { return this._request.LogEvents.Count; } } public bool IsEmpty => _request.LogEvents.Count == 0; public bool IsSizeConstraintViolated(string message) { Encoding unicode = Encoding.Unicode; int prospectiveLength = _totalMessageSize + unicode.GetMaxByteCount(message.Length); if (MaxBatchSize < prospectiveLength) return true; return false; } public void AddMessage(InputLogEvent ev) { Encoding unicode = Encoding.Unicode; _totalMessageSize += unicode.GetMaxByteCount(ev.Message.Length); _request.LogEvents.Add(ev); } public void Reset(string SeqToken) { _request.LogEvents.Clear(); _totalMessageSize = 0; _request.SequenceToken = SeqToken; _nextPushTime = DateTime.UtcNow.Add(TimeIntervalBetweenPushes); } }
-
0
Thanks alot @liangshiwei It worked