@page "/monitor-dlq" @using System.Timers @using Amazon.Lambda.TestTool.Runtime @using Amazon.Lambda.TestTool.BlazorTester.Models @implements IDisposable @inject LocalLambdaOptions LambdaOptions @inject IModalService Modal

Monitor Dead Letter Queue

An Amazon SQS queue can be designated as the dead letter queue for a Lambda function. When Lambda functions fail to handle an asynchronous request, like an Amazon S3 or Amazon DynamoDB Stream event, the failed request is sent to the queue.

When monitoring is enabled the @Constants.PRODUCT_NAME will read the request from the queue and begin executing it within your debugging environment.

@if (this.Logs != null) { @foreach (var log in this.Logs) { @if (string.IsNullOrEmpty(log.Logs) || log.Logs.Length <= MAX_LOG_TABLE_TEXT_LENGTH) { } else { } @if (string.IsNullOrEmpty(log.Error) || log.Error.Length <= MAX_LOG_TABLE_TEXT_LENGTH) { } else { } @if (string.IsNullOrEmpty(log.Event) || log.Event.Length <= MAX_LOG_TABLE_TEXT_LENGTH) { } else { } } }
Time Logs Error Event
@log.ProcessTime@FormatForLogTable(log.Logs)@FormatForLogTable(log.Logs)@FormatForLogTable(log.Error)@FormatForLogTable(log.Error)@FormatForLogTable(log.Event)@FormatForLogTable(log.Event)
@code { const int MAX_LOG_TABLE_TEXT_LENGTH = 50; FunctionPickerComponent _functionPicker; string ErrorMessage { get; set; } DlqMonitor _dlqMonitor; Timer _logRefreshTimer; FunctionPickerComponent FunctionPicker { get => _functionPicker; set { _functionPicker = value; FunctionPicker.OnChangeAsync = this.OnFunctionPickerChange; _ = OnFunctionPickerChange(); } } IList AvailableQueues { get; set; } = new List(); public string SelectedQueueUrl { get; set; } public bool IsRunning { get; set; } IList Logs { get; set; } = new List(); void OnStartMonitoring() { Logs.Clear(); this.ErrorMessage = null; try { var function = this.LambdaOptions.LoadLambdaFuntion(FunctionPicker.ConfigFile, FunctionPicker.FunctionHandler); _dlqMonitor = new DlqMonitor(this.LambdaOptions.LambdaRuntime, function, FunctionPicker.AWSProfile, FunctionPicker.AWSRegion, SelectedQueueUrl); _dlqMonitor.Start(); IsRunning = true; if (_logRefreshTimer != null) { _logRefreshTimer.Dispose(); _logRefreshTimer = null; } _logRefreshTimer = new Timer { Interval = 5000, AutoReset = true }; _logRefreshTimer.Elapsed += RefreshLogs; _logRefreshTimer.Start(); } catch(Exception e) { this.ErrorMessage = "Error starting monitoring: " + e.Message; } this.StateHasChanged(); } void RefreshLogs(object sender, ElapsedEventArgs e) { const int MAX_LOGS = 3; if (_dlqMonitor == null) { return; } var newLogs = _dlqMonitor.FetchNewLogs(); this.Logs = this.Logs.Concat(newLogs).OrderByDescending(x => x.ProcessTime).Take(MAX_LOGS).ToList(); base.InvokeAsync(() => this.StateHasChanged()); } void OnStopMonitoring() { IsRunning = false; _dlqMonitor?.Stop(); _dlqMonitor = null; _logRefreshTimer.Dispose(); _logRefreshTimer = null; } void OnPurgeDlqClick() { var parameters = new ModalParameters(); parameters.Add(ConfirmDialog.PARAMETER_NAME_MESSAGE, "Are you sure you want to delete all messages from the SQS queue?"); Modal.OnClose += OnPurgeDlqClickConfirmed; Modal.Show("Confirm Purging Queue", parameters); } void OnPurgeDlqClickConfirmed(ModalResult result) { Modal.OnClose -= OnPurgeDlqClickConfirmed; if (result.Cancelled) return; Task.Run(async () => { try { await this.LambdaOptions.LambdaRuntime.AWSService.PurgeQueueAsync(FunctionPicker.AWSProfile, FunctionPicker.AWSRegion, SelectedQueueUrl); } catch(Exception e) { this.ErrorMessage = "Error purging messages from queue: " + e.Message; _ = base.InvokeAsync(() => this.StateHasChanged()); } }); } string _lastFetchQueueSettings; async Task OnFunctionPickerChange() { if (string.IsNullOrEmpty(FunctionPicker.AWSProfile) || string.IsNullOrEmpty(FunctionPicker.AWSRegion)) { _lastFetchQueueSettings = ""; AvailableQueues.Clear(); this.StateHasChanged(); return; } var fetchQueueSettings = $"profile={FunctionPicker.AWSProfile},region={FunctionPicker.AWSRegion}"; if (!string.Equals(_lastFetchQueueSettings, fetchQueueSettings)) { _lastFetchQueueSettings = fetchQueueSettings; this.ErrorMessage = null; this.SelectedQueueUrl = null; try { var queueUrls = await this.LambdaOptions.LambdaRuntime.AWSService.ListQueuesAsync(FunctionPicker.AWSProfile, FunctionPicker.AWSRegion); AvailableQueues.Clear(); foreach (var queueUrl in queueUrls) { AvailableQueues.Add(new QueueItem { QueueUrl = queueUrl }); } if (AvailableQueues.Count > 0) { SelectedQueueUrl = AvailableQueues[0].QueueUrl; } } catch(Exception e) { this.ErrorMessage = "Error listing queues: " + e.Message; } this.StateHasChanged(); } } string FormatForLogTable(string text) { if (text == null) return string.Empty; text = text.Replace("\n", "").Replace("\r", ""); if (text.Length > MAX_LOG_TABLE_TEXT_LENGTH) text = text.Substring(0, MAX_LOG_TABLE_TEXT_LENGTH); return text; } void ShowExpandedText(string text) { var parameters = new ModalParameters(); parameters.Add(ExpandedTextDialog.PARAMETER_NAME_FULL_TEXT, text); Modal.Show("Full Text", parameters); } public void Dispose() { if (this._logRefreshTimer != null) { this._logRefreshTimer.Dispose(); this._logRefreshTimer = null; } if (this._dlqMonitor != null) { _dlqMonitor.Stop(); _dlqMonitor = null; } } }