improves error reporting for discord bot

This commit is contained in:
benbierens 2024-10-18 11:03:05 +02:00
parent e29ffe4f9c
commit 9e842207ab
No known key found for this signature in database
GPG Key ID: 877D2C2E09A22F3A
13 changed files with 101 additions and 33 deletions

View File

@ -4,6 +4,7 @@
{
public RewardUsersCommand[] Rewards { get; set; } = Array.Empty<RewardUsersCommand>();
public ChainEventMessage[] EventsOverview { get; set; } = Array.Empty<ChainEventMessage>();
public string[] Errors { get; set; } = Array.Empty<string>();
public bool HasAny()
{

View File

@ -17,6 +17,8 @@ namespace CodexContractsPlugin.ChainMonitor
void OnSlotFilled(RequestEvent requestEvent, EthAddress host, BigInteger slotIndex);
void OnSlotFreed(RequestEvent requestEvent, BigInteger slotIndex);
void OnSlotReservationsFull(RequestEvent requestEvent, BigInteger slotIndex);
void OnError(string msg);
}
public class RequestEvent
@ -67,7 +69,11 @@ namespace CodexContractsPlugin.ChainMonitor
private void Apply(ChainEvents events)
{
if (events.BlockInterval.TimeRange.From < TotalSpan.From)
throw new Exception("Attempt to update ChainState with set of events from before its current record.");
{
var msg = "Attempt to update ChainState with set of events from before its current record.";
handler.OnError(msg);
throw new Exception(msg);
}
log.Log($"ChainState updating: {events.BlockInterval}");
@ -110,7 +116,7 @@ namespace CodexContractsPlugin.ChainMonitor
private void ApplyEvent(RequestFulfilledEventDTO @event)
{
var r = FindRequest(@event.RequestId);
var r = FindRequest(@event);
if (r == null) return;
r.UpdateState(@event.Block.BlockNumber, RequestState.Started);
handler.OnRequestFulfilled(new RequestEvent(@event.Block, r));
@ -118,7 +124,7 @@ namespace CodexContractsPlugin.ChainMonitor
private void ApplyEvent(RequestCancelledEventDTO @event)
{
var r = FindRequest(@event.RequestId);
var r = FindRequest(@event);
if (r == null) return;
r.UpdateState(@event.Block.BlockNumber, RequestState.Cancelled);
handler.OnRequestCancelled(new RequestEvent(@event.Block, r));
@ -126,7 +132,7 @@ namespace CodexContractsPlugin.ChainMonitor
private void ApplyEvent(RequestFailedEventDTO @event)
{
var r = FindRequest(@event.RequestId);
var r = FindRequest(@event);
if (r == null) return;
r.UpdateState(@event.Block.BlockNumber, RequestState.Failed);
handler.OnRequestFailed(new RequestEvent(@event.Block, r));
@ -134,7 +140,7 @@ namespace CodexContractsPlugin.ChainMonitor
private void ApplyEvent(SlotFilledEventDTO @event)
{
var r = FindRequest(@event.RequestId);
var r = FindRequest(@event);
if (r == null) return;
r.Hosts.Add(@event.Host, (int)@event.SlotIndex);
r.Log($"[{@event.Block.BlockNumber}] SlotFilled (host:'{@event.Host}', slotIndex:{@event.SlotIndex})");
@ -143,7 +149,7 @@ namespace CodexContractsPlugin.ChainMonitor
private void ApplyEvent(SlotFreedEventDTO @event)
{
var r = FindRequest(@event.RequestId);
var r = FindRequest(@event);
if (r == null) return;
r.Hosts.RemoveHost((int)@event.SlotIndex);
r.Log($"[{@event.Block.BlockNumber}] SlotFreed (slotIndex:{@event.SlotIndex})");
@ -152,7 +158,7 @@ namespace CodexContractsPlugin.ChainMonitor
private void ApplyEvent(SlotReservationsFullEventDTO @event)
{
var r = FindRequest(@event.RequestId);
var r = FindRequest(@event);
if (r == null) return;
r.Log($"[{@event.Block.BlockNumber}] SlotReservationsFull (slotIndex:{@event.SlotIndex})");
handler.OnSlotReservationsFull(new RequestEvent(@event.Block, r), @event.SlotIndex);
@ -171,10 +177,23 @@ namespace CodexContractsPlugin.ChainMonitor
}
}
private ChainStateRequest? FindRequest(byte[] requestId)
private ChainStateRequest? FindRequest(IHasRequestId request)
{
var r = requests.SingleOrDefault(r => Equal(r.Request.RequestId, requestId));
if (r == null) log.Log("Unable to find request by ID!");
var r = requests.SingleOrDefault(r => Equal(r.Request.RequestId, request.RequestId));
if (r == null)
{
var blockNumber = "unknown";
if (request is IHasBlock blk)
{
blockNumber = blk.Block.BlockNumber.ToString();
}
var msg = $"Received event of type '{request.GetType()}' in block '{blockNumber}' for request by Id: '{request.RequestId}'. " +
$"Failed to find request. Request creation event not seen! (Tracker start time: {TotalSpan.From})";
log.Error(msg);
handler.OnError(msg);
}
return r;
}

View File

@ -1,10 +1,5 @@
using GethPlugin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
namespace CodexContractsPlugin.ChainMonitor
{
@ -56,5 +51,10 @@ namespace CodexContractsPlugin.ChainMonitor
{
foreach (var handler in Handlers) handler.OnSlotReservationsFull(requestEvent, slotIndex);
}
public void OnError(string msg)
{
foreach (var handler in Handlers) handler.OnError(msg);
}
}
}

View File

@ -36,5 +36,9 @@ namespace CodexContractsPlugin.ChainMonitor
public void OnSlotReservationsFull(RequestEvent requestEvent, BigInteger slotIndex)
{
}
public void OnError(string msg)
{
}
}
}

View File

@ -10,7 +10,12 @@ namespace CodexContractsPlugin.Marketplace
BlockTimeEntry Block { get; set; }
}
public partial class Request : RequestBase, IHasBlock
public interface IHasRequestId
{
byte[] RequestId { get; set; }
}
public partial class Request : RequestBase, IHasBlock, IHasRequestId
{
[JsonIgnore]
public BlockTimeEntry Block { get; set; }
@ -28,38 +33,38 @@ namespace CodexContractsPlugin.Marketplace
}
}
public partial class RequestFulfilledEventDTO : IHasBlock
public partial class RequestFulfilledEventDTO : IHasBlock, IHasRequestId
{
[JsonIgnore]
public BlockTimeEntry Block { get; set; }
}
public partial class RequestCancelledEventDTO : IHasBlock
public partial class RequestCancelledEventDTO : IHasBlock, IHasRequestId
{
[JsonIgnore]
public BlockTimeEntry Block { get; set; }
}
public partial class RequestFailedEventDTO : IHasBlock
public partial class RequestFailedEventDTO : IHasBlock, IHasRequestId
{
[JsonIgnore]
public BlockTimeEntry Block { get; set; }
}
public partial class SlotFilledEventDTO : IHasBlock
public partial class SlotFilledEventDTO : IHasBlock, IHasRequestId
{
[JsonIgnore]
public BlockTimeEntry Block { get; set; }
public EthAddress Host { get; set; }
}
public partial class SlotFreedEventDTO : IHasBlock
public partial class SlotFreedEventDTO : IHasBlock, IHasRequestId
{
[JsonIgnore]
public BlockTimeEntry Block { get; set; }
}
public partial class SlotReservationsFullEventDTO : IHasBlock
public partial class SlotReservationsFullEventDTO : IHasBlock, IHasRequestId
{
[JsonIgnore]
public BlockTimeEntry Block { get; set; }

View File

@ -17,8 +17,10 @@ namespace BiblioTech.Rewards
this.eventsChannel = eventsChannel;
}
public async Task ProcessChainEvents(ChainEventMessage[] eventsOverview)
public async Task ProcessChainEvents(ChainEventMessage[] eventsOverview, string[] errors)
{
await SendErrorsToAdminChannel(errors);
if (eventsChannel == null || eventsOverview == null || !eventsOverview.Any()) return;
try
{
@ -34,6 +36,22 @@ namespace BiblioTech.Rewards
}
}
private async Task SendErrorsToAdminChannel(string[] errors)
{
try
{
foreach (var error in errors)
{
await Program.AdminChecker.SendInAdminChannel(error);
}
}
catch (Exception exc)
{
log.Error("Failed to send error messages to admin channel. " + exc);
Environment.Exit(1);
}
}
private async Task SendChainEventsInOrder(ChainEventMessage[] eventsOverview, SocketTextChannel eventsChannel, UserData[] users)
{
eventsOverview = eventsOverview.OrderBy(e => e.BlockNumber).ToArray();

View File

@ -31,7 +31,7 @@ namespace BiblioTech.Rewards
await ProcessRewards(rewards);
}
await eventsSender.ProcessChainEvents(rewards.EventsOverview);
await eventsSender.ProcessChainEvents(rewards.EventsOverview, rewards.Errors);
}
private async Task ProcessRewards(GiveRewardsCommand rewards)

View File

@ -1,6 +1,5 @@
using CodexContractsPlugin;
using CodexContractsPlugin.ChainMonitor;
using Nethereum.Model;
using TestNetRewarder;
using Utils;
@ -40,7 +39,7 @@ namespace MarketInsights
private MarketTimeSegment BuildContribution(TimeRange timeRange)
{
var builder = new ContributionBuilder(timeRange);
var builder = new ContributionBuilder(appState.Log, timeRange);
mux.Handlers.Add(builder);
chainState.Update(timeRange.To);
mux.Handlers.Remove(builder);

View File

@ -1,5 +1,6 @@
using CodexContractsPlugin.ChainMonitor;
using GethPlugin;
using Logging;
using System.Numerics;
using Utils;
@ -8,14 +9,16 @@ namespace MarketInsights
public class ContributionBuilder : IChainStateChangeHandler
{
private readonly MarketTimeSegment segment = new MarketTimeSegment();
private readonly ILog log;
public ContributionBuilder(TimeRange timeRange)
public ContributionBuilder(ILog log, TimeRange timeRange)
{
segment = new MarketTimeSegment
{
FromUtc = timeRange.From,
ToUtc = timeRange.To
};
this.log = log;
}
public void OnNewRequest(RequestEvent requestEvent)
@ -55,6 +58,11 @@ namespace MarketInsights
{
}
public void OnError(string msg)
{
log.Error(msg);
}
public MarketTimeSegment GetSegment()
{
return segment;

View File

@ -12,6 +12,7 @@ namespace TestNetRewarder
{
private static readonly string nl = Environment.NewLine;
private readonly List<ChainEventMessage> events = new List<ChainEventMessage>();
private readonly List<string> errors = new List<string>();
private readonly EmojiMaps emojiMaps = new EmojiMaps();
public ChainEventMessage[] GetEvents()
@ -21,9 +22,11 @@ namespace TestNetRewarder
return result;
}
public void AddError(string error)
public string[] GetErrors()
{
AddBlock(1, "📢 **Error**", error);
var result = errors.ToArray();
errors.Clear();
return result;
}
public void OnNewRequest(RequestEvent requestEvent)
@ -83,6 +86,11 @@ namespace TestNetRewarder
$"Slot Index: {slotIndex}"
);
}
public void OnError(string msg)
{
errors.Add(msg);
}
private void AddRequestBlock(RequestEvent requestEvent, string eventName, params string[] content)
{

View File

@ -48,7 +48,7 @@ namespace TestNetRewarder
{
var msg = "Exception processing time segment: " + ex;
log.Error(msg);
eventsFormatter.AddError(msg);
eventsFormatter.OnError(msg);
throw;
}
}
@ -58,8 +58,9 @@ namespace TestNetRewarder
var numberOfChainEvents = chainState.Update(timeRange.To);
var events = eventsFormatter.GetEvents();
var errors = eventsFormatter.GetErrors();
var request = builder.Build(events);
var request = builder.Build(events, errors);
if (request.HasAny())
{
await client.SendRewards(request);

View File

@ -19,7 +19,7 @@ namespace TestNetRewarder
}
}
public GiveRewardsCommand Build(ChainEventMessage[] lines)
public GiveRewardsCommand Build(ChainEventMessage[] lines, string[] errors)
{
var result = new GiveRewardsCommand
{
@ -28,7 +28,8 @@ namespace TestNetRewarder
RewardId = p.Key,
UserAddresses = p.Value.Select(v => v.Address).ToArray()
}).ToArray(),
EventsOverview = lines
EventsOverview = lines,
Errors = errors
};
rewards.Clear();

View File

@ -76,6 +76,10 @@ namespace TestNetRewarder
{
}
public void OnError(string msg)
{
}
private void GiveReward(RewardConfig reward, EthAddress receiver)
{
giver.Give(reward, receiver);