/// <summary> /// Logs an error to the application memory. /// </summary> /// <remarks> /// If the log is full then the oldest error entry is removed. /// </remarks> public override string Log(Error error) { if (error == null) { throw new ArgumentNullException(nameof(error)); } // // Make a copy of the error to log since the source is mutable. // Assign a new GUID and create an entry for the error. // error = error.Clone(); error.ApplicationName = ApplicationName; var newId = Guid.NewGuid(); var entry = new ErrorLogEntry(this, newId.ToString(), error); Lock.EnterWriteLock(); try { var entries = _entries ??= new EntryCollection(_size); entries.Add(entry); } finally { Lock.ExitWriteLock(); } return(newId.ToString()); }
private static void RenderError(TextWriter writer, ErrorLogEntry entry, Uri baseUrl) { Debug.Assert(writer != null); Debug.Assert(entry != null); Debug.Assert(baseUrl != null); Debug.Assert(baseUrl.IsAbsoluteUri); var error = entry.Error; writer.Write("<li>"); var errorType = ErrorDisplay.HumaneExceptionErrorType(error); if (errorType.Length > 0) { var abbreviated = errorType.Length < error.Type.Length; if (abbreviated) { writer.Write("<span title='{0}'>", Html.Encode(error.Type).ToHtmlString()); } writer.Write(Html.Encode(errorType).ToHtmlString()); if (abbreviated) { writer.Write("</span>"); } writer.Write(": "); } writer.Write("<a href='{0}'>", Html.Encode(baseUrl + "detail?id=" + Uri.EscapeDataString(entry.Id)).ToHtmlString()); writer.Write(Html.Encode(error.Message).ToHtmlString()); writer.Write("</a>"); writer.Write("</li>"); }
/// <summary> /// Returns a page of errors from the application memory in /// descending order of logged time. /// </summary> public override int GetErrors(int pageIndex, int pageSize, ICollection <ErrorLogEntry> errorEntryList) { if (pageIndex < 0) { throw new ArgumentOutOfRangeException("pageIndex", pageIndex, null); } if (pageSize < 0) { throw new ArgumentOutOfRangeException("pageSize", pageSize, null); } // // To minimize the time for which we hold the lock, we'll first // grab just references to the entries we need to return. Later, // we'll make copies and return those to the caller. Since Error // is mutable, we don't want to return direct references to our // internal versions since someone could change their state. // ErrorLogEntry[] selectedEntries = null; int totalCount; _lock.EnterReadLock(); try { if (_entries == null) { return(0); } totalCount = _entries.Count; var startIndex = totalCount - ((pageIndex + 1) * Math.Min(pageSize, totalCount)); var endIndex = Math.Min(startIndex + pageSize, totalCount); var count = Math.Max(0, endIndex - startIndex); if (count > 0) { selectedEntries = new ErrorLogEntry[count]; var sourceIndex = endIndex; var targetIndex = 0; while (sourceIndex > startIndex) { selectedEntries[targetIndex++] = _entries[--sourceIndex]; } } } finally { _lock.ExitReadLock(); } if (errorEntryList != null && selectedEntries != null) { // // Return copies of fetched entries. If the Error class would // be immutable then this step wouldn't be necessary. // foreach (var entry in selectedEntries) { var error = entry.Error.CloneObject(); errorEntryList.Add(new ErrorLogEntry(this, entry.Id, error)); } } return(totalCount); }
protected void LogException(Exception e, HttpContext context) { if (e == null) { throw new ArgumentNullException(nameof(e)); } // // Fire an event to check if listeners want to filter out // logging of the uncaught exception. // ErrorLogEntry entry = null; try { var args = new ExceptionFilterEventArgs(e, context); if (_filters.Any()) { OnFiltering(args); if (args.Dismissed && !args.DismissedNotifiers.Any()) { return; } } // // Log away... // var error = new Error(e, context); var log = GetErrorLog(context); error.ApplicationName = log.ApplicationName; var id = log.Log(error); entry = new ErrorLogEntry(log, id, error); //Send notification foreach (var notifier in _notifiers) { if (!args.DismissedNotifiers.Any(i => i.Equals(notifier.Name, StringComparison.InvariantCultureIgnoreCase))) { notifier.Notify(error); } } } catch (Exception localException) { // // IMPORTANT! We swallow any exception raised during the // logging and send them out to the trace . The idea // here is that logging of exceptions by itself should not // be critical to the overall operation of the application. // The bad thing is that we catch ANY kind of exception, // even system ones and potentially let them slip by. // _logger.LogError("Elmah local exception", localException); } if (entry != null) { OnLogged(new ErrorLoggedEventArgs(entry)); } }
public ErrorLoggedEventArgs(ErrorLogEntry entry) { _entry = entry ?? throw new ArgumentNullException(nameof(entry)); }